refactor(backend): standardize error responses, logging, pagination

- errorResponse(res, error, status, publicMessage) in routeHelpers,
  wired into 125 catch blocks across 10 route files; wire format
  ({ error: <string> }) unchanged byte-for-byte
- Replace remaining console.* with logger across src (178 sites);
  3 intentional console sites kept (install boot, unbound .catch ref)
- Adopt getPagination in 6 routes where semantics match exactly
This commit is contained in:
Paul Nothaft
2026-07-03 07:49:45 +02:00
parent d44ead41c5
commit 6eb46d8c31
41 changed files with 372 additions and 482 deletions
+4 -3
View File
@@ -1,4 +1,5 @@
const { db } = require('../database/db');
const logger = require('../utils/logger');
// Cache maintenance mode status to avoid DB queries on every request
let maintenanceMode = false;
@@ -26,7 +27,7 @@ async function queryWithRetry(queryFn, retries = MAX_RETRIES) {
error.code === 'ECONNRESET';
if (isConnectionError) {
console.warn(`Database connection error, retrying in ${RETRY_DELAY}ms... (attempt ${i + 1}/${retries})`);
logger.warn(`Database connection error, retrying in ${RETRY_DELAY}ms... (attempt ${i + 1}/${retries})`);
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
} else {
throw error; // Don't retry non-connection errors
@@ -56,7 +57,7 @@ async function checkMaintenanceMode() {
return maintenanceMode;
} catch (error) {
console.error('Error checking maintenance mode after retries:', error.message);
logger.error('Error checking maintenance mode after retries:', error.message);
// Return cached value or false if no cache
return maintenanceMode;
}
@@ -102,7 +103,7 @@ async function maintenanceMiddleware(req, res, next) {
}
} catch (error) {
// If we can't check maintenance mode, allow the request to proceed
console.error('Failed to check maintenance mode, allowing request:', error.message);
logger.error('Failed to check maintenance mode, allowing request:', error.message);
}
next();
@@ -333,7 +333,7 @@ class SecureImageMiddleware {
await db('security_logs').insert(logData).catch(console.error);
}
} catch (error) {
console.error('Error logging security event:', error);
logger.error('Error logging security event:', error);
}
}
@@ -363,7 +363,7 @@ class SecureImageMiddleware {
perHour: config.perHour || 500
};
} catch (error) {
console.error('Error getting rate limit settings:', error);
logger.error('Error getting rate limit settings:', error);
return { perMinute: 30, per5Minutes: 100, perHour: 500 };
}
}
+3 -2
View File
@@ -1,6 +1,7 @@
const path = require('path');
const express = require('express');
const { safePathJoin, isPathSafe } = require('../utils/fileSecurityUtils');
const logger = require('../utils/logger');
/**
* Create a secure static file serving middleware that prevents path traversal attacks
@@ -17,7 +18,7 @@ function secureStatic(basePath, options = {}) {
// Validate the path doesn't contain dangerous patterns
if (!isPathSafe(requestedPath)) {
console.warn(`Potential path traversal attempt blocked: ${requestedPath}`);
logger.warn(`Potential path traversal attempt blocked: ${requestedPath}`);
return res.status(403).json({ error: 'Access denied' });
}
@@ -52,7 +53,7 @@ function secureStatic(basePath, options = {}) {
return staticMiddleware(req, res, next);
} catch (error) {
// Path traversal detected
console.error(`Path traversal blocked: ${requestedPath}`, error.message);
logger.error(`Path traversal blocked: ${requestedPath}`, error.message);
return res.status(403).json({ error: 'Access denied' });
}
};
+2 -1
View File
@@ -1,6 +1,7 @@
const jwt = require('jsonwebtoken');
const { db } = require('../database/db');
const { getAdminTokenFromRequest } = require('../utils/tokenUtils');
const logger = require('../utils/logger');
// In-memory session tracking (in production, use Redis)
const sessions = new Map();
@@ -69,7 +70,7 @@ async function getSessionTimeout() {
} catch (error) {
// Only log if it's not a connection error (to avoid spam)
if (error.code !== 'ECONNRESET' && !error.message?.includes('Connection terminated')) {
console.error('Error getting session timeout:', error.message);
logger.error('Error getting session timeout:', error.message);
}
}