mirror of
				https://github.com/9technologygroup/patchmon.net.git
				synced 2025-11-03 21:43:33 +00:00 
			
		
		
		
	Refactor database model references to use consistent naming conventions and update related queries
This commit is contained in:
		@@ -17,26 +17,29 @@ const authenticateToken = async (req, res, next) => {
 | 
			
		||||
    const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key');
 | 
			
		||||
    
 | 
			
		||||
    // Get user from database
 | 
			
		||||
    const user = await prisma.user.findUnique({
 | 
			
		||||
    const user = await prisma.users.findUnique({
 | 
			
		||||
      where: { id: decoded.userId },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
        email: true,
 | 
			
		||||
        role: true,
 | 
			
		||||
        isActive: true,
 | 
			
		||||
        lastLogin: true
 | 
			
		||||
        is_active: true,
 | 
			
		||||
        last_login: true
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (!user || !user.isActive) {
 | 
			
		||||
    if (!user || !user.is_active) {
 | 
			
		||||
      return res.status(401).json({ error: 'Invalid or inactive user' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update last login
 | 
			
		||||
    await prisma.user.update({
 | 
			
		||||
    await prisma.users.update({
 | 
			
		||||
      where: { id: user.id },
 | 
			
		||||
      data: { lastLogin: new Date() }
 | 
			
		||||
      data: { 
 | 
			
		||||
        last_login: new Date(),
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    req.user = user;
 | 
			
		||||
@@ -69,18 +72,18 @@ const optionalAuth = async (req, res, next) => {
 | 
			
		||||
 | 
			
		||||
    if (token) {
 | 
			
		||||
      const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key');
 | 
			
		||||
      const user = await prisma.user.findUnique({
 | 
			
		||||
      const user = await prisma.users.findUnique({
 | 
			
		||||
        where: { id: decoded.userId },
 | 
			
		||||
        select: {
 | 
			
		||||
          id: true,
 | 
			
		||||
          username: true,
 | 
			
		||||
          email: true,
 | 
			
		||||
          role: true,
 | 
			
		||||
          isActive: true
 | 
			
		||||
          is_active: true
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (user && user.isActive) {
 | 
			
		||||
      if (user && user.is_active) {
 | 
			
		||||
        req.user = user;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ const requirePermission = (permission) => {
 | 
			
		||||
  return async (req, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
      // Get user's role permissions
 | 
			
		||||
      const rolePermissions = await prisma.rolePermissions.findUnique({
 | 
			
		||||
      const rolePermissions = await prisma.role_permissions.findUnique({
 | 
			
		||||
        where: { role: req.user.role }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ const { PrismaClient } = require('@prisma/client');
 | 
			
		||||
const { body, validationResult } = require('express-validator');
 | 
			
		||||
const { authenticateToken, requireAdmin } = require('../middleware/auth');
 | 
			
		||||
const { requireViewUsers, requireManageUsers } = require('../middleware/permissions');
 | 
			
		||||
const { v4: uuidv4 } = require('uuid');
 | 
			
		||||
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
const prisma = new PrismaClient();
 | 
			
		||||
@@ -21,7 +22,7 @@ const generateToken = (userId) => {
 | 
			
		||||
// Admin endpoint to list all users
 | 
			
		||||
router.get('/admin/users', authenticateToken, requireViewUsers, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const users = await prisma.user.findMany({
 | 
			
		||||
    const users = await prisma.users.findMany({
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
@@ -51,7 +52,7 @@ router.post('/admin/users', authenticateToken, requireManageUsers, [
 | 
			
		||||
  body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters'),
 | 
			
		||||
  body('role').optional().custom(async (value) => {
 | 
			
		||||
    if (!value) return true; // Optional field
 | 
			
		||||
    const rolePermissions = await prisma.rolePermissions.findUnique({
 | 
			
		||||
    const rolePermissions = await prisma.role_permissions.findUnique({
 | 
			
		||||
      where: { role: value }
 | 
			
		||||
    });
 | 
			
		||||
    if (!rolePermissions) {
 | 
			
		||||
@@ -69,7 +70,7 @@ router.post('/admin/users', authenticateToken, requireManageUsers, [
 | 
			
		||||
    const { username, email, password, role = 'user' } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if user already exists
 | 
			
		||||
    const existingUser = await prisma.user.findFirst({
 | 
			
		||||
    const existingUser = await prisma.users.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        OR: [
 | 
			
		||||
          { username },
 | 
			
		||||
@@ -86,7 +87,7 @@ router.post('/admin/users', authenticateToken, requireManageUsers, [
 | 
			
		||||
    const passwordHash = await bcrypt.hash(password, 12);
 | 
			
		||||
 | 
			
		||||
    // Create user
 | 
			
		||||
    const user = await prisma.user.create({
 | 
			
		||||
    const user = await prisma.users.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        username,
 | 
			
		||||
        email,
 | 
			
		||||
@@ -119,7 +120,7 @@ router.put('/admin/users/:userId', authenticateToken, requireManageUsers, [
 | 
			
		||||
  body('email').optional().isEmail().withMessage('Valid email is required'),
 | 
			
		||||
  body('role').optional().custom(async (value) => {
 | 
			
		||||
    if (!value) return true; // Optional field
 | 
			
		||||
    const rolePermissions = await prisma.rolePermissions.findUnique({
 | 
			
		||||
    const rolePermissions = await prisma.role_permissions.findUnique({
 | 
			
		||||
      where: { role: value }
 | 
			
		||||
    });
 | 
			
		||||
    if (!rolePermissions) {
 | 
			
		||||
@@ -146,7 +147,7 @@ router.put('/admin/users/:userId', authenticateToken, requireManageUsers, [
 | 
			
		||||
    if (typeof isActive === 'boolean') updateData.isActive = isActive;
 | 
			
		||||
 | 
			
		||||
    // Check if user exists
 | 
			
		||||
    const existingUser = await prisma.user.findUnique({
 | 
			
		||||
    const existingUser = await prisma.users.findUnique({
 | 
			
		||||
      where: { id: userId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +157,7 @@ router.put('/admin/users/:userId', authenticateToken, requireManageUsers, [
 | 
			
		||||
 | 
			
		||||
    // Check if username/email already exists (excluding current user)
 | 
			
		||||
    if (username || email) {
 | 
			
		||||
      const duplicateUser = await prisma.user.findFirst({
 | 
			
		||||
      const duplicateUser = await prisma.users.findFirst({
 | 
			
		||||
        where: {
 | 
			
		||||
          AND: [
 | 
			
		||||
            { id: { not: userId } },
 | 
			
		||||
@@ -177,7 +178,7 @@ router.put('/admin/users/:userId', authenticateToken, requireManageUsers, [
 | 
			
		||||
 | 
			
		||||
    // Prevent deactivating the last admin
 | 
			
		||||
    if (isActive === false && existingUser.role === 'admin') {
 | 
			
		||||
      const adminCount = await prisma.user.count({
 | 
			
		||||
      const adminCount = await prisma.users.count({
 | 
			
		||||
        where: { 
 | 
			
		||||
          role: 'admin',
 | 
			
		||||
          isActive: true
 | 
			
		||||
@@ -190,7 +191,7 @@ router.put('/admin/users/:userId', authenticateToken, requireManageUsers, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update user
 | 
			
		||||
    const updatedUser = await prisma.user.update({
 | 
			
		||||
    const updatedUser = await prisma.users.update({
 | 
			
		||||
      where: { id: userId },
 | 
			
		||||
      data: updateData,
 | 
			
		||||
      select: {
 | 
			
		||||
@@ -226,7 +227,7 @@ router.delete('/admin/users/:userId', authenticateToken, requireManageUsers, asy
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if user exists
 | 
			
		||||
    const user = await prisma.user.findUnique({
 | 
			
		||||
    const user = await prisma.users.findUnique({
 | 
			
		||||
      where: { id: userId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +237,7 @@ router.delete('/admin/users/:userId', authenticateToken, requireManageUsers, asy
 | 
			
		||||
 | 
			
		||||
    // Prevent deleting the last admin
 | 
			
		||||
    if (user.role === 'admin') {
 | 
			
		||||
      const adminCount = await prisma.user.count({
 | 
			
		||||
      const adminCount = await prisma.users.count({
 | 
			
		||||
        where: { 
 | 
			
		||||
          role: 'admin',
 | 
			
		||||
          isActive: true
 | 
			
		||||
@@ -249,7 +250,7 @@ router.delete('/admin/users/:userId', authenticateToken, requireManageUsers, asy
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Delete user
 | 
			
		||||
    await prisma.user.delete({
 | 
			
		||||
    await prisma.users.delete({
 | 
			
		||||
      where: { id: userId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -277,14 +278,14 @@ router.post('/admin/users/:userId/reset-password', authenticateToken, requireMan
 | 
			
		||||
    const { newPassword } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if user exists
 | 
			
		||||
    const user = await prisma.user.findUnique({
 | 
			
		||||
    const user = await prisma.users.findUnique({
 | 
			
		||||
      where: { id: userId },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
        email: true,
 | 
			
		||||
        role: true,
 | 
			
		||||
        isActive: true
 | 
			
		||||
        is_active: true
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -293,7 +294,7 @@ router.post('/admin/users/:userId/reset-password', authenticateToken, requireMan
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prevent resetting password of inactive users
 | 
			
		||||
    if (!user.isActive) {
 | 
			
		||||
    if (!user.is_active) {
 | 
			
		||||
      return res.status(400).json({ error: 'Cannot reset password for inactive user' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -301,7 +302,7 @@ router.post('/admin/users/:userId/reset-password', authenticateToken, requireMan
 | 
			
		||||
    const passwordHash = await bcrypt.hash(newPassword, 12);
 | 
			
		||||
 | 
			
		||||
    // Update user password
 | 
			
		||||
    await prisma.user.update({
 | 
			
		||||
    await prisma.users.update({
 | 
			
		||||
      where: { id: userId },
 | 
			
		||||
      data: { passwordHash }
 | 
			
		||||
    });
 | 
			
		||||
@@ -338,7 +339,7 @@ router.post('/signup', [
 | 
			
		||||
    const { username, email, password } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if user already exists
 | 
			
		||||
    const existingUser = await prisma.user.findFirst({
 | 
			
		||||
    const existingUser = await prisma.users.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        OR: [
 | 
			
		||||
          { username },
 | 
			
		||||
@@ -355,20 +356,22 @@ router.post('/signup', [
 | 
			
		||||
    const passwordHash = await bcrypt.hash(password, 12);
 | 
			
		||||
 | 
			
		||||
    // Create user with default 'user' role
 | 
			
		||||
    const user = await prisma.user.create({
 | 
			
		||||
    const user = await prisma.users.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        id: uuidv4(),
 | 
			
		||||
        username,
 | 
			
		||||
        email,
 | 
			
		||||
        passwordHash,
 | 
			
		||||
        role: 'user'
 | 
			
		||||
        password_hash: passwordHash,
 | 
			
		||||
        role: 'user',
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
        email: true,
 | 
			
		||||
        role: true,
 | 
			
		||||
        isActive: true,
 | 
			
		||||
        createdAt: true
 | 
			
		||||
        is_active: true,
 | 
			
		||||
        created_at: true
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -389,6 +392,8 @@ router.post('/signup', [
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Signup error:', error);
 | 
			
		||||
    console.error('Signup error message:', error.message);
 | 
			
		||||
    console.error('Signup error stack:', error.stack);
 | 
			
		||||
    res.status(500).json({ error: 'Failed to create account' });
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
@@ -407,21 +412,21 @@ router.post('/login', [
 | 
			
		||||
    const { username, password } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Find user by username or email
 | 
			
		||||
    const user = await prisma.user.findFirst({
 | 
			
		||||
    const user = await prisma.users.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        OR: [
 | 
			
		||||
          { username },
 | 
			
		||||
          { email: username }
 | 
			
		||||
        ],
 | 
			
		||||
        isActive: true
 | 
			
		||||
        is_active: true
 | 
			
		||||
      },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
        email: true,
 | 
			
		||||
        passwordHash: true,
 | 
			
		||||
        password_hash: true,
 | 
			
		||||
        role: true,
 | 
			
		||||
        tfaEnabled: true
 | 
			
		||||
        tfa_enabled: true
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -430,13 +435,13 @@ router.post('/login', [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Verify password
 | 
			
		||||
    const isValidPassword = await bcrypt.compare(password, user.passwordHash);
 | 
			
		||||
    const isValidPassword = await bcrypt.compare(password, user.password_hash);
 | 
			
		||||
    if (!isValidPassword) {
 | 
			
		||||
      return res.status(401).json({ error: 'Invalid credentials' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if TFA is enabled
 | 
			
		||||
    if (user.tfaEnabled) {
 | 
			
		||||
    if (user.tfa_enabled) {
 | 
			
		||||
      return res.status(200).json({
 | 
			
		||||
        message: 'TFA verification required',
 | 
			
		||||
        requiresTfa: true,
 | 
			
		||||
@@ -445,9 +450,12 @@ router.post('/login', [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update last login
 | 
			
		||||
    await prisma.user.update({
 | 
			
		||||
    await prisma.users.update({
 | 
			
		||||
      where: { id: user.id },
 | 
			
		||||
      data: { lastLogin: new Date() }
 | 
			
		||||
      data: { 
 | 
			
		||||
        last_login: new Date(),
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Generate token
 | 
			
		||||
@@ -484,22 +492,22 @@ router.post('/verify-tfa', [
 | 
			
		||||
    const { username, token } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Find user
 | 
			
		||||
    const user = await prisma.user.findFirst({
 | 
			
		||||
    const user = await prisma.users.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        OR: [
 | 
			
		||||
          { username },
 | 
			
		||||
          { email: username }
 | 
			
		||||
        ],
 | 
			
		||||
        isActive: true,
 | 
			
		||||
        tfaEnabled: true
 | 
			
		||||
        is_active: true,
 | 
			
		||||
        tfa_enabled: true
 | 
			
		||||
      },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        username: true,
 | 
			
		||||
        email: true,
 | 
			
		||||
        role: true,
 | 
			
		||||
        tfaSecret: true,
 | 
			
		||||
        tfaBackupCodes: true
 | 
			
		||||
        tfa_secret: true,
 | 
			
		||||
        tfa_backup_codes: true
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,8 @@ const prisma = new PrismaClient();
 | 
			
		||||
// Get user's dashboard preferences
 | 
			
		||||
router.get('/', authenticateToken, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const preferences = await prisma.dashboardPreferences.findMany({
 | 
			
		||||
      where: { userId: req.user.id },
 | 
			
		||||
    const preferences = await prisma.dashboard_preferences.findMany({
 | 
			
		||||
      where: { user_id: req.user.id },
 | 
			
		||||
      orderBy: { order: 'asc' }
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
@@ -38,19 +38,21 @@ router.put('/', authenticateToken, [
 | 
			
		||||
    const userId = req.user.id;
 | 
			
		||||
 | 
			
		||||
    // Delete existing preferences for this user
 | 
			
		||||
    await prisma.dashboardPreferences.deleteMany({
 | 
			
		||||
      where: { userId }
 | 
			
		||||
    await prisma.dashboard_preferences.deleteMany({
 | 
			
		||||
      where: { user_id: userId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Create new preferences
 | 
			
		||||
    const newPreferences = preferences.map(pref => ({
 | 
			
		||||
      userId,
 | 
			
		||||
      cardId: pref.cardId,
 | 
			
		||||
      id: require('uuid').v4(),
 | 
			
		||||
      user_id: userId,
 | 
			
		||||
      card_id: pref.cardId,
 | 
			
		||||
      enabled: pref.enabled,
 | 
			
		||||
      order: pref.order
 | 
			
		||||
      order: pref.order,
 | 
			
		||||
      updated_at: new Date()
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    const createdPreferences = await prisma.dashboardPreferences.createMany({
 | 
			
		||||
    const createdPreferences = await prisma.dashboard_preferences.createMany({
 | 
			
		||||
      data: newPreferences
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ router.get('/stats', authenticateToken, requireViewDashboard, async (req, res) =
 | 
			
		||||
    
 | 
			
		||||
    // Get the agent update interval setting
 | 
			
		||||
    const settings = await prisma.settings.findFirst();
 | 
			
		||||
    const updateIntervalMinutes = settings?.updateInterval || 60; // Default to 60 minutes if no setting
 | 
			
		||||
    const updateIntervalMinutes = settings?.update_interval || 60; // Default to 60 minutes if no setting
 | 
			
		||||
    
 | 
			
		||||
    // Calculate the threshold based on the actual update interval
 | 
			
		||||
    // Use 2x the update interval as the threshold for "errored" hosts
 | 
			
		||||
@@ -37,66 +37,66 @@ router.get('/stats', authenticateToken, requireViewDashboard, async (req, res) =
 | 
			
		||||
      updateTrends
 | 
			
		||||
    ] = await Promise.all([
 | 
			
		||||
      // Total hosts count
 | 
			
		||||
      prisma.host.count({
 | 
			
		||||
      prisma.hosts.count({
 | 
			
		||||
        where: { status: 'active' }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Hosts needing updates (distinct hosts with packages needing updates)
 | 
			
		||||
      prisma.host.count({
 | 
			
		||||
      prisma.hosts.count({
 | 
			
		||||
        where: {
 | 
			
		||||
          status: 'active',
 | 
			
		||||
          hostPackages: {
 | 
			
		||||
          host_packages: {
 | 
			
		||||
            some: {
 | 
			
		||||
              needsUpdate: true
 | 
			
		||||
              needs_update: true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Total outdated packages across all hosts
 | 
			
		||||
      prisma.hostPackage.count({
 | 
			
		||||
        where: { needsUpdate: true }
 | 
			
		||||
      prisma.host_packages.count({
 | 
			
		||||
        where: { needs_update: true }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Errored hosts (not updated within threshold based on update interval)
 | 
			
		||||
      prisma.host.count({
 | 
			
		||||
      prisma.hosts.count({
 | 
			
		||||
        where: {
 | 
			
		||||
          status: 'active',
 | 
			
		||||
          lastUpdate: {
 | 
			
		||||
          last_update: {
 | 
			
		||||
            lt: thresholdTime
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Security updates count
 | 
			
		||||
      prisma.hostPackage.count({
 | 
			
		||||
      prisma.host_packages.count({
 | 
			
		||||
        where: {
 | 
			
		||||
          needsUpdate: true,
 | 
			
		||||
          isSecurityUpdate: true
 | 
			
		||||
          needs_update: true,
 | 
			
		||||
          is_security_update: true
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Offline/Stale hosts (not updated within 3x the update interval)
 | 
			
		||||
      prisma.host.count({
 | 
			
		||||
      prisma.hosts.count({
 | 
			
		||||
        where: {
 | 
			
		||||
          status: 'active',
 | 
			
		||||
          lastUpdate: {
 | 
			
		||||
          last_update: {
 | 
			
		||||
            lt: moment(now).subtract(updateIntervalMinutes * 3, 'minutes').toDate()
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // OS distribution for pie chart
 | 
			
		||||
      prisma.host.groupBy({
 | 
			
		||||
        by: ['osType'],
 | 
			
		||||
      prisma.hosts.groupBy({
 | 
			
		||||
        by: ['os_type'],
 | 
			
		||||
        where: { status: 'active' },
 | 
			
		||||
        _count: {
 | 
			
		||||
          osType: true
 | 
			
		||||
          os_type: true
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      // Update trends for the last 7 days
 | 
			
		||||
      prisma.updateHistory.groupBy({
 | 
			
		||||
      prisma.update_history.groupBy({
 | 
			
		||||
        by: ['timestamp'],
 | 
			
		||||
        where: {
 | 
			
		||||
          timestamp: {
 | 
			
		||||
@@ -107,16 +107,16 @@ router.get('/stats', authenticateToken, requireViewDashboard, async (req, res) =
 | 
			
		||||
          id: true
 | 
			
		||||
        },
 | 
			
		||||
        _sum: {
 | 
			
		||||
          packagesCount: true,
 | 
			
		||||
          securityCount: true
 | 
			
		||||
          packages_count: true,
 | 
			
		||||
          security_count: true
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Format OS distribution for pie chart
 | 
			
		||||
    const osDistributionFormatted = osDistribution.map(item => ({
 | 
			
		||||
      name: item.osType,
 | 
			
		||||
      count: item._count.osType
 | 
			
		||||
      name: item.os_type,
 | 
			
		||||
      count: item._count.os_type
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    // Calculate update status distribution
 | 
			
		||||
@@ -158,7 +158,7 @@ router.get('/stats', authenticateToken, requireViewDashboard, async (req, res) =
 | 
			
		||||
// Get hosts with their update status
 | 
			
		||||
router.get('/hosts', authenticateToken, requireViewHosts, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const hosts = await prisma.host.findMany({
 | 
			
		||||
    const hosts = await prisma.hosts.findMany({
 | 
			
		||||
      // Show all hosts regardless of status
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
@@ -194,7 +194,7 @@ router.get('/hosts', authenticateToken, requireViewHosts, async (req, res) => {
 | 
			
		||||
    // Get update counts for each host separately
 | 
			
		||||
    const hostsWithUpdateInfo = await Promise.all(
 | 
			
		||||
      hosts.map(async (host) => {
 | 
			
		||||
        const updatesCount = await prisma.hostPackage.count({
 | 
			
		||||
        const updatesCount = await prisma.host_packages.count({
 | 
			
		||||
          where: {
 | 
			
		||||
            hostId: host.id,
 | 
			
		||||
            needsUpdate: true
 | 
			
		||||
@@ -202,7 +202,7 @@ router.get('/hosts', authenticateToken, requireViewHosts, async (req, res) => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Get total packages count for this host
 | 
			
		||||
        const totalPackagesCount = await prisma.hostPackage.count({
 | 
			
		||||
        const totalPackagesCount = await prisma.host_packages.count({
 | 
			
		||||
          where: {
 | 
			
		||||
            hostId: host.id
 | 
			
		||||
          }
 | 
			
		||||
@@ -210,11 +210,11 @@ router.get('/hosts', authenticateToken, requireViewHosts, async (req, res) => {
 | 
			
		||||
 | 
			
		||||
        // Get the agent update interval setting for stale calculation
 | 
			
		||||
        const settings = await prisma.settings.findFirst();
 | 
			
		||||
        const updateIntervalMinutes = settings?.updateInterval || 60;
 | 
			
		||||
        const updateIntervalMinutes = settings?.update_interval || 60;
 | 
			
		||||
        const thresholdMinutes = updateIntervalMinutes * 2;
 | 
			
		||||
 | 
			
		||||
        // Calculate effective status based on reporting interval
 | 
			
		||||
        const isStale = moment(host.lastUpdate).isBefore(moment().subtract(thresholdMinutes, 'minutes'));
 | 
			
		||||
        const isStale = moment(host.last_update).isBefore(moment().subtract(thresholdMinutes, 'minutes'));
 | 
			
		||||
        let effectiveStatus = host.status;
 | 
			
		||||
        
 | 
			
		||||
        // Override status if host hasn't reported within threshold
 | 
			
		||||
@@ -242,7 +242,7 @@ router.get('/hosts', authenticateToken, requireViewHosts, async (req, res) => {
 | 
			
		||||
// Get packages that need updates across all hosts
 | 
			
		||||
router.get('/packages', authenticateToken, requireViewPackages, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const packages = await prisma.package.findMany({
 | 
			
		||||
    const packages = await prisma.packages.findMany({
 | 
			
		||||
      where: {
 | 
			
		||||
        hostPackages: {
 | 
			
		||||
          some: {
 | 
			
		||||
@@ -282,10 +282,10 @@ router.get('/packages', authenticateToken, requireViewPackages, async (req, res)
 | 
			
		||||
      name: pkg.name,
 | 
			
		||||
      description: pkg.description,
 | 
			
		||||
      category: pkg.category,
 | 
			
		||||
      latestVersion: pkg.latestVersion,
 | 
			
		||||
      affectedHostsCount: pkg.hostPackages.length,
 | 
			
		||||
      isSecurityUpdate: pkg.hostPackages.some(hp => hp.isSecurityUpdate),
 | 
			
		||||
      affectedHosts: pkg.hostPackages.map(hp => ({
 | 
			
		||||
      latestVersion: pkg.latest_version,
 | 
			
		||||
      affectedHostsCount: pkg.host_packages.length,
 | 
			
		||||
      isSecurityUpdate: pkg.host_packages.some(hp => hp.isSecurityUpdate),
 | 
			
		||||
      affectedHosts: pkg.host_packages.map(hp => ({
 | 
			
		||||
        hostId: hp.host.id,
 | 
			
		||||
        friendlyName: hp.host.friendlyName,
 | 
			
		||||
        osType: hp.host.osType,
 | 
			
		||||
@@ -307,7 +307,7 @@ router.get('/hosts/:hostId', authenticateToken, requireViewHosts, async (req, re
 | 
			
		||||
  try {
 | 
			
		||||
    const { hostId } = req.params;
 | 
			
		||||
    
 | 
			
		||||
    const host = await prisma.host.findUnique({
 | 
			
		||||
    const host = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { id: hostId },
 | 
			
		||||
      include: {
 | 
			
		||||
        hostGroup: {
 | 
			
		||||
@@ -341,9 +341,9 @@ router.get('/hosts/:hostId', authenticateToken, requireViewHosts, async (req, re
 | 
			
		||||
    const hostWithStats = {
 | 
			
		||||
      ...host,
 | 
			
		||||
      stats: {
 | 
			
		||||
        totalPackages: host.hostPackages.length,
 | 
			
		||||
        outdatedPackages: host.hostPackages.filter(hp => hp.needsUpdate).length,
 | 
			
		||||
        securityUpdates: host.hostPackages.filter(hp => hp.needsUpdate && hp.isSecurityUpdate).length
 | 
			
		||||
        totalPackages: host.host_packages.length,
 | 
			
		||||
        outdatedPackages: host.host_packages.filter(hp => hp.needsUpdate).length,
 | 
			
		||||
        securityUpdates: host.host_packages.filter(hp => hp.needsUpdate && hp.isSecurityUpdate).length
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ const prisma = new PrismaClient();
 | 
			
		||||
// Get all host groups
 | 
			
		||||
router.get('/', authenticateToken, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const hostGroups = await prisma.hostGroup.findMany({
 | 
			
		||||
    const hostGroups = await prisma.host_groups.findMany({
 | 
			
		||||
      include: {
 | 
			
		||||
        _count: {
 | 
			
		||||
          select: {
 | 
			
		||||
@@ -35,7 +35,7 @@ router.get('/:id', authenticateToken, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const { id } = req.params;
 | 
			
		||||
 | 
			
		||||
    const hostGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
    const hostGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
      where: { id },
 | 
			
		||||
      include: {
 | 
			
		||||
        hosts: {
 | 
			
		||||
@@ -79,7 +79,7 @@ router.post('/', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { name, description, color } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if host group with this name already exists
 | 
			
		||||
    const existingGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
    const existingGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
      where: { name }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -87,7 +87,7 @@ router.post('/', authenticateToken, requireManageHosts, [
 | 
			
		||||
      return res.status(400).json({ error: 'A host group with this name already exists' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const hostGroup = await prisma.hostGroup.create({
 | 
			
		||||
    const hostGroup = await prisma.host_groups.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        name,
 | 
			
		||||
        description: description || null,
 | 
			
		||||
@@ -118,7 +118,7 @@ router.put('/:id', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { name, description, color } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if host group exists
 | 
			
		||||
    const existingGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
    const existingGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
      where: { id }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +127,7 @@ router.put('/:id', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if another host group with this name already exists
 | 
			
		||||
    const duplicateGroup = await prisma.hostGroup.findFirst({
 | 
			
		||||
    const duplicateGroup = await prisma.host_groups.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        name,
 | 
			
		||||
        id: { not: id }
 | 
			
		||||
@@ -138,7 +138,7 @@ router.put('/:id', authenticateToken, requireManageHosts, [
 | 
			
		||||
      return res.status(400).json({ error: 'A host group with this name already exists' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const hostGroup = await prisma.hostGroup.update({
 | 
			
		||||
    const hostGroup = await prisma.host_groups.update({
 | 
			
		||||
      where: { id },
 | 
			
		||||
      data: {
 | 
			
		||||
        name,
 | 
			
		||||
@@ -160,7 +160,7 @@ router.delete('/:id', authenticateToken, requireManageHosts, async (req, res) =>
 | 
			
		||||
    const { id } = req.params;
 | 
			
		||||
 | 
			
		||||
    // Check if host group exists
 | 
			
		||||
    const existingGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
    const existingGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
      where: { id },
 | 
			
		||||
      include: {
 | 
			
		||||
        _count: {
 | 
			
		||||
@@ -182,7 +182,7 @@ router.delete('/:id', authenticateToken, requireManageHosts, async (req, res) =>
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await prisma.hostGroup.delete({
 | 
			
		||||
    await prisma.host_groups.delete({
 | 
			
		||||
      where: { id }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +198,7 @@ router.get('/:id/hosts', authenticateToken, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const { id } = req.params;
 | 
			
		||||
 | 
			
		||||
    const hosts = await prisma.host.findMany({
 | 
			
		||||
    const hosts = await prisma.hosts.findMany({
 | 
			
		||||
      where: { hostGroupId: id },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ router.get('/agent/download', async (req, res) => {
 | 
			
		||||
    
 | 
			
		||||
    if (version) {
 | 
			
		||||
      // Download specific version
 | 
			
		||||
      agentVersion = await prisma.agentVersion.findUnique({
 | 
			
		||||
      agentVersion = await prisma.agent_versions.findUnique({
 | 
			
		||||
        where: { version }
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
@@ -30,16 +30,16 @@ router.get('/agent/download', async (req, res) => {
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      // Download current version (latest)
 | 
			
		||||
      agentVersion = await prisma.agentVersion.findFirst({
 | 
			
		||||
        where: { isCurrent: true },
 | 
			
		||||
        orderBy: { createdAt: 'desc' }
 | 
			
		||||
      agentVersion = await prisma.agent_versions.findFirst({
 | 
			
		||||
        where: { is_current: true },
 | 
			
		||||
        orderBy: { created_at: 'desc' }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (!agentVersion) {
 | 
			
		||||
        // Fallback to default version
 | 
			
		||||
        agentVersion = await prisma.agentVersion.findFirst({
 | 
			
		||||
          where: { isDefault: true },
 | 
			
		||||
          orderBy: { createdAt: 'desc' }
 | 
			
		||||
        agentVersion = await prisma.agent_versions.findFirst({
 | 
			
		||||
          where: { is_default: true },
 | 
			
		||||
          orderBy: { created_at: 'desc' }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -49,10 +49,10 @@ router.get('/agent/download', async (req, res) => {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Use script content from database if available, otherwise fallback to file
 | 
			
		||||
    if (agentVersion.scriptContent) {
 | 
			
		||||
    if (agentVersion.script_content) {
 | 
			
		||||
      res.setHeader('Content-Type', 'application/x-shellscript');
 | 
			
		||||
      res.setHeader('Content-Disposition', `attachment; filename="patchmon-agent-${agentVersion.version}.sh"`);
 | 
			
		||||
      res.send(agentVersion.scriptContent);
 | 
			
		||||
      res.send(agentVersion.script_content);
 | 
			
		||||
    } else {
 | 
			
		||||
      // Fallback to file system
 | 
			
		||||
      const agentPath = path.join(__dirname, '../../../agents/patchmon-agent.sh');
 | 
			
		||||
@@ -74,9 +74,9 @@ router.get('/agent/download', async (req, res) => {
 | 
			
		||||
// Version check endpoint for agents
 | 
			
		||||
router.get('/agent/version', async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const currentVersion = await prisma.agentVersion.findFirst({
 | 
			
		||||
      where: { isCurrent: true },
 | 
			
		||||
      orderBy: { createdAt: 'desc' }
 | 
			
		||||
    const currentVersion = await prisma.agent_versions.findFirst({
 | 
			
		||||
      where: { is_current: true },
 | 
			
		||||
      orderBy: { created_at: 'desc' }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (!currentVersion) {
 | 
			
		||||
@@ -85,9 +85,9 @@ router.get('/agent/version', async (req, res) => {
 | 
			
		||||
 | 
			
		||||
    res.json({
 | 
			
		||||
      currentVersion: currentVersion.version,
 | 
			
		||||
      downloadUrl: currentVersion.downloadUrl || `/api/v1/hosts/agent/download`,
 | 
			
		||||
      releaseNotes: currentVersion.releaseNotes,
 | 
			
		||||
      minServerVersion: currentVersion.minServerVersion
 | 
			
		||||
      downloadUrl: currentVersion.download_url || `/api/v1/hosts/agent/download`,
 | 
			
		||||
      releaseNotes: currentVersion.release_notes,
 | 
			
		||||
      minServerVersion: currentVersion.min_server_version
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Version check error:', error);
 | 
			
		||||
@@ -112,10 +112,10 @@ const validateApiCredentials = async (req, res, next) => {
 | 
			
		||||
      return res.status(401).json({ error: 'API ID and Key required' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const host = await prisma.host.findFirst({
 | 
			
		||||
    const host = await prisma.hosts.findFirst({
 | 
			
		||||
      where: { 
 | 
			
		||||
        apiId: apiId,
 | 
			
		||||
        apiKey: apiKey
 | 
			
		||||
        api_id: apiId,
 | 
			
		||||
        api_key: apiKey
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -148,8 +148,8 @@ router.post('/create', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { apiId, apiKey } = generateApiCredentials();
 | 
			
		||||
    
 | 
			
		||||
    // Check if host already exists
 | 
			
		||||
    const existingHost = await prisma.host.findUnique({
 | 
			
		||||
      where: { friendlyName }
 | 
			
		||||
    const existingHost = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { friendly_name: friendlyName }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (existingHost) {
 | 
			
		||||
@@ -158,7 +158,7 @@ router.post('/create', authenticateToken, requireManageHosts, [
 | 
			
		||||
 | 
			
		||||
    // If hostGroupId is provided, verify the group exists
 | 
			
		||||
    if (hostGroupId) {
 | 
			
		||||
      const hostGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
      const hostGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
        where: { id: hostGroupId }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
@@ -168,20 +168,22 @@ router.post('/create', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create new host with API credentials - system info will be populated when agent connects
 | 
			
		||||
    const host = await prisma.host.create({
 | 
			
		||||
    const host = await prisma.hosts.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        friendlyName,
 | 
			
		||||
        osType: 'unknown', // Will be updated when agent connects
 | 
			
		||||
        osVersion: 'unknown', // Will be updated when agent connects
 | 
			
		||||
        id: uuidv4(),
 | 
			
		||||
        friendly_name: friendlyName,
 | 
			
		||||
        os_type: 'unknown', // Will be updated when agent connects
 | 
			
		||||
        os_version: 'unknown', // Will be updated when agent connects
 | 
			
		||||
        ip: null, // Will be updated when agent connects
 | 
			
		||||
        architecture: null, // Will be updated when agent connects
 | 
			
		||||
        apiId,
 | 
			
		||||
        apiKey,
 | 
			
		||||
        hostGroupId: hostGroupId || null,
 | 
			
		||||
        status: 'pending' // Will change to 'active' when agent connects
 | 
			
		||||
        api_id: apiId,
 | 
			
		||||
        api_key: apiKey,
 | 
			
		||||
        host_group_id: hostGroupId || null,
 | 
			
		||||
        status: 'pending', // Will change to 'active' when agent connects
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      },
 | 
			
		||||
      include: {
 | 
			
		||||
        hostGroup: {
 | 
			
		||||
        host_groups: {
 | 
			
		||||
          select: {
 | 
			
		||||
            id: true,
 | 
			
		||||
            name: true,
 | 
			
		||||
@@ -194,10 +196,10 @@ router.post('/create', authenticateToken, requireManageHosts, [
 | 
			
		||||
    res.status(201).json({
 | 
			
		||||
      message: 'Host created successfully',
 | 
			
		||||
      hostId: host.id,
 | 
			
		||||
      friendlyName: host.friendlyName,
 | 
			
		||||
      apiId: host.apiId,
 | 
			
		||||
      apiKey: host.apiKey,
 | 
			
		||||
      hostGroup: host.hostGroup,
 | 
			
		||||
      friendlyName: host.friendly_name,
 | 
			
		||||
      apiId: host.api_id,
 | 
			
		||||
      apiKey: host.api_key,
 | 
			
		||||
      hostGroup: host.host_groups,
 | 
			
		||||
      instructions: 'Use these credentials in your patchmon agent configuration. System information will be automatically detected when the agent connects.'
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
@@ -250,40 +252,43 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
    const host = req.hostRecord;
 | 
			
		||||
 | 
			
		||||
    // Update host last update timestamp and system info if provided
 | 
			
		||||
    const updateData = { lastUpdate: new Date() };
 | 
			
		||||
    const updateData = { 
 | 
			
		||||
      last_update: new Date(),
 | 
			
		||||
      updated_at: new Date()
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Basic system info
 | 
			
		||||
    if (req.body.osType) updateData.osType = req.body.osType;
 | 
			
		||||
    if (req.body.osVersion) updateData.osVersion = req.body.osVersion;
 | 
			
		||||
    if (req.body.osType) updateData.os_type = req.body.osType;
 | 
			
		||||
    if (req.body.osVersion) updateData.os_version = req.body.osVersion;
 | 
			
		||||
    if (req.body.hostname) updateData.hostname = req.body.hostname;
 | 
			
		||||
    if (req.body.ip) updateData.ip = req.body.ip;
 | 
			
		||||
    if (req.body.architecture) updateData.architecture = req.body.architecture;
 | 
			
		||||
    if (req.body.agentVersion) updateData.agentVersion = req.body.agentVersion;
 | 
			
		||||
    if (req.body.agentVersion) updateData.agent_version = req.body.agentVersion;
 | 
			
		||||
    
 | 
			
		||||
    // Hardware Information
 | 
			
		||||
    if (req.body.cpuModel) updateData.cpuModel = req.body.cpuModel;
 | 
			
		||||
    if (req.body.cpuCores) updateData.cpuCores = req.body.cpuCores;
 | 
			
		||||
    if (req.body.ramInstalled) updateData.ramInstalled = req.body.ramInstalled;
 | 
			
		||||
    if (req.body.swapSize !== undefined) updateData.swapSize = req.body.swapSize;
 | 
			
		||||
    if (req.body.diskDetails) updateData.diskDetails = req.body.diskDetails;
 | 
			
		||||
    if (req.body.cpuModel) updateData.cpu_model = req.body.cpuModel;
 | 
			
		||||
    if (req.body.cpuCores) updateData.cpu_cores = req.body.cpuCores;
 | 
			
		||||
    if (req.body.ramInstalled) updateData.ram_installed = req.body.ramInstalled;
 | 
			
		||||
    if (req.body.swapSize !== undefined) updateData.swap_size = req.body.swapSize;
 | 
			
		||||
    if (req.body.diskDetails) updateData.disk_details = req.body.diskDetails;
 | 
			
		||||
    
 | 
			
		||||
    // Network Information
 | 
			
		||||
    if (req.body.gatewayIp) updateData.gatewayIp = req.body.gatewayIp;
 | 
			
		||||
    if (req.body.dnsServers) updateData.dnsServers = req.body.dnsServers;
 | 
			
		||||
    if (req.body.networkInterfaces) updateData.networkInterfaces = req.body.networkInterfaces;
 | 
			
		||||
    if (req.body.gatewayIp) updateData.gateway_ip = req.body.gatewayIp;
 | 
			
		||||
    if (req.body.dnsServers) updateData.dns_servers = req.body.dnsServers;
 | 
			
		||||
    if (req.body.networkInterfaces) updateData.network_interfaces = req.body.networkInterfaces;
 | 
			
		||||
    
 | 
			
		||||
    // System Information
 | 
			
		||||
    if (req.body.kernelVersion) updateData.kernelVersion = req.body.kernelVersion;
 | 
			
		||||
    if (req.body.selinuxStatus) updateData.selinuxStatus = req.body.selinuxStatus;
 | 
			
		||||
    if (req.body.systemUptime) updateData.systemUptime = req.body.systemUptime;
 | 
			
		||||
    if (req.body.loadAverage) updateData.loadAverage = req.body.loadAverage;
 | 
			
		||||
    if (req.body.kernelVersion) updateData.kernel_version = req.body.kernelVersion;
 | 
			
		||||
    if (req.body.selinuxStatus) updateData.selinux_status = req.body.selinuxStatus;
 | 
			
		||||
    if (req.body.systemUptime) updateData.system_uptime = req.body.systemUptime;
 | 
			
		||||
    if (req.body.loadAverage) updateData.load_average = req.body.loadAverage;
 | 
			
		||||
    
 | 
			
		||||
    // If this is the first update (status is 'pending'), change to 'active'
 | 
			
		||||
    if (host.status === 'pending') {
 | 
			
		||||
      updateData.status = 'active';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await prisma.host.update({
 | 
			
		||||
    await prisma.hosts.update({
 | 
			
		||||
      where: { id: host.id },
 | 
			
		||||
      data: updateData
 | 
			
		||||
    });
 | 
			
		||||
@@ -291,46 +296,52 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
    // Process packages in transaction
 | 
			
		||||
    await prisma.$transaction(async (tx) => {
 | 
			
		||||
      // Clear existing host packages
 | 
			
		||||
      await tx.hostPackage.deleteMany({
 | 
			
		||||
        where: { hostId: host.id }
 | 
			
		||||
      await tx.host_packages.deleteMany({
 | 
			
		||||
        where: { host_id: host.id }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // Process each package
 | 
			
		||||
      for (const packageData of packages) {
 | 
			
		||||
        // Find or create package
 | 
			
		||||
        let pkg = await tx.package.findUnique({
 | 
			
		||||
        let pkg = await tx.packages.findUnique({
 | 
			
		||||
          where: { name: packageData.name }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (!pkg) {
 | 
			
		||||
          pkg = await tx.package.create({
 | 
			
		||||
          pkg = await tx.packages.create({
 | 
			
		||||
            data: {
 | 
			
		||||
              id: uuidv4(),
 | 
			
		||||
              name: packageData.name,
 | 
			
		||||
              description: packageData.description || null,
 | 
			
		||||
              category: packageData.category || null,
 | 
			
		||||
              latestVersion: packageData.availableVersion || packageData.currentVersion
 | 
			
		||||
              latest_version: packageData.availableVersion || packageData.currentVersion,
 | 
			
		||||
              updated_at: new Date()
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          // Update package latest version if newer
 | 
			
		||||
          if (packageData.availableVersion && packageData.availableVersion !== pkg.latestVersion) {
 | 
			
		||||
            await tx.package.update({
 | 
			
		||||
          if (packageData.availableVersion && packageData.availableVersion !== pkg.latest_version) {
 | 
			
		||||
            await tx.packages.update({
 | 
			
		||||
              where: { id: pkg.id },
 | 
			
		||||
              data: { latestVersion: packageData.availableVersion }
 | 
			
		||||
              data: { 
 | 
			
		||||
                latest_version: packageData.availableVersion,
 | 
			
		||||
                updated_at: new Date()
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create host package relationship
 | 
			
		||||
        await tx.hostPackage.create({
 | 
			
		||||
        await tx.host_packages.create({
 | 
			
		||||
          data: {
 | 
			
		||||
            hostId: host.id,
 | 
			
		||||
            packageId: pkg.id,
 | 
			
		||||
            currentVersion: packageData.currentVersion,
 | 
			
		||||
            availableVersion: packageData.availableVersion || null,
 | 
			
		||||
            needsUpdate: packageData.needsUpdate,
 | 
			
		||||
            isSecurityUpdate: packageData.isSecurityUpdate || false,
 | 
			
		||||
            lastChecked: new Date()
 | 
			
		||||
            id: uuidv4(),
 | 
			
		||||
            host_id: host.id,
 | 
			
		||||
            package_id: pkg.id,
 | 
			
		||||
            current_version: packageData.currentVersion,
 | 
			
		||||
            available_version: packageData.availableVersion || null,
 | 
			
		||||
            needs_update: packageData.needsUpdate,
 | 
			
		||||
            is_security_update: packageData.isSecurityUpdate || false,
 | 
			
		||||
            last_checked: new Date()
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
@@ -338,8 +349,8 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
      // Process repositories if provided
 | 
			
		||||
      if (repositories && Array.isArray(repositories)) {
 | 
			
		||||
        // Clear existing host repositories
 | 
			
		||||
        await tx.hostRepository.deleteMany({
 | 
			
		||||
          where: { hostId: host.id }
 | 
			
		||||
        await tx.host_repositories.deleteMany({
 | 
			
		||||
          where: { host_id: host.id }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Deduplicate repositories by URL+distribution+components to avoid constraint violations
 | 
			
		||||
@@ -354,7 +365,7 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
        // Process each unique repository
 | 
			
		||||
        for (const repoData of uniqueRepos.values()) {
 | 
			
		||||
          // Find or create repository
 | 
			
		||||
          let repo = await tx.repository.findFirst({
 | 
			
		||||
          let repo = await tx.repositories.findFirst({
 | 
			
		||||
            where: {
 | 
			
		||||
              url: repoData.url,
 | 
			
		||||
              distribution: repoData.distribution,
 | 
			
		||||
@@ -363,27 +374,30 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          if (!repo) {
 | 
			
		||||
            repo = await tx.repository.create({
 | 
			
		||||
            repo = await tx.repositories.create({
 | 
			
		||||
              data: {
 | 
			
		||||
                id: uuidv4(),
 | 
			
		||||
                name: repoData.name,
 | 
			
		||||
                url: repoData.url,
 | 
			
		||||
                distribution: repoData.distribution,
 | 
			
		||||
                components: repoData.components,
 | 
			
		||||
                repoType: repoData.repoType,
 | 
			
		||||
                isActive: true,
 | 
			
		||||
                isSecure: repoData.isSecure || false,
 | 
			
		||||
                description: `${repoData.repoType} repository for ${repoData.distribution}`
 | 
			
		||||
                repo_type: repoData.repoType,
 | 
			
		||||
                is_active: true,
 | 
			
		||||
                is_secure: repoData.isSecure || false,
 | 
			
		||||
                description: `${repoData.repoType} repository for ${repoData.distribution}`,
 | 
			
		||||
                updated_at: new Date()
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // Create host repository relationship
 | 
			
		||||
          await tx.hostRepository.create({
 | 
			
		||||
          await tx.host_repositories.create({
 | 
			
		||||
            data: {
 | 
			
		||||
              hostId: host.id,
 | 
			
		||||
              repositoryId: repo.id,
 | 
			
		||||
              isEnabled: repoData.isEnabled !== false, // Default to enabled
 | 
			
		||||
              lastChecked: new Date()
 | 
			
		||||
              id: uuidv4(),
 | 
			
		||||
              host_id: host.id,
 | 
			
		||||
              repository_id: repo.id,
 | 
			
		||||
              is_enabled: repoData.isEnabled !== false, // Default to enabled
 | 
			
		||||
              last_checked: new Date()
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
@@ -394,11 +408,12 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
    const securityCount = packages.filter(pkg => pkg.isSecurityUpdate).length;
 | 
			
		||||
    const updatesCount = packages.filter(pkg => pkg.needsUpdate).length;
 | 
			
		||||
 | 
			
		||||
    await prisma.updateHistory.create({
 | 
			
		||||
    await prisma.update_history.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        hostId: host.id,
 | 
			
		||||
        packagesCount: updatesCount,
 | 
			
		||||
        securityCount,
 | 
			
		||||
        id: uuidv4(),
 | 
			
		||||
        host_id: host.id,
 | 
			
		||||
        packages_count: updatesCount,
 | 
			
		||||
        security_count: securityCount,
 | 
			
		||||
        status: 'success'
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
@@ -408,15 +423,15 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
    try {
 | 
			
		||||
      const settings = await prisma.settings.findFirst();
 | 
			
		||||
      // Check both global auto-update setting AND host-specific auto-update setting
 | 
			
		||||
      if (settings && settings.autoUpdate && host.autoUpdate) {
 | 
			
		||||
      if (settings && settings.auto_update && host.auto_update) {
 | 
			
		||||
        // Get current agent version from the request
 | 
			
		||||
        const currentAgentVersion = req.body.agentVersion;
 | 
			
		||||
        
 | 
			
		||||
        if (currentAgentVersion) {
 | 
			
		||||
          // Get the latest agent version
 | 
			
		||||
          const latestAgentVersion = await prisma.agentVersion.findFirst({
 | 
			
		||||
            where: { isCurrent: true },
 | 
			
		||||
            orderBy: { createdAt: 'desc' }
 | 
			
		||||
          const latestAgentVersion = await prisma.agent_versions.findFirst({
 | 
			
		||||
            where: { is_current: true },
 | 
			
		||||
            orderBy: { created_at: 'desc' }
 | 
			
		||||
          });
 | 
			
		||||
          
 | 
			
		||||
          if (latestAgentVersion && latestAgentVersion.version !== currentAgentVersion) {
 | 
			
		||||
@@ -450,7 +465,7 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
 | 
			
		||||
    // Check if crontab update is needed (when update interval changes)
 | 
			
		||||
    // This is a simple check - if the host has auto-update enabled, we'll suggest crontab update
 | 
			
		||||
    if (host.autoUpdate) {
 | 
			
		||||
    if (host.auto_update) {
 | 
			
		||||
      // For now, we'll always suggest crontab update to ensure it's current
 | 
			
		||||
      // In a more sophisticated implementation, we could track when the interval last changed
 | 
			
		||||
      response.crontabUpdate = {
 | 
			
		||||
@@ -466,13 +481,14 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
    
 | 
			
		||||
    // Log error in update history
 | 
			
		||||
    try {
 | 
			
		||||
      await prisma.updateHistory.create({
 | 
			
		||||
      await prisma.update_history.create({
 | 
			
		||||
        data: {
 | 
			
		||||
          hostId: req.hostRecord.id,
 | 
			
		||||
          packagesCount: 0,
 | 
			
		||||
          securityCount: 0,
 | 
			
		||||
          id: uuidv4(),
 | 
			
		||||
          host_id: req.hostRecord.id,
 | 
			
		||||
          packages_count: 0,
 | 
			
		||||
          security_count: 0,
 | 
			
		||||
          status: 'error',
 | 
			
		||||
          errorMessage: error.message
 | 
			
		||||
          error_message: error.message
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    } catch (logError) {
 | 
			
		||||
@@ -486,20 +502,20 @@ router.post('/update', validateApiCredentials, [
 | 
			
		||||
// Get host information (now uses API credentials)
 | 
			
		||||
router.get('/info', validateApiCredentials, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const host = await prisma.host.findUnique({
 | 
			
		||||
    const host = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { id: req.hostRecord.id },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        friendlyName: true,
 | 
			
		||||
        friendly_name: true,
 | 
			
		||||
        hostname: true,
 | 
			
		||||
        ip: true,
 | 
			
		||||
        osType: true,
 | 
			
		||||
        osVersion: true,
 | 
			
		||||
        os_type: true,
 | 
			
		||||
        os_version: true,
 | 
			
		||||
        architecture: true,
 | 
			
		||||
        lastUpdate: true,
 | 
			
		||||
        last_update: true,
 | 
			
		||||
        status: true,
 | 
			
		||||
        createdAt: true,
 | 
			
		||||
        apiId: true // Include API ID for reference
 | 
			
		||||
        created_at: true,
 | 
			
		||||
        api_id: true // Include API ID for reference
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -514,20 +530,23 @@ router.get('/info', validateApiCredentials, async (req, res) => {
 | 
			
		||||
router.post('/ping', validateApiCredentials, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    // Update last update timestamp
 | 
			
		||||
    await prisma.host.update({
 | 
			
		||||
    await prisma.hosts.update({
 | 
			
		||||
      where: { id: req.hostRecord.id },
 | 
			
		||||
      data: { lastUpdate: new Date() }
 | 
			
		||||
      data: { 
 | 
			
		||||
        last_update: new Date(),
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const response = { 
 | 
			
		||||
      message: 'Ping successful',
 | 
			
		||||
      timestamp: new Date().toISOString(),
 | 
			
		||||
      friendlyName: req.hostRecord.friendlyName
 | 
			
		||||
      friendlyName: req.hostRecord.friendly_name
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Check if this is a crontab update trigger
 | 
			
		||||
    if (req.body.triggerCrontabUpdate && req.hostRecord.autoUpdate) {
 | 
			
		||||
      console.log(`Triggering crontab update for host: ${req.hostRecord.friendlyName}`);
 | 
			
		||||
    if (req.body.triggerCrontabUpdate && req.hostRecord.auto_update) {
 | 
			
		||||
      console.log(`Triggering crontab update for host: ${req.hostRecord.friendly_name}`);
 | 
			
		||||
      response.crontabUpdate = {
 | 
			
		||||
        shouldUpdate: true,
 | 
			
		||||
        message: 'Update interval changed, please run: /usr/local/bin/patchmon-agent.sh update-crontab',
 | 
			
		||||
@@ -547,7 +566,7 @@ router.post('/:hostId/regenerate-credentials', authenticateToken, requireManageH
 | 
			
		||||
  try {
 | 
			
		||||
    const { hostId } = req.params;
 | 
			
		||||
    
 | 
			
		||||
    const host = await prisma.host.findUnique({
 | 
			
		||||
    const host = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { id: hostId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -559,16 +578,20 @@ router.post('/:hostId/regenerate-credentials', authenticateToken, requireManageH
 | 
			
		||||
    const { apiId, apiKey } = generateApiCredentials();
 | 
			
		||||
 | 
			
		||||
    // Update host with new credentials
 | 
			
		||||
    const updatedHost = await prisma.host.update({
 | 
			
		||||
    const updatedHost = await prisma.hosts.update({
 | 
			
		||||
      where: { id: hostId },
 | 
			
		||||
      data: { apiId, apiKey }
 | 
			
		||||
      data: { 
 | 
			
		||||
        api_id: apiId, 
 | 
			
		||||
        api_key: apiKey,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.json({
 | 
			
		||||
      message: 'API credentials regenerated successfully',
 | 
			
		||||
      hostname: updatedHost.hostname,
 | 
			
		||||
      apiId: updatedHost.apiId,
 | 
			
		||||
      apiKey: updatedHost.apiKey,
 | 
			
		||||
      apiId: updatedHost.api_id,
 | 
			
		||||
      apiKey: updatedHost.api_key,
 | 
			
		||||
      warning: 'Previous credentials are now invalid. Update your agent configuration.'
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
@@ -593,7 +616,7 @@ router.put('/bulk/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
 | 
			
		||||
    // If hostGroupId is provided, verify the group exists
 | 
			
		||||
    if (hostGroupId) {
 | 
			
		||||
      const hostGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
      const hostGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
        where: { id: hostGroupId }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
@@ -603,9 +626,9 @@ router.put('/bulk/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if all hosts exist
 | 
			
		||||
    const existingHosts = await prisma.host.findMany({
 | 
			
		||||
    const existingHosts = await prisma.hosts.findMany({
 | 
			
		||||
      where: { id: { in: hostIds } },
 | 
			
		||||
      select: { id: true, friendlyName: true }
 | 
			
		||||
      select: { id: true, friendly_name: true }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (existingHosts.length !== hostIds.length) {
 | 
			
		||||
@@ -618,20 +641,21 @@ router.put('/bulk/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Bulk update host groups
 | 
			
		||||
    const updateResult = await prisma.host.updateMany({
 | 
			
		||||
    const updateResult = await prisma.hosts.updateMany({
 | 
			
		||||
      where: { id: { in: hostIds } },
 | 
			
		||||
      data: {
 | 
			
		||||
        hostGroupId: hostGroupId || null
 | 
			
		||||
        host_group_id: hostGroupId || null,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Get updated hosts with group information
 | 
			
		||||
    const updatedHosts = await prisma.host.findMany({
 | 
			
		||||
    const updatedHosts = await prisma.hosts.findMany({
 | 
			
		||||
      where: { id: { in: hostIds } },
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        friendlyName: true,
 | 
			
		||||
        hostGroup: {
 | 
			
		||||
        friendly_name: true,
 | 
			
		||||
        host_groups: {
 | 
			
		||||
          select: {
 | 
			
		||||
            id: true,
 | 
			
		||||
            name: true,
 | 
			
		||||
@@ -666,7 +690,7 @@ router.put('/:hostId/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { hostGroupId } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if host exists
 | 
			
		||||
    const host = await prisma.host.findUnique({
 | 
			
		||||
    const host = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { id: hostId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -676,7 +700,7 @@ router.put('/:hostId/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
 | 
			
		||||
    // If hostGroupId is provided, verify the group exists
 | 
			
		||||
    if (hostGroupId) {
 | 
			
		||||
      const hostGroup = await prisma.hostGroup.findUnique({
 | 
			
		||||
      const hostGroup = await prisma.host_groups.findUnique({
 | 
			
		||||
        where: { id: hostGroupId }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
@@ -686,13 +710,14 @@ router.put('/:hostId/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update host group
 | 
			
		||||
    const updatedHost = await prisma.host.update({
 | 
			
		||||
    const updatedHost = await prisma.hosts.update({
 | 
			
		||||
      where: { id: hostId },
 | 
			
		||||
      data: {
 | 
			
		||||
        hostGroupId: hostGroupId || null
 | 
			
		||||
        host_group_id: hostGroupId || null,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      },
 | 
			
		||||
      include: {
 | 
			
		||||
        hostGroup: {
 | 
			
		||||
        host_groups: {
 | 
			
		||||
          select: {
 | 
			
		||||
            id: true,
 | 
			
		||||
            name: true,
 | 
			
		||||
@@ -715,23 +740,23 @@ router.put('/:hostId/group', authenticateToken, requireManageHosts, [
 | 
			
		||||
// Admin endpoint to list all hosts
 | 
			
		||||
router.get('/admin/list', authenticateToken, requireManageHosts, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const hosts = await prisma.host.findMany({
 | 
			
		||||
    const hosts = await prisma.hosts.findMany({
 | 
			
		||||
      select: {
 | 
			
		||||
        id: true,
 | 
			
		||||
        friendlyName: true,
 | 
			
		||||
        friendly_name: true,
 | 
			
		||||
        hostname: true,
 | 
			
		||||
        ip: true,
 | 
			
		||||
        osType: true,
 | 
			
		||||
        osVersion: true,
 | 
			
		||||
        os_type: true,
 | 
			
		||||
        os_version: true,
 | 
			
		||||
        architecture: true,
 | 
			
		||||
        lastUpdate: true,
 | 
			
		||||
        last_update: true,
 | 
			
		||||
        status: true,
 | 
			
		||||
        apiId: true,
 | 
			
		||||
        agentVersion: true,
 | 
			
		||||
        autoUpdate: true,
 | 
			
		||||
        createdAt: true
 | 
			
		||||
        api_id: true,
 | 
			
		||||
        agent_version: true,
 | 
			
		||||
        auto_update: true,
 | 
			
		||||
        created_at: true
 | 
			
		||||
      },
 | 
			
		||||
      orderBy: { createdAt: 'desc' }
 | 
			
		||||
      orderBy: { created_at: 'desc' }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.json(hosts);
 | 
			
		||||
@@ -747,7 +772,7 @@ router.delete('/:hostId', authenticateToken, requireManageHosts, async (req, res
 | 
			
		||||
    const { hostId } = req.params;
 | 
			
		||||
    
 | 
			
		||||
    // Delete host and all related data (cascade)
 | 
			
		||||
    await prisma.host.delete({
 | 
			
		||||
    await prisma.hosts.delete({
 | 
			
		||||
      where: { id: hostId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -771,17 +796,20 @@ router.patch('/:hostId/auto-update', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { hostId } = req.params;
 | 
			
		||||
    const { autoUpdate } = req.body;
 | 
			
		||||
 | 
			
		||||
    const host = await prisma.host.update({
 | 
			
		||||
    const host = await prisma.hosts.update({
 | 
			
		||||
      where: { id: hostId },
 | 
			
		||||
      data: { autoUpdate }
 | 
			
		||||
      data: { 
 | 
			
		||||
        auto_update: autoUpdate,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.json({
 | 
			
		||||
      message: `Host auto-update ${autoUpdate ? 'enabled' : 'disabled'} successfully`,
 | 
			
		||||
      host: {
 | 
			
		||||
        id: host.id,
 | 
			
		||||
        friendlyName: host.friendlyName,
 | 
			
		||||
        autoUpdate: host.autoUpdate
 | 
			
		||||
        friendlyName: host.friendly_name,
 | 
			
		||||
        autoUpdate: host.auto_update
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
@@ -811,7 +839,7 @@ router.get('/install', async (req, res) => {
 | 
			
		||||
        // Replace the default server URL in the script with the configured one
 | 
			
		||||
        script = script.replace(
 | 
			
		||||
          /PATCHMON_URL="[^"]*"/g,
 | 
			
		||||
          `PATCHMON_URL="${settings.serverUrl}"`
 | 
			
		||||
          `PATCHMON_URL="${settings.server_url}"`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    } catch (settingsError) {
 | 
			
		||||
@@ -832,8 +860,8 @@ router.get('/install', async (req, res) => {
 | 
			
		||||
// Get all agent versions (admin only)
 | 
			
		||||
router.get('/agent/versions', authenticateToken, requireManageSettings, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const versions = await prisma.agentVersion.findMany({
 | 
			
		||||
      orderBy: { createdAt: 'desc' }
 | 
			
		||||
    const versions = await prisma.agent_versions.findMany({
 | 
			
		||||
      orderBy: { created_at: 'desc' }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.json(versions);
 | 
			
		||||
@@ -861,7 +889,7 @@ router.post('/agent/versions', authenticateToken, requireManageSettings, [
 | 
			
		||||
    const { version, releaseNotes, downloadUrl, minServerVersion, scriptContent, isDefault } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if version already exists
 | 
			
		||||
    const existingVersion = await prisma.agentVersion.findUnique({
 | 
			
		||||
    const existingVersion = await prisma.agent_versions.findUnique({
 | 
			
		||||
      where: { version }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -871,21 +899,26 @@ router.post('/agent/versions', authenticateToken, requireManageSettings, [
 | 
			
		||||
 | 
			
		||||
    // If this is being set as default, unset other defaults
 | 
			
		||||
    if (isDefault) {
 | 
			
		||||
      await prisma.agentVersion.updateMany({
 | 
			
		||||
        where: { isDefault: true },
 | 
			
		||||
        data: { isDefault: false }
 | 
			
		||||
      await prisma.agent_versions.updateMany({
 | 
			
		||||
        where: { is_default: true },
 | 
			
		||||
        data: { 
 | 
			
		||||
          is_default: false,
 | 
			
		||||
          updated_at: new Date()
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const agentVersion = await prisma.agentVersion.create({
 | 
			
		||||
    const agentVersion = await prisma.agent_versions.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        id: uuidv4(),
 | 
			
		||||
        version,
 | 
			
		||||
        releaseNotes,
 | 
			
		||||
        downloadUrl,
 | 
			
		||||
        minServerVersion,
 | 
			
		||||
        scriptContent,
 | 
			
		||||
        isDefault: isDefault || false,
 | 
			
		||||
        isCurrent: false
 | 
			
		||||
        release_notes: releaseNotes,
 | 
			
		||||
        download_url: downloadUrl,
 | 
			
		||||
        min_server_version: minServerVersion,
 | 
			
		||||
        script_content: scriptContent,
 | 
			
		||||
        is_default: isDefault || false,
 | 
			
		||||
        is_current: false,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -902,13 +935,13 @@ router.patch('/agent/versions/:versionId/current', authenticateToken, requireMan
 | 
			
		||||
    const { versionId } = req.params;
 | 
			
		||||
 | 
			
		||||
    // First, unset all current versions
 | 
			
		||||
    await prisma.agentVersion.updateMany({
 | 
			
		||||
    await prisma.agent_versions.updateMany({
 | 
			
		||||
      where: { isCurrent: true },
 | 
			
		||||
      data: { isCurrent: false }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Set the specified version as current
 | 
			
		||||
    const agentVersion = await prisma.agentVersion.update({
 | 
			
		||||
    const agentVersion = await prisma.agent_versions.update({
 | 
			
		||||
      where: { id: versionId },
 | 
			
		||||
      data: { isCurrent: true }
 | 
			
		||||
    });
 | 
			
		||||
@@ -926,13 +959,13 @@ router.patch('/agent/versions/:versionId/default', authenticateToken, requireMan
 | 
			
		||||
    const { versionId } = req.params;
 | 
			
		||||
 | 
			
		||||
    // First, unset all default versions
 | 
			
		||||
    await prisma.agentVersion.updateMany({
 | 
			
		||||
    await prisma.agent_versions.updateMany({
 | 
			
		||||
      where: { isDefault: true },
 | 
			
		||||
      data: { isDefault: false }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Set the specified version as default
 | 
			
		||||
    const agentVersion = await prisma.agentVersion.update({
 | 
			
		||||
    const agentVersion = await prisma.agent_versions.update({
 | 
			
		||||
      where: { id: versionId },
 | 
			
		||||
      data: { isDefault: true }
 | 
			
		||||
    });
 | 
			
		||||
@@ -949,7 +982,7 @@ router.delete('/agent/versions/:versionId', authenticateToken, requireManageSett
 | 
			
		||||
  try {
 | 
			
		||||
    const { versionId } = req.params;
 | 
			
		||||
 | 
			
		||||
    const agentVersion = await prisma.agentVersion.findUnique({
 | 
			
		||||
    const agentVersion = await prisma.agent_versions.findUnique({
 | 
			
		||||
      where: { id: versionId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -957,11 +990,11 @@ router.delete('/agent/versions/:versionId', authenticateToken, requireManageSett
 | 
			
		||||
      return res.status(404).json({ error: 'Agent version not found' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (agentVersion.isCurrent) {
 | 
			
		||||
    if (agentVersion.is_current) {
 | 
			
		||||
      return res.status(400).json({ error: 'Cannot delete current agent version' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await prisma.agentVersion.delete({
 | 
			
		||||
    await prisma.agent_versions.delete({
 | 
			
		||||
      where: { id: versionId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -986,7 +1019,7 @@ router.patch('/:hostId/friendly-name', authenticateToken, requireManageHosts, [
 | 
			
		||||
    const { friendlyName } = req.body;
 | 
			
		||||
 | 
			
		||||
    // Check if host exists
 | 
			
		||||
    const host = await prisma.host.findUnique({
 | 
			
		||||
    const host = await prisma.hosts.findUnique({
 | 
			
		||||
      where: { id: hostId }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -995,7 +1028,7 @@ router.patch('/:hostId/friendly-name', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if friendly name is already taken by another host
 | 
			
		||||
    const existingHost = await prisma.host.findFirst({
 | 
			
		||||
    const existingHost = await prisma.hosts.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        friendlyName: friendlyName,
 | 
			
		||||
        id: { not: hostId }
 | 
			
		||||
@@ -1007,7 +1040,7 @@ router.patch('/:hostId/friendly-name', authenticateToken, requireManageHosts, [
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update the friendly name
 | 
			
		||||
    const updatedHost = await prisma.host.update({
 | 
			
		||||
    const updatedHost = await prisma.hosts.update({
 | 
			
		||||
      where: { id: hostId },
 | 
			
		||||
      data: { friendlyName },
 | 
			
		||||
      select: {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,16 +34,16 @@ router.get('/', async (req, res) => {
 | 
			
		||||
        category ? { category: { equals: category } } : {},
 | 
			
		||||
        // Update status filters
 | 
			
		||||
        needsUpdate ? {
 | 
			
		||||
          hostPackages: {
 | 
			
		||||
          host_packages: {
 | 
			
		||||
            some: {
 | 
			
		||||
              needsUpdate: needsUpdate === 'true'
 | 
			
		||||
              needs_update: needsUpdate === 'true'
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } : {},
 | 
			
		||||
        isSecurityUpdate ? {
 | 
			
		||||
          hostPackages: {
 | 
			
		||||
          host_packages: {
 | 
			
		||||
            some: {
 | 
			
		||||
              isSecurityUpdate: isSecurityUpdate === 'true'
 | 
			
		||||
              is_security_update: isSecurityUpdate === 'true'
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } : {}
 | 
			
		||||
@@ -52,17 +52,17 @@ router.get('/', async (req, res) => {
 | 
			
		||||
 | 
			
		||||
    // Get packages with counts
 | 
			
		||||
    const [packages, totalCount] = await Promise.all([
 | 
			
		||||
      prisma.package.findMany({
 | 
			
		||||
      prisma.packages.findMany({
 | 
			
		||||
        where,
 | 
			
		||||
        select: {
 | 
			
		||||
          id: true,
 | 
			
		||||
          name: true,
 | 
			
		||||
          description: true,
 | 
			
		||||
          category: true,
 | 
			
		||||
          latestVersion: true,
 | 
			
		||||
          createdAt: true,
 | 
			
		||||
          latest_version: true,
 | 
			
		||||
          created_at: true,
 | 
			
		||||
          _count: {
 | 
			
		||||
            hostPackages: true
 | 
			
		||||
            host_packages: true
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        skip,
 | 
			
		||||
@@ -71,38 +71,38 @@ router.get('/', async (req, res) => {
 | 
			
		||||
          name: 'asc'
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
      prisma.package.count({ where })
 | 
			
		||||
      prisma.packages.count({ where })
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Get additional stats for each package
 | 
			
		||||
    const packagesWithStats = await Promise.all(
 | 
			
		||||
      packages.map(async (pkg) => {
 | 
			
		||||
        const [updatesCount, securityCount, affectedHosts] = await Promise.all([
 | 
			
		||||
          prisma.hostPackage.count({
 | 
			
		||||
          prisma.host_packages.count({
 | 
			
		||||
            where: {
 | 
			
		||||
              packageId: pkg.id,
 | 
			
		||||
              needsUpdate: true
 | 
			
		||||
              package_id: pkg.id,
 | 
			
		||||
              needs_update: true
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
          prisma.hostPackage.count({
 | 
			
		||||
          prisma.host_packages.count({
 | 
			
		||||
            where: {
 | 
			
		||||
              packageId: pkg.id,
 | 
			
		||||
              needsUpdate: true,
 | 
			
		||||
              isSecurityUpdate: true
 | 
			
		||||
              package_id: pkg.id,
 | 
			
		||||
              needs_update: true,
 | 
			
		||||
              is_security_update: true
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
          prisma.hostPackage.findMany({
 | 
			
		||||
          prisma.host_packages.findMany({
 | 
			
		||||
            where: {
 | 
			
		||||
              packageId: pkg.id,
 | 
			
		||||
              needsUpdate: true
 | 
			
		||||
              package_id: pkg.id,
 | 
			
		||||
              needs_update: true
 | 
			
		||||
            },
 | 
			
		||||
            select: {
 | 
			
		||||
              host: {
 | 
			
		||||
              hosts: {
 | 
			
		||||
                select: {
 | 
			
		||||
                  id: true,
 | 
			
		||||
                  friendlyName: true,
 | 
			
		||||
                  friendly_name: true,
 | 
			
		||||
                  hostname: true,
 | 
			
		||||
                  osType: true
 | 
			
		||||
                  os_type: true
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
@@ -142,7 +142,7 @@ router.get('/:packageId', async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const { packageId } = req.params;
 | 
			
		||||
 | 
			
		||||
    const packageData = await prisma.package.findUnique({
 | 
			
		||||
    const packageData = await prisma.packages.findUnique({
 | 
			
		||||
      where: { id: packageId },
 | 
			
		||||
      include: {
 | 
			
		||||
        hostPackages: {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ const prisma = new PrismaClient();
 | 
			
		||||
// Get all role permissions
 | 
			
		||||
router.get('/roles', authenticateToken, requireManageSettings, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const permissions = await prisma.rolePermissions.findMany({
 | 
			
		||||
    const permissions = await prisma.role_permissions.findMany({
 | 
			
		||||
      orderBy: {
 | 
			
		||||
        role: 'asc'
 | 
			
		||||
      }
 | 
			
		||||
@@ -27,7 +27,7 @@ router.get('/roles/:role', authenticateToken, requireManageSettings, async (req,
 | 
			
		||||
  try {
 | 
			
		||||
    const { role } = req.params;
 | 
			
		||||
    
 | 
			
		||||
    const permissions = await prisma.rolePermissions.findUnique({
 | 
			
		||||
    const permissions = await prisma.role_permissions.findUnique({
 | 
			
		||||
      where: { role }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -64,32 +64,35 @@ router.put('/roles/:role', authenticateToken, requireManageSettings, async (req,
 | 
			
		||||
      return res.status(400).json({ error: 'Cannot modify admin role permissions' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const permissions = await prisma.rolePermissions.upsert({
 | 
			
		||||
    const permissions = await prisma.role_permissions.upsert({
 | 
			
		||||
      where: { role },
 | 
			
		||||
      update: {
 | 
			
		||||
        canViewDashboard,
 | 
			
		||||
        canViewHosts,
 | 
			
		||||
        canManageHosts,
 | 
			
		||||
        canViewPackages,
 | 
			
		||||
        canManagePackages,
 | 
			
		||||
        canViewUsers,
 | 
			
		||||
        canManageUsers,
 | 
			
		||||
        canViewReports,
 | 
			
		||||
        canExportData,
 | 
			
		||||
        canManageSettings
 | 
			
		||||
        can_view_dashboard: canViewDashboard,
 | 
			
		||||
        can_view_hosts: canViewHosts,
 | 
			
		||||
        can_manage_hosts: canManageHosts,
 | 
			
		||||
        can_view_packages: canViewPackages,
 | 
			
		||||
        can_manage_packages: canManagePackages,
 | 
			
		||||
        can_view_users: canViewUsers,
 | 
			
		||||
        can_manage_users: canManageUsers,
 | 
			
		||||
        can_view_reports: canViewReports,
 | 
			
		||||
        can_export_data: canExportData,
 | 
			
		||||
        can_manage_settings: canManageSettings,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      },
 | 
			
		||||
      create: {
 | 
			
		||||
        id: require('uuid').v4(),
 | 
			
		||||
        role,
 | 
			
		||||
        canViewDashboard,
 | 
			
		||||
        canViewHosts,
 | 
			
		||||
        canManageHosts,
 | 
			
		||||
        canViewPackages,
 | 
			
		||||
        canManagePackages,
 | 
			
		||||
        canViewUsers,
 | 
			
		||||
        canManageUsers,
 | 
			
		||||
        canViewReports,
 | 
			
		||||
        canExportData,
 | 
			
		||||
        canManageSettings
 | 
			
		||||
        can_view_dashboard: canViewDashboard,
 | 
			
		||||
        can_view_hosts: canViewHosts,
 | 
			
		||||
        can_manage_hosts: canManageHosts,
 | 
			
		||||
        can_view_packages: canViewPackages,
 | 
			
		||||
        can_manage_packages: canManagePackages,
 | 
			
		||||
        can_view_users: canViewUsers,
 | 
			
		||||
        can_manage_users: canManageUsers,
 | 
			
		||||
        can_view_reports: canViewReports,
 | 
			
		||||
        can_export_data: canExportData,
 | 
			
		||||
        can_manage_settings: canManageSettings,
 | 
			
		||||
        updated_at: new Date()
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -114,7 +117,7 @@ router.delete('/roles/:role', authenticateToken, requireManageSettings, async (r
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if any users are using this role
 | 
			
		||||
    const usersWithRole = await prisma.user.count({
 | 
			
		||||
    const usersWithRole = await prisma.users.count({
 | 
			
		||||
      where: { role }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -124,7 +127,7 @@ router.delete('/roles/:role', authenticateToken, requireManageSettings, async (r
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await prisma.rolePermissions.delete({
 | 
			
		||||
    await prisma.role_permissions.delete({
 | 
			
		||||
      where: { role }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -142,7 +145,7 @@ router.get('/user-permissions', authenticateToken, async (req, res) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const userRole = req.user.role;
 | 
			
		||||
    
 | 
			
		||||
    const permissions = await prisma.rolePermissions.findUnique({
 | 
			
		||||
    const permissions = await prisma.role_permissions.findUnique({
 | 
			
		||||
      where: { role: userRole }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const { body, validationResult } = require('express-validator');
 | 
			
		||||
const { PrismaClient } = require('@prisma/client');
 | 
			
		||||
const { v4: uuidv4 } = require('uuid');
 | 
			
		||||
const { authenticateToken } = require('../middleware/auth');
 | 
			
		||||
const { requireManageSettings } = require('../middleware/permissions');
 | 
			
		||||
 | 
			
		||||
@@ -96,13 +97,15 @@ router.get('/', authenticateToken, requireManageSettings, async (req, res) => {
 | 
			
		||||
    if (!settings) {
 | 
			
		||||
      settings = await prisma.settings.create({
 | 
			
		||||
        data: {
 | 
			
		||||
          serverUrl: 'http://localhost:3001',
 | 
			
		||||
          serverProtocol: 'http',
 | 
			
		||||
          serverHost: 'localhost',
 | 
			
		||||
          serverPort: 3001,
 | 
			
		||||
          frontendUrl: 'http://localhost:3000',
 | 
			
		||||
          updateInterval: 60,
 | 
			
		||||
          autoUpdate: false
 | 
			
		||||
          id: uuidv4(),
 | 
			
		||||
          server_url: 'http://localhost:3001',
 | 
			
		||||
          server_protocol: 'http',
 | 
			
		||||
          server_host: 'localhost',
 | 
			
		||||
          server_port: 3001,
 | 
			
		||||
          frontend_url: 'http://localhost:3000',
 | 
			
		||||
          update_interval: 60,
 | 
			
		||||
          auto_update: false,
 | 
			
		||||
          updated_at: new Date()
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
@@ -171,16 +174,17 @@ router.put('/', authenticateToken, requireManageSettings, [
 | 
			
		||||
      settings = await prisma.settings.update({
 | 
			
		||||
        where: { id: settings.id },
 | 
			
		||||
        data: {
 | 
			
		||||
          serverUrl,
 | 
			
		||||
          serverProtocol,
 | 
			
		||||
          serverHost,
 | 
			
		||||
          serverPort,
 | 
			
		||||
          frontendUrl,
 | 
			
		||||
          updateInterval: updateInterval || 60,
 | 
			
		||||
          autoUpdate: autoUpdate || false,
 | 
			
		||||
          githubRepoUrl: githubRepoUrl !== undefined ? githubRepoUrl : 'git@github.com:9technologygroup/patchmon.net.git',
 | 
			
		||||
          repositoryType: repositoryType || 'public',
 | 
			
		||||
          sshKeyPath: sshKeyPath || null
 | 
			
		||||
          server_url: serverUrl,
 | 
			
		||||
          server_protocol: serverProtocol,
 | 
			
		||||
          server_host: serverHost,
 | 
			
		||||
          server_port: serverPort,
 | 
			
		||||
          frontend_url: frontendUrl,
 | 
			
		||||
          update_interval: updateInterval || 60,
 | 
			
		||||
          auto_update: autoUpdate || false,
 | 
			
		||||
          github_repo_url: githubRepoUrl !== undefined ? githubRepoUrl : 'git@github.com:9technologygroup/patchmon.net.git',
 | 
			
		||||
          repository_type: repositoryType || 'public',
 | 
			
		||||
          ssh_key_path: sshKeyPath || null,
 | 
			
		||||
          updated_at: new Date()
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      console.log('Settings updated successfully:', settings);
 | 
			
		||||
@@ -194,16 +198,18 @@ router.put('/', authenticateToken, requireManageSettings, [
 | 
			
		||||
      // Create new settings
 | 
			
		||||
      settings = await prisma.settings.create({
 | 
			
		||||
        data: {
 | 
			
		||||
          serverUrl,
 | 
			
		||||
          serverProtocol,
 | 
			
		||||
          serverHost,
 | 
			
		||||
          serverPort,
 | 
			
		||||
          frontendUrl,
 | 
			
		||||
          updateInterval: updateInterval || 60,
 | 
			
		||||
          autoUpdate: autoUpdate || false,
 | 
			
		||||
          githubRepoUrl: githubRepoUrl !== undefined ? githubRepoUrl : 'git@github.com:9technologygroup/patchmon.net.git',
 | 
			
		||||
          repositoryType: repositoryType || 'public',
 | 
			
		||||
          sshKeyPath: sshKeyPath || null
 | 
			
		||||
          id: uuidv4(),
 | 
			
		||||
          server_url: serverUrl,
 | 
			
		||||
          server_protocol: serverProtocol,
 | 
			
		||||
          server_host: serverHost,
 | 
			
		||||
          server_port: serverPort,
 | 
			
		||||
          frontend_url: frontendUrl,
 | 
			
		||||
          update_interval: updateInterval || 60,
 | 
			
		||||
          auto_update: autoUpdate || false,
 | 
			
		||||
          github_repo_url: githubRepoUrl !== undefined ? githubRepoUrl : 'git@github.com:9technologygroup/patchmon.net.git',
 | 
			
		||||
          repository_type: repositoryType || 'public',
 | 
			
		||||
          ssh_key_path: sshKeyPath || null,
 | 
			
		||||
          updated_at: new Date()
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user