fix(backend): lint errors

This commit is contained in:
tigattack
2025-09-25 01:39:18 +01:00
parent 03802daf13
commit 22f6befc89
15 changed files with 91 additions and 106 deletions

View File

@@ -58,9 +58,13 @@ async function checkDatabaseConnection(prisma) {
// Wait for database to be available with retry logic
async function waitForDatabase(prisma, options = {}) {
const maxAttempts =
options.maxAttempts || parseInt(process.env.PM_DB_CONN_MAX_ATTEMPTS) || 30;
options.maxAttempts ||
parseInt(process.env.PM_DB_CONN_MAX_ATTEMPTS, 10) ||
30;
const waitInterval =
options.waitInterval || parseInt(process.env.PM_DB_CONN_WAIT_INTERVAL) || 2;
options.waitInterval ||
parseInt(process.env.PM_DB_CONN_WAIT_INTERVAL, 10) ||
2;
console.log(
`Waiting for database connection (max ${maxAttempts} attempts, ${waitInterval}s interval)...`,
@@ -75,7 +79,7 @@ async function waitForDatabase(prisma, options = {}) {
);
return true;
}
} catch (error) {
} catch {
// checkDatabaseConnection already logs the error
}

View File

@@ -6,8 +6,8 @@ const prisma = new PrismaClient();
// Middleware to verify JWT token
const authenticateToken = async (req, res, next) => {
try {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1]; // Bearer TOKEN
const authHeader = req.headers.authorization;
const token = authHeader?.split(" ")[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({ error: "Access token required" });
@@ -70,10 +70,10 @@ const requireAdmin = (req, res, next) => {
};
// Middleware to check if user is authenticated (optional)
const optionalAuth = async (req, res, next) => {
const optionalAuth = async (req, _res, next) => {
try {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
const authHeader = req.headers.authorization;
const token = authHeader?.split(" ")[1];
if (token) {
const decoded = jwt.verify(
@@ -94,12 +94,12 @@ const optionalAuth = async (req, res, next) => {
},
});
if (user && user.is_active) {
if (user?.is_active) {
req.user = user;
}
}
next();
} catch (error) {
} catch {
// Continue without authentication for optional auth
next();
}

View File

@@ -3,7 +3,7 @@ const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { PrismaClient } = require("@prisma/client");
const { body, validationResult } = require("express-validator");
const { authenticateToken, requireAdmin } = require("../middleware/auth");
const { authenticateToken, _requireAdmin } = require("../middleware/auth");
const {
requireViewUsers,
requireManageUsers,
@@ -17,7 +17,7 @@ const router = express.Router();
const prisma = new PrismaClient();
// Check if any admin users exist (for first-time setup)
router.get("/check-admin-users", async (req, res) => {
router.get("/check-admin-users", async (_req, res) => {
try {
const adminCount = await prisma.users.count({
where: { role: "admin" },
@@ -143,7 +143,7 @@ router.get(
"/admin/users",
authenticateToken,
requireViewUsers,
async (req, res) => {
async (_req, res) => {
try {
const users = await prisma.users.findMany({
select: {
@@ -527,7 +527,7 @@ router.post(
);
// Check if signup is enabled (public endpoint)
router.get("/signup-enabled", async (req, res) => {
router.get("/signup-enabled", async (_req, res) => {
try {
const settings = await prisma.settings.findFirst();
res.json({ signupEnabled: settings?.signup_enabled || false });
@@ -990,7 +990,7 @@ router.put(
);
// Logout (client-side token removal)
router.post("/logout", authenticateToken, async (req, res) => {
router.post("/logout", authenticateToken, async (_req, res) => {
try {
res.json({
message: "Logout successful",

View File

@@ -218,7 +218,7 @@ router.put(
updated_at: new Date(),
}));
const createdPreferences = await prisma.dashboard_preferences.createMany({
await prisma.dashboard_preferences.createMany({
data: newPreferences,
});
@@ -234,7 +234,7 @@ router.put(
);
// Get default dashboard card configuration
router.get("/defaults", authenticateToken, async (req, res) => {
router.get("/defaults", authenticateToken, async (_req, res) => {
try {
// This provides a comprehensive dashboard view for all new users
const defaultCards = [

View File

@@ -17,7 +17,7 @@ router.get(
"/stats",
authenticateToken,
requireViewDashboard,
async (req, res) => {
async (_req, res) => {
try {
const now = new Date();
@@ -179,7 +179,7 @@ router.get(
);
// Get hosts with their update status
router.get("/hosts", authenticateToken, requireViewHosts, async (req, res) => {
router.get("/hosts", authenticateToken, requireViewHosts, async (_req, res) => {
try {
const hosts = await prisma.hosts.findMany({
// Show all hosts regardless of status
@@ -269,7 +269,7 @@ router.get(
"/packages",
authenticateToken,
requireViewPackages,
async (req, res) => {
async (_req, res) => {
try {
const packages = await prisma.packages.findMany({
where: {
@@ -397,7 +397,7 @@ router.get(
"/recent-users",
authenticateToken,
requireViewUsers,
async (req, res) => {
async (_req, res) => {
try {
const users = await prisma.users.findMany({
where: {
@@ -430,7 +430,7 @@ router.get(
"/recent-collection",
authenticateToken,
requireViewHosts,
async (req, res) => {
async (_req, res) => {
try {
const hosts = await prisma.hosts.findMany({
select: {

View File

@@ -1,7 +1,7 @@
const express = require("express");
const { body, validationResult } = require("express-validator");
const { PrismaClient } = require("@prisma/client");
const { randomUUID } = require("crypto");
const { randomUUID } = require("node:crypto");
const { authenticateToken } = require("../middleware/auth");
const { requireManageHosts } = require("../middleware/permissions");
@@ -9,7 +9,7 @@ const router = express.Router();
const prisma = new PrismaClient();
// Get all host groups
router.get("/", authenticateToken, async (req, res) => {
router.get("/", authenticateToken, async (_req, res) => {
try {
const hostGroups = await prisma.host_groups.findMany({
include: {

View File

@@ -2,11 +2,10 @@ const express = require("express");
const { PrismaClient } = require("@prisma/client");
const { body, validationResult } = require("express-validator");
const { v4: uuidv4 } = require("uuid");
const bcrypt = require("bcryptjs");
const crypto = require("crypto");
const path = require("path");
const fs = require("fs");
const { authenticateToken, requireAdmin } = require("../middleware/auth");
const crypto = require("node:crypto");
const path = require("node:path");
const fs = require("node:fs");
const { authenticateToken, _requireAdmin } = require("../middleware/auth");
const {
requireManageHosts,
requireManageSettings,
@@ -48,7 +47,7 @@ router.get("/agent/download", async (req, res) => {
}
// Use script content from database if available, otherwise fallback to file
if (agentVersion && agentVersion.script_content) {
if (agentVersion?.script_content) {
// Convert Windows line endings to Unix line endings
const scriptContent = agentVersion.script_content
.replace(/\r\n/g, "\n")
@@ -88,7 +87,7 @@ router.get("/agent/download", async (req, res) => {
});
// Version check endpoint for agents
router.get("/agent/version", async (req, res) => {
router.get("/agent/version", async (_req, res) => {
try {
const currentVersion = await prisma.agent_versions.findFirst({
where: { is_current: true },
@@ -235,7 +234,7 @@ router.post(
);
// Legacy register endpoint (deprecated - returns error message)
router.post("/register", async (req, res) => {
router.post("/register", async (_req, res) => {
res.status(400).json({
error:
"Host registration has been disabled. Please contact your administrator to add this host to PatchMon.",
@@ -517,7 +516,7 @@ router.post(
try {
const settings = await prisma.settings.findFirst();
// Check both global auto-update setting AND host-specific auto-update setting
if (settings && settings.auto_update && host.auto_update) {
if (settings?.auto_update && host.auto_update) {
// Get current agent version from the request
const currentAgentVersion = req.body.agentVersion;
@@ -863,7 +862,7 @@ router.get(
"/admin/list",
authenticateToken,
requireManageHosts,
async (req, res) => {
async (_req, res) => {
try {
const hosts = await prisma.hosts.findMany({
select: {
@@ -1089,10 +1088,10 @@ router.patch(
);
// Serve the installation script
router.get("/install", async (req, res) => {
router.get("/install", async (_req, res) => {
try {
const fs = require("fs");
const path = require("path");
const fs = require("node:fs");
const path = require("node:path");
const scriptPath = path.join(
__dirname,
@@ -1144,7 +1143,7 @@ router.get(
"/agent/versions",
authenticateToken,
requireManageSettings,
async (req, res) => {
async (_req, res) => {
try {
const versions = await prisma.agent_versions.findMany({
orderBy: { created_at: "desc" },

View File

@@ -1,6 +1,5 @@
const express = require("express");
const { PrismaClient } = require("@prisma/client");
const { body, validationResult } = require("express-validator");
const router = express.Router();
const prisma = new PrismaClient();
@@ -17,8 +16,8 @@ router.get("/", async (req, res) => {
isSecurityUpdate = "",
} = req.query;
const skip = (parseInt(page) - 1) * parseInt(limit);
const take = parseInt(limit);
const skip = (parseInt(page, 10) - 1) * parseInt(limit, 10);
const take = parseInt(limit, 10);
// Build where clause
const where = {
@@ -139,10 +138,10 @@ router.get("/", async (req, res) => {
res.json({
packages: packagesWithStats,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
page: parseInt(page, 10),
limit: parseInt(limit, 10),
total: totalCount,
pages: Math.ceil(totalCount / parseInt(limit)),
pages: Math.ceil(totalCount / parseInt(limit, 10)),
},
});
} catch (error) {

View File

@@ -1,6 +1,6 @@
const express = require("express");
const { PrismaClient } = require("@prisma/client");
const { authenticateToken, requireAdmin } = require("../middleware/auth");
const { authenticateToken } = require("../middleware/auth");
const {
requireManageSettings,
requireManageUsers,
@@ -14,7 +14,7 @@ router.get(
"/roles",
authenticateToken,
requireManageUsers,
async (req, res) => {
async (_req, res) => {
try {
const permissions = await prisma.role_permissions.findMany({
orderBy: {

View File

@@ -11,7 +11,7 @@ const router = express.Router();
const prisma = new PrismaClient();
// Get all repositories with host count
router.get("/", authenticateToken, requireViewHosts, async (req, res) => {
router.get("/", authenticateToken, requireViewHosts, async (_req, res) => {
try {
const repositories = await prisma.repositories.findMany({
include: {
@@ -251,7 +251,7 @@ router.get(
"/stats/summary",
authenticateToken,
requireViewHosts,
async (req, res) => {
async (_req, res) => {
try {
const stats = await prisma.repositories.aggregate({
_count: true,
@@ -294,7 +294,7 @@ router.delete(
"/cleanup/orphaned",
authenticateToken,
requireManageHosts,
async (req, res) => {
async (_req, res) => {
try {
console.log("Cleaning up orphaned repositories...");

View File

@@ -45,8 +45,8 @@ async function triggerCrontabUpdates() {
// We'll use the existing ping endpoint but add a special parameter
// The agent will detect this and run update-crontab command
const http = require("http");
const https = require("https");
const http = require("node:http");
const https = require("node:https");
const url = new URL(`${serverUrl}/api/v1/hosts/ping`);
const isHttps = url.protocol === "https:";
@@ -106,7 +106,7 @@ async function triggerCrontabUpdates() {
}
// Get current settings
router.get("/", authenticateToken, requireManageSettings, async (req, res) => {
router.get("/", authenticateToken, requireManageSettings, async (_req, res) => {
try {
const settings = await getSettings();
console.log("Returning settings:", settings);
@@ -228,7 +228,7 @@ router.put(
);
// Get server URL for public use (used by installation scripts)
router.get("/server-url", async (req, res) => {
router.get("/server-url", async (_req, res) => {
try {
const settings = await getSettings();
const serverUrl = settings.server_url;
@@ -240,7 +240,7 @@ router.get("/server-url", async (req, res) => {
});
// Get update interval policy for agents (public endpoint)
router.get("/update-interval", async (req, res) => {
router.get("/update-interval", async (_req, res) => {
try {
const settings = await getSettings();
res.json({
@@ -254,7 +254,7 @@ router.get("/update-interval", async (req, res) => {
});
// Get auto-update policy for agents (public endpoint)
router.get("/auto-update", async (req, res) => {
router.get("/auto-update", async (_req, res) => {
try {
const settings = await getSettings();
res.json({

View File

@@ -150,7 +150,7 @@ router.post(
return res.status(400).json({ errors: errors.array() });
}
const { password } = req.body;
const { password: _password } = req.body;
const userId = req.user.id;
// Verify password
@@ -165,12 +165,12 @@ router.post(
});
}
// Note: In a real implementation, you would verify the password hash here
// FIXME: In a real implementation, you would verify the password hash here
// For now, we'll skip password verification for simplicity
// Disable TFA
await prisma.users.update({
where: { id: id },
where: { id: userId },
data: {
tfa_enabled: false,
tfa_secret: null,

View File

@@ -2,8 +2,8 @@ const express = require("express");
const { authenticateToken } = require("../middleware/auth");
const { requireManageSettings } = require("../middleware/permissions");
const { PrismaClient } = require("@prisma/client");
const { exec } = require("child_process");
const { promisify } = require("util");
const { exec } = require("node:child_process");
const { promisify } = require("node:util");
const prisma = new PrismaClient();
const execAsync = promisify(exec);
@@ -11,14 +11,14 @@ const execAsync = promisify(exec);
const router = express.Router();
// Get current version info
router.get("/current", authenticateToken, async (req, res) => {
router.get("/current", authenticateToken, async (_req, res) => {
try {
// Read version from package.json dynamically
let currentVersion = "1.2.6"; // fallback
try {
const packageJson = require("../../package.json");
if (packageJson && packageJson.version) {
if (packageJson?.version) {
currentVersion = packageJson.version;
}
} catch (packageError) {
@@ -78,8 +78,8 @@ router.post(
// Check if SSH key file exists and is readable
try {
require("fs").accessSync(sshKeyPath);
} catch (e) {
require("node:fs").accessSync(sshKeyPath);
} catch {
return res.status(400).json({
error: "SSH key file not found or not accessible",
details: `Cannot access: ${sshKeyPath}`,
@@ -165,7 +165,7 @@ router.get(
"/check-updates",
authenticateToken,
requireManageSettings,
async (req, res) => {
async (_req, res) => {
try {
// Get cached update information from settings
const settings = await prisma.settings.findFirst();
@@ -201,22 +201,4 @@ router.get(
},
);
// Simple version comparison function
function compareVersions(version1, version2) {
const v1Parts = version1.split(".").map(Number);
const v2Parts = version2.split(".").map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part > v2Part) return 1;
if (v1Part < v2Part) return -1;
}
return 0;
}
module.exports = router;

View File

@@ -20,7 +20,6 @@ const permissionsRoutes = require("./routes/permissionsRoutes");
const settingsRoutes = require("./routes/settingsRoutes");
const {
router: dashboardPreferencesRoutes,
createDefaultDashboardPreferences,
} = require("./routes/dashboardPreferencesRoutes");
const repositoryRoutes = require("./routes/repositoryRoutes");
const versionRoutes = require("./routes/versionRoutes");
@@ -63,9 +62,9 @@ async function checkAndImportAgentVersion() {
}
try {
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const fs = require("node:fs");
const path = require("node:path");
const crypto = require("node:crypto");
// Read and validate agent script
const agentScriptPath = path.join(
@@ -239,7 +238,7 @@ async function checkAndCreateRolePermissions() {
}
try {
const crypto = require("crypto");
const crypto = require("node:crypto");
// Define default roles and permissions
const defaultRoles = [
@@ -437,12 +436,12 @@ app.disable("x-powered-by");
// 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,
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS, 10) || 15 * 60 * 1000,
max: parseInt(process.env.RATE_LIMIT_MAX, 10) || 100,
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,
(parseInt(process.env.RATE_LIMIT_WINDOW_MS, 10) || 15 * 60 * 1000) / 1000,
),
},
standardHeaders: true,
@@ -523,7 +522,7 @@ if (process.env.ENABLE_LOGGING === "true") {
}
// Health check endpoint
app.get("/health", (req, res) => {
app.get("/health", (_req, res) => {
res.json({ status: "ok", timestamp: new Date().toISOString() });
});
@@ -532,12 +531,13 @@ const apiVersion = process.env.API_VERSION || "v1";
// 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,
windowMs:
parseInt(process.env.AUTH_RATE_LIMIT_WINDOW_MS, 10) || 10 * 60 * 1000,
max: parseInt(process.env.AUTH_RATE_LIMIT_MAX, 10) || 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) /
(parseInt(process.env.AUTH_RATE_LIMIT_WINDOW_MS, 10) || 10 * 60 * 1000) /
1000,
),
},
@@ -546,12 +546,13 @@ const authLimiter = rateLimit({
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,
windowMs: parseInt(process.env.AGENT_RATE_LIMIT_WINDOW_MS, 10) || 60 * 1000,
max: parseInt(process.env.AGENT_RATE_LIMIT_MAX, 10) || 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,
(parseInt(process.env.AGENT_RATE_LIMIT_WINDOW_MS, 10) || 60 * 1000) /
1000,
),
},
standardHeaders: true,
@@ -572,7 +573,7 @@ app.use(`/api/${apiVersion}/version`, versionRoutes);
app.use(`/api/${apiVersion}/tfa`, tfaRoutes);
// Error handling middleware
app.use((err, req, res, next) => {
app.use((err, _req, res, _next) => {
if (process.env.ENABLE_LOGGING === "true") {
logger.error(err.stack);
}
@@ -583,7 +584,7 @@ app.use((err, req, res, next) => {
});
// 404 handler
app.use("*", (req, res) => {
app.use("*", (_req, res) => {
res.status(404).json({ error: "Route not found" });
});

View File

@@ -1,6 +1,6 @@
const { PrismaClient } = require("@prisma/client");
const { exec } = require("child_process");
const { promisify } = require("util");
const { exec } = require("node:child_process");
const { promisify } = require("node:util");
const prisma = new PrismaClient();
const execAsync = promisify(exec);
@@ -112,7 +112,7 @@ class UpdateScheduler {
let currentVersion = "1.2.6"; // fallback
try {
const packageJson = require("../../package.json");
if (packageJson && packageJson.version) {
if (packageJson?.version) {
currentVersion = packageJson.version;
}
} catch (packageError) {
@@ -179,10 +179,10 @@ class UpdateScheduler {
for (const path of possibleKeyPaths) {
try {
require("fs").accessSync(path);
require("node:fs").accessSync(path);
sshKeyPath = path;
break;
} catch (e) {
} catch {
// Key not found at this path, try next
}
}
@@ -222,7 +222,7 @@ class UpdateScheduler {
let currentVersion = "1.2.6"; // fallback
try {
const packageJson = require("../../package.json");
if (packageJson && packageJson.version) {
if (packageJson?.version) {
currentVersion = packageJson.version;
}
} catch (packageError) {