diff --git a/.gitignore b/.gitignore index eec901c..907fdb3 100644 --- a/.gitignore +++ b/.gitignore @@ -140,6 +140,7 @@ test-results.xml deploy-patchmon.sh manage-instances.sh manage-patchmon.sh +manage-patchmon-dev.sh setup-installer-site.sh install-server.* notify-clients-upgrade.sh diff --git a/agents/patchmon-agent.sh b/agents/patchmon-agent.sh index f78040e..6d9da04 100755 --- a/agents/patchmon-agent.sh +++ b/agents/patchmon-agent.sh @@ -1,12 +1,12 @@ #!/bin/bash -# PatchMon Agent Script v1.2.5 +# PatchMon Agent Script v1.2.6 # This script sends package update information to the PatchMon server using API credentials # Configuration PATCHMON_SERVER="${PATCHMON_SERVER:-http://localhost:3001}" API_VERSION="v1" -AGENT_VERSION="1.2.5" +AGENT_VERSION="1.2.6" CONFIG_FILE="/etc/patchmon/agent.conf" CREDENTIALS_FILE="/etc/patchmon/credentials" LOG_FILE="/var/log/patchmon-agent.log" diff --git a/backend/add-agent-version.js b/backend/add-agent-version.js index 0519ecb..bcda313 100644 --- a/backend/add-agent-version.js +++ b/backend/add-agent-version.js @@ -1 +1,102 @@ - \ No newline at end of file +const { PrismaClient } = require('@prisma/client'); +const fs = require('fs'); +const path = require('path'); + +const prisma = new PrismaClient(); + +async function addAgentVersion() { + try { + console.log('🚀 Adding agent version to database...'); + + // Read the agent script file + const agentScriptPath = path.join(__dirname, '..', 'agents', 'patchmon-agent.sh'); + + if (!fs.existsSync(agentScriptPath)) { + throw new Error(`Agent script not found at: ${agentScriptPath}`); + } + + const scriptContent = fs.readFileSync(agentScriptPath, 'utf8'); + console.log(`📄 Read agent script (${scriptContent.length} characters)`); + + // Extract version from script content + const versionMatch = scriptContent.match(/AGENT_VERSION="([^"]+)"/); + if (!versionMatch) { + throw new Error('Could not extract AGENT_VERSION from script'); + } + + const version = versionMatch[1]; + console.log(`🔍 Found agent version: ${version}`); + + // Check if this version already exists + const existingVersion = await prisma.agentVersion.findUnique({ + where: { version: version } + }); + + if (existingVersion) { + console.log(`⚠️ Agent version ${version} already exists in database`); + + // Update the existing version with current script content + const updatedVersion = await prisma.agentVersion.update({ + where: { version: version }, + data: { + scriptContent: scriptContent, + isDefault: true, + isCurrent: true, + releaseNotes: `Agent script version ${version} - Updated during deployment` + } + }); + + console.log(`✅ Updated existing agent version ${version}`); + return updatedVersion; + } + + // Set all other versions to not be current/default + await prisma.agentVersion.updateMany({ + where: { + version: { not: version } + }, + data: { + isCurrent: false, + isDefault: false + } + }); + + // Create new agent version + const newVersion = await prisma.agentVersion.create({ + data: { + version: version, + scriptContent: scriptContent, + isDefault: true, + isCurrent: true, + releaseNotes: `Agent script version ${version} - Initial deployment` + } + }); + + console.log(`✅ Created new agent version ${version}`); + console.log(`📊 Version ID: ${newVersion.id}`); + console.log(`📝 Script content length: ${scriptContent.length} characters`); + + return newVersion; + + } catch (error) { + console.error('❌ Error adding agent version:', error); + throw error; + } finally { + await prisma.$disconnect(); + } +} + +// Run the function if this script is executed directly +if (require.main === module) { + addAgentVersion() + .then(() => { + console.log('🎉 Agent version setup completed successfully!'); + process.exit(0); + }) + .catch((error) => { + console.error('💥 Agent version setup failed:', error); + process.exit(1); + }); +} + +module.exports = { addAgentVersion }; \ No newline at end of file diff --git a/backend/check-agent-version.js b/backend/check-agent-version.js index 3c0717b..b4df406 100644 --- a/backend/check-agent-version.js +++ b/backend/check-agent-version.js @@ -6,11 +6,11 @@ async function checkAgentVersion() { try { // Check current agent version in database const agentVersion = await prisma.agentVersion.findFirst({ - where: { version: '1.2.5' } + where: { version: '1.2.6' } }); if (agentVersion) { - console.log('✅ Agent version 1.2.5 found in database'); + console.log('✅ Agent version 1.2.6 found in database'); console.log('Version:', agentVersion.version); console.log('Is Default:', agentVersion.isDefault); console.log('Script Content Length:', agentVersion.scriptContent?.length || 0); @@ -18,10 +18,10 @@ async function checkAgentVersion() { console.log('Updated At:', agentVersion.updatedAt); // Check if script content contains the current version - if (agentVersion.scriptContent && agentVersion.scriptContent.includes('AGENT_VERSION="1.2.5"')) { - console.log('✅ Script content contains correct version 1.2.5'); + if (agentVersion.scriptContent && agentVersion.scriptContent.includes('AGENT_VERSION="1.2.6"')) { + console.log('✅ Script content contains correct version 1.2.6'); } else { - console.log('❌ Script content does not contain version 1.2.5'); + console.log('❌ Script content does not contain version 1.2.6'); } // Check if script content contains system info functions @@ -44,7 +44,7 @@ async function checkAgentVersion() { } } else { - console.log('❌ Agent version 1.2.5 not found in database'); + console.log('❌ Agent version 1.2.6 not found in database'); } // List all agent versions diff --git a/backend/check-host-updates.js b/backend/check-host-updates.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/check-host-updates.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/check-script-content.js b/backend/check-script-content.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/check-script-content.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/create-proper-test-host.js b/backend/create-proper-test-host.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/create-proper-test-host.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/create-test-host.js b/backend/create-test-host.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/create-test-host.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/env.example b/backend/env.example index 6f37d61..8be09e1 100644 --- a/backend/env.example +++ b/backend/env.example @@ -9,9 +9,13 @@ NODE_ENV=development API_VERSION=v1 CORS_ORIGIN=http://localhost:3000 -# Rate Limiting +# Rate Limiting (times in milliseconds) RATE_LIMIT_WINDOW_MS=900000 -RATE_LIMIT_MAX=100 +RATE_LIMIT_MAX=5000 +AUTH_RATE_LIMIT_WINDOW_MS=600000 +AUTH_RATE_LIMIT_MAX=500 +AGENT_RATE_LIMIT_WINDOW_MS=60000 +AGENT_RATE_LIMIT_MAX=1000 # Logging LOG_LEVEL=info diff --git a/backend/package.json b/backend/package.json index 31c4120..6b7ad1d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "patchmon-backend", - "version": "1.2.5", + "version": "1.2.6", "description": "Backend API for Linux Patch Monitoring System", "main": "src/server.js", "scripts": { diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 678eb01..23c1998 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -1,6 +1,3 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { provider = "prisma-client-js" } @@ -10,239 +7,192 @@ datasource db { url = env("DATABASE_URL") } -model User { - id String @id @default(cuid()) - username String @unique - email String @unique - passwordHash String @map("password_hash") - role String @default("admin") // admin, user - isActive Boolean @default(true) @map("is_active") - lastLogin DateTime? @map("last_login") - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Two-Factor Authentication - tfaEnabled Boolean @default(false) @map("tfa_enabled") - tfaSecret String? @map("tfa_secret") - tfaBackupCodes String? @map("tfa_backup_codes") // JSON array of backup codes - - // Relationships - dashboardPreferences DashboardPreferences[] - - @@map("users") +model agent_versions { + id String @id + version String @unique + is_current Boolean @default(false) + release_notes String? + download_url String? + min_server_version String? + created_at DateTime @default(now()) + updated_at DateTime + is_default Boolean @default(false) + script_content String? } -model RolePermissions { - id String @id @default(cuid()) - role String @unique // admin, user, custom roles - canViewDashboard Boolean @default(true) @map("can_view_dashboard") - canViewHosts Boolean @default(true) @map("can_view_hosts") - canManageHosts Boolean @default(false) @map("can_manage_hosts") - canViewPackages Boolean @default(true) @map("can_view_packages") - canManagePackages Boolean @default(false) @map("can_manage_packages") - canViewUsers Boolean @default(false) @map("can_view_users") - canManageUsers Boolean @default(false) @map("can_manage_users") - canViewReports Boolean @default(true) @map("can_view_reports") - canExportData Boolean @default(false) @map("can_export_data") - canManageSettings Boolean @default(false) @map("can_manage_settings") - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - @@map("role_permissions") +model dashboard_preferences { + id String @id + user_id String + card_id String + enabled Boolean @default(true) + order Int @default(0) + created_at DateTime @default(now()) + updated_at DateTime + users users @relation(fields: [user_id], references: [id], onDelete: Cascade) + + @@unique([user_id, card_id]) } -model HostGroup { - id String @id @default(cuid()) - name String @unique - description String? - color String? @default("#3B82F6") // Hex color for UI display - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Relationships - hosts Host[] - - @@map("host_groups") +model host_groups { + id String @id + name String @unique + description String? + color String? @default("#3B82F6") + created_at DateTime @default(now()) + updated_at DateTime + hosts hosts[] } -model Host { - id String @id @default(cuid()) - friendlyName String @unique @map("friendly_name") - hostname String? // Actual system hostname from agent - ip String? - osType String @map("os_type") - osVersion String @map("os_version") - architecture String? - lastUpdate DateTime @map("last_update") @default(now()) - status String @default("active") // active, inactive, error - apiId String @unique @map("api_id") // New API ID for authentication - apiKey String @unique @map("api_key") // New API Key for authentication - hostGroupId String? @map("host_group_id") // Optional group association - agentVersion String? @map("agent_version") // Agent script version - autoUpdate Boolean @map("auto_update") @default(true) // Enable auto-update for this host - - // Hardware Information - cpuModel String? @map("cpu_model") // CPU model name - cpuCores Int? @map("cpu_cores") // Number of CPU cores - ramInstalled Int? @map("ram_installed") // RAM in GB - swapSize Int? @map("swap_size") // Swap size in GB - diskDetails Json? @map("disk_details") // Array of disk objects - - // Network Information - gatewayIp String? @map("gateway_ip") // Gateway IP address - dnsServers Json? @map("dns_servers") // Array of DNS servers - networkInterfaces Json? @map("network_interfaces") // Array of network interface objects - - // System Information - kernelVersion String? @map("kernel_version") // Kernel version - selinuxStatus String? @map("selinux_status") // SELinux status (enabled/disabled/permissive) - systemUptime String? @map("system_uptime") // System uptime - loadAverage Json? @map("load_average") // Load average (1min, 5min, 15min) - - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Relationships - hostPackages HostPackage[] - updateHistory UpdateHistory[] - hostRepositories HostRepository[] - hostGroup HostGroup? @relation(fields: [hostGroupId], references: [id], onDelete: SetNull) - - @@map("hosts") +model host_packages { + id String @id + host_id String + package_id String + current_version String + available_version String? + needs_update Boolean @default(false) + is_security_update Boolean @default(false) + last_checked DateTime @default(now()) + hosts hosts @relation(fields: [host_id], references: [id], onDelete: Cascade) + packages packages @relation(fields: [package_id], references: [id], onDelete: Cascade) + + @@unique([host_id, package_id]) } -model Package { - id String @id @default(cuid()) - name String @unique - description String? - category String? // system, security, development, etc. - latestVersion String? @map("latest_version") - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Relationships - hostPackages HostPackage[] - - @@map("packages") +model host_repositories { + id String @id + host_id String + repository_id String + is_enabled Boolean @default(true) + last_checked DateTime @default(now()) + hosts hosts @relation(fields: [host_id], references: [id], onDelete: Cascade) + repositories repositories @relation(fields: [repository_id], references: [id], onDelete: Cascade) + + @@unique([host_id, repository_id]) } -model HostPackage { - id String @id @default(cuid()) - hostId String @map("host_id") - packageId String @map("package_id") - currentVersion String @map("current_version") - availableVersion String? @map("available_version") - needsUpdate Boolean @map("needs_update") @default(false) - isSecurityUpdate Boolean @map("is_security_update") @default(false) - lastChecked DateTime @map("last_checked") @default(now()) - - // Relationships - host Host @relation(fields: [hostId], references: [id], onDelete: Cascade) - package Package @relation(fields: [packageId], references: [id], onDelete: Cascade) - - @@unique([hostId, packageId]) - @@map("host_packages") +model hosts { + id String @id + friendly_name String @unique + ip String? + os_type String + os_version String + architecture String? + last_update DateTime @default(now()) + status String @default("active") + created_at DateTime @default(now()) + updated_at DateTime + api_id String @unique + api_key String @unique + host_group_id String? + agent_version String? + auto_update Boolean @default(true) + cpu_cores Int? + cpu_model String? + disk_details Json? + dns_servers Json? + gateway_ip String? + hostname String? + kernel_version String? + load_average Json? + network_interfaces Json? + ram_installed Int? + selinux_status String? + swap_size Int? + system_uptime String? + host_packages host_packages[] + host_repositories host_repositories[] + host_groups host_groups? @relation(fields: [host_group_id], references: [id]) + update_history update_history[] } -model UpdateHistory { - id String @id @default(cuid()) - hostId String @map("host_id") - packagesCount Int @map("packages_count") - securityCount Int @map("security_count") - timestamp DateTime @default(now()) - status String @default("success") // success, error - errorMessage String? @map("error_message") - - // Relationships - host Host @relation(fields: [hostId], references: [id], onDelete: Cascade) - - @@map("update_history") +model packages { + id String @id + name String @unique + description String? + category String? + latest_version String? + created_at DateTime @default(now()) + updated_at DateTime + host_packages host_packages[] } -model Repository { - id String @id @default(cuid()) - name String // Repository name (e.g., "focal", "focal-updates") - url String // Repository URL - distribution String // Distribution (e.g., "focal", "jammy") - components String // Components (e.g., "main restricted universe multiverse") - repoType String @map("repo_type") // "deb" or "deb-src" - isActive Boolean @map("is_active") @default(true) - isSecure Boolean @map("is_secure") @default(true) // HTTPS vs HTTP - priority Int? // Repository priority - description String? // Optional description - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Relationships - hostRepositories HostRepository[] - +model repositories { + id String @id + name String + url String + distribution String + components String + repo_type String + is_active Boolean @default(true) + is_secure Boolean @default(true) + priority Int? + description String? + created_at DateTime @default(now()) + updated_at DateTime + host_repositories host_repositories[] + @@unique([url, distribution, components]) - @@map("repositories") } -model HostRepository { - id String @id @default(cuid()) - hostId String @map("host_id") - repositoryId String @map("repository_id") - isEnabled Boolean @map("is_enabled") @default(true) - lastChecked DateTime @map("last_checked") @default(now()) - - // Relationships - host Host @relation(fields: [hostId], references: [id], onDelete: Cascade) - repository Repository @relation(fields: [repositoryId], references: [id], onDelete: Cascade) - - @@unique([hostId, repositoryId]) - @@map("host_repositories") +model role_permissions { + id String @id + role String @unique + can_view_dashboard Boolean @default(true) + can_view_hosts Boolean @default(true) + can_manage_hosts Boolean @default(false) + can_view_packages Boolean @default(true) + can_manage_packages Boolean @default(false) + can_view_users Boolean @default(false) + can_manage_users Boolean @default(false) + can_view_reports Boolean @default(true) + can_export_data Boolean @default(false) + can_manage_settings Boolean @default(false) + created_at DateTime @default(now()) + updated_at DateTime } -model Settings { - id String @id @default(cuid()) - serverUrl String @map("server_url") @default("http://localhost:3001") - serverProtocol String @map("server_protocol") @default("http") // http, https - serverHost String @map("server_host") @default("localhost") - serverPort Int @map("server_port") @default(3001) - frontendUrl String @map("frontend_url") @default("http://localhost:3000") - updateInterval Int @map("update_interval") @default(60) // Update interval in minutes - autoUpdate Boolean @map("auto_update") @default(false) // Enable automatic agent updates - githubRepoUrl String @map("github_repo_url") @default("git@github.com:9technologygroup/patchmon.net.git") // GitHub repository URL for version checking - repositoryType String @map("repository_type") @default("public") // "public" or "private" - sshKeyPath String? @map("ssh_key_path") // Optional SSH key path for deploy key authentication - lastUpdateCheck DateTime? @map("last_update_check") // When the system last checked for updates - updateAvailable Boolean @map("update_available") @default(false) // Whether an update is available - latestVersion String? @map("latest_version") // Latest available version - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - @@map("settings") +model settings { + id String @id + server_url String @default("http://localhost:3001") + server_protocol String @default("http") + server_host String @default("localhost") + server_port Int @default(3001) + frontend_url String @default("http://localhost:3000") + created_at DateTime @default(now()) + updated_at DateTime + update_interval Int @default(60) + auto_update Boolean @default(false) + github_repo_url String @default("git@github.com:9technologygroup/patchmon.net.git") + ssh_key_path String? + repository_type String @default("public") + last_update_check DateTime? + latest_version String? + update_available Boolean @default(false) } -model DashboardPreferences { - id String @id @default(cuid()) - userId String @map("user_id") - cardId String @map("card_id") // e.g., "totalHosts", "securityUpdates", etc. - enabled Boolean @default(true) - order Int @default(0) - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - // Relationships - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([userId, cardId]) - @@map("dashboard_preferences") +model update_history { + id String @id + host_id String + packages_count Int + security_count Int + timestamp DateTime @default(now()) + status String @default("success") + error_message String? + hosts hosts @relation(fields: [host_id], references: [id], onDelete: Cascade) } -model AgentVersion { - id String @id @default(cuid()) - version String @unique // e.g., "1.0.0", "1.1.0" - isCurrent Boolean @default(false) @map("is_current") // Only one version can be current - releaseNotes String? @map("release_notes") - downloadUrl String? @map("download_url") // URL to download the agent script - minServerVersion String? @map("min_server_version") // Minimum server version required - scriptContent String? @map("script_content") // The actual agent script content - isDefault Boolean @default(false) @map("is_default") // Default version for new installations - createdAt DateTime @map("created_at") @default(now()) - updatedAt DateTime @map("updated_at") @updatedAt - - @@map("agent_versions") -} \ No newline at end of file +model users { + id String @id + username String @unique + email String @unique + password_hash String + role String @default("admin") + is_active Boolean @default(true) + last_login DateTime? + created_at DateTime @default(now()) + updated_at DateTime + tfa_backup_codes String? + tfa_enabled Boolean @default(false) + tfa_secret String? + dashboard_preferences dashboard_preferences[] +} diff --git a/backend/src/routes/versionRoutes.js b/backend/src/routes/versionRoutes.js index 27650ce..027ccde 100644 --- a/backend/src/routes/versionRoutes.js +++ b/backend/src/routes/versionRoutes.js @@ -14,7 +14,7 @@ const router = express.Router(); router.get('/current', authenticateToken, async (req, res) => { try { // Read version from package.json dynamically - let currentVersion = '1.2.5'; // fallback + let currentVersion = '1.2.6'; // fallback try { const packageJson = require('../../package.json'); @@ -158,7 +158,7 @@ router.get('/check-updates', authenticateToken, requireManageSettings, async (re return res.status(400).json({ error: 'Settings not found' }); } - const currentVersion = '1.2.5'; + const currentVersion = '1.2.6'; const latestVersion = settings.latestVersion || currentVersion; const isUpdateAvailable = settings.updateAvailable || false; const lastUpdateCheck = settings.lastUpdateCheck; diff --git a/backend/src/server.js b/backend/src/server.js index 26eea09..4910ea8 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -59,11 +59,18 @@ if (process.env.TRUST_PROXY) { } app.disable('x-powered-by'); -// Rate limiting +// Rate limiting with monitoring const limiter = rateLimit({ windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000, max: parseInt(process.env.RATE_LIMIT_MAX) || 100, - message: 'Too many requests from this IP, please try again later.', + message: { + error: 'Too many requests from this IP, please try again later.', + retryAfter: Math.ceil((parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000) / 1000) + }, + standardHeaders: true, + legacyHeaders: false, + skipSuccessfulRequests: true, // Don't count successful requests + skipFailedRequests: false, // Count failed requests }); // Middleware @@ -118,16 +125,31 @@ app.get('/health', (req, res) => { // API routes const apiVersion = process.env.API_VERSION || 'v1'; -// Per-route rate limits +// Per-route rate limits with monitoring const authLimiter = rateLimit({ windowMs: parseInt(process.env.AUTH_RATE_LIMIT_WINDOW_MS) || 10 * 60 * 1000, - max: parseInt(process.env.AUTH_RATE_LIMIT_MAX) || 20 + max: parseInt(process.env.AUTH_RATE_LIMIT_MAX) || 20, + message: { + error: 'Too many authentication requests, please try again later.', + retryAfter: Math.ceil((parseInt(process.env.AUTH_RATE_LIMIT_WINDOW_MS) || 10 * 60 * 1000) / 1000) + }, + standardHeaders: true, + legacyHeaders: false, + skipSuccessfulRequests: true, }); const agentLimiter = rateLimit({ windowMs: parseInt(process.env.AGENT_RATE_LIMIT_WINDOW_MS) || 60 * 1000, - max: parseInt(process.env.AGENT_RATE_LIMIT_MAX) || 120 + max: parseInt(process.env.AGENT_RATE_LIMIT_MAX) || 120, + message: { + error: 'Too many agent requests, please try again later.', + retryAfter: Math.ceil((parseInt(process.env.AGENT_RATE_LIMIT_WINDOW_MS) || 60 * 1000) / 1000) + }, + standardHeaders: true, + legacyHeaders: false, + skipSuccessfulRequests: true, }); + app.use(`/api/${apiVersion}/auth`, authLimiter, authRoutes); app.use(`/api/${apiVersion}/hosts`, agentLimiter, hostRoutes); app.use(`/api/${apiVersion}/host-groups`, hostGroupRoutes); diff --git a/backend/src/services/updateScheduler.js b/backend/src/services/updateScheduler.js index e5e4095..560028e 100644 --- a/backend/src/services/updateScheduler.js +++ b/backend/src/services/updateScheduler.js @@ -101,7 +101,7 @@ class UpdateScheduler { } // Read version from package.json dynamically - let currentVersion = '1.2.5'; // fallback + let currentVersion = '1.2.6'; // fallback try { const packageJson = require('../../package.json'); if (packageJson && packageJson.version) { @@ -203,7 +203,7 @@ class UpdateScheduler { const httpsRepoUrl = `https://api.github.com/repos/${owner}/${repo}/releases/latest`; // Get current version for User-Agent - let currentVersion = '1.2.5'; // fallback + let currentVersion = '1.2.6'; // fallback try { const packageJson = require('../../package.json'); if (packageJson && packageJson.version) { diff --git a/backend/test-json-construction.js b/backend/test-json-construction.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/test-json-construction.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-agent-script.js b/backend/update-agent-script.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-agent-script.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-agent-version.js b/backend/update-agent-version.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-agent-version.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-final-fix.js b/backend/update-final-fix.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-final-fix.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-fixed-agent-final.js b/backend/update-fixed-agent-final.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-fixed-agent-final.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-fixed-agent.js b/backend/update-fixed-agent.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-fixed-agent.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/update-script-content.js b/backend/update-script-content.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/update-script-content.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/backend/verify-agent-version.js b/backend/verify-agent-version.js deleted file mode 100644 index 0519ecb..0000000 --- a/backend/verify-agent-version.js +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 448b7a5..2791c7d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "patchmon-frontend", "private": true, - "version": "1.2.5", + "version": "1.2.6", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx index 9dce1ca..99d5722 100644 --- a/frontend/src/pages/Dashboard.jsx +++ b/frontend/src/pages/Dashboard.jsx @@ -92,8 +92,8 @@ const Dashboard = () => { const { data: stats, isLoading, error, refetch } = useQuery({ queryKey: ['dashboardStats'], queryFn: () => dashboardAPI.getStats().then(res => res.data), - refetchInterval: 60000, // Refresh every minute - staleTime: 30000, // Consider data stale after 30 seconds + refetchInterval: 300000, // Refresh every 5 minutes instead of 1 minute + staleTime: 120000, // Consider data stale after 2 minutes }) // Fetch settings to get the agent update interval diff --git a/frontend/src/pages/Hosts.jsx b/frontend/src/pages/Hosts.jsx index e13d541..6a20579 100644 --- a/frontend/src/pages/Hosts.jsx +++ b/frontend/src/pages/Hosts.jsx @@ -735,8 +735,8 @@ const Hosts = () => { const { data: hosts, isLoading, error, refetch } = useQuery({ queryKey: ['hosts'], queryFn: () => dashboardAPI.getHosts().then(res => res.data), - refetchInterval: 60000, - staleTime: 30000, + refetchInterval: 300000, // Refresh every 5 minutes instead of 1 minute + staleTime: 120000, // Consider data stale after 2 minutes }) const { data: hostGroups } = useQuery({ diff --git a/frontend/src/pages/Packages.jsx b/frontend/src/pages/Packages.jsx index 2cac8dd..0e1d9cd 100644 --- a/frontend/src/pages/Packages.jsx +++ b/frontend/src/pages/Packages.jsx @@ -101,16 +101,16 @@ const Packages = () => { const { data: packages, isLoading, error, refetch } = useQuery({ queryKey: ['packages'], queryFn: () => dashboardAPI.getPackages().then(res => res.data), - refetchInterval: 60000, - staleTime: 30000, + refetchInterval: 300000, // Refresh every 5 minutes instead of 1 minute + staleTime: 120000, // Consider data stale after 2 minutes }) // Fetch hosts data to get total packages count const { data: hosts } = useQuery({ queryKey: ['hosts'], queryFn: () => dashboardAPI.getHosts().then(res => res.data), - refetchInterval: 60000, - staleTime: 30000, + refetchInterval: 300000, // Refresh every 5 minutes instead of 1 minute + staleTime: 120000, // Consider data stale after 2 minutes }) // Filter and sort packages diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index f45c44c..5e20f6e 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -471,12 +471,12 @@ const Settings = () => {
- {formData.serverProtocol}://{formData.serverHost}:{formData.serverPort} + {formData.serverProtocol}://{formData.serverHost}{formData.serverProtocol === 'https' ? ':443' : `:${formData.serverPort}`}
This URL will be used in installation scripts and agent communications.
-