From d99a299bf5f17f696a080ae0809a6400ef581e07 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 23 Jul 2025 14:22:59 +0200 Subject: [PATCH] fix: Resolve backend permission errors for temp and logs directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix MinIO service temp directory path (was going to /temp instead of /app/temp) - Add TEMP_DIR environment variable support - Make audit logger optional in development mode to avoid permission issues - Ensure log directory exists before creating loggers - Update docker-entrypoint.sh to create temp directory - Create backend/temp directory with .gitkeep - Update .gitignore to exclude temp files but keep directory structure This fixes the EACCES permission errors that were causing the backend to restart. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .gitignore | 2 ++ backend/docker-entrypoint.sh | 5 +++ backend/src/services/minio.service.js | 2 +- backend/src/utils/logger.js | 52 +++++++++++++++++++-------- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 11b5578..1e9f36a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,8 @@ coverage/ temp/ tmp/ *.tmp +backend/temp/* +!backend/temp/.gitkeep # MinIO configuration .mc/ diff --git a/backend/docker-entrypoint.sh b/backend/docker-entrypoint.sh index d2f4b81..d47211a 100755 --- a/backend/docker-entrypoint.sh +++ b/backend/docker-entrypoint.sh @@ -6,5 +6,10 @@ if [ ! -d "/app/logs" ]; then mkdir -p /app/logs fi +# Ensure temp directory exists +if [ ! -d "/app/temp" ]; then + mkdir -p /app/temp +fi + # Start the application exec node src/app.js \ No newline at end of file diff --git a/backend/src/services/minio.service.js b/backend/src/services/minio.service.js index e6b8bef..93d838f 100644 --- a/backend/src/services/minio.service.js +++ b/backend/src/services/minio.service.js @@ -12,7 +12,7 @@ const execAsync = util.promisify(exec); class MinIOService { constructor(alias = config.minio.defaultAlias) { this.alias = alias; - this.tempDir = path.join(__dirname, '../../../temp'); + this.tempDir = process.env.TEMP_DIR || path.join(__dirname, '../../temp'); this.ensureTempDir(); } diff --git a/backend/src/utils/logger.js b/backend/src/utils/logger.js index cba7988..1774f4a 100644 --- a/backend/src/utils/logger.js +++ b/backend/src/utils/logger.js @@ -1,10 +1,20 @@ const winston = require('winston'); const DailyRotateFile = require('winston-daily-rotate-file'); const path = require('path'); +const fs = require('fs'); const config = require('../config'); const logDir = process.env.LOG_DIR || path.join(__dirname, '../../logs'); +// Ensure log directory exists +try { + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }); + } +} catch (error) { + console.error('Failed to create log directory:', error); +} + // Define log format const logFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), @@ -72,22 +82,30 @@ const logger = winston.createLogger({ }); // Create audit logger for security events -const auditLogger = winston.createLogger({ - level: 'info', - format: logFormat, - transports: [ - new DailyRotateFile({ - filename: path.join(logDir, 'audit-%DATE%.log'), - datePattern: 'YYYY-MM-DD', - maxSize: '20m', - maxFiles: '90d', - }) - ], -}); +let auditLogger; +if (config.app.env === 'production') { + auditLogger = winston.createLogger({ + level: 'info', + format: logFormat, + transports: [ + new DailyRotateFile({ + filename: path.join(logDir, 'audit-%DATE%.log'), + datePattern: 'YYYY-MM-DD', + maxSize: '20m', + maxFiles: '90d', + }) + ], + exitOnError: false, + }); +} else { + // In development, just use the main logger for audit events + auditLogger = logger; +} // Helper function for audit logging const logAudit = (action, { userId, ip, resource, status, details = {} }) => { - auditLogger.info({ + const auditEntry = { + audit: true, action, userId, ip, @@ -95,7 +113,13 @@ const logAudit = (action, { userId, ip, resource, status, details = {} }) => { status, details, timestamp: new Date().toISOString(), - }); + }; + + if (config.app.env === 'production') { + auditLogger.info(auditEntry); + } else { + logger.info('AUDIT:', auditEntry); + } }; module.exports = {