fix: Resolve backend permission errors for temp and logs directories

- 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 <noreply@anthropic.com>
This commit is contained in:
2025-07-23 14:22:59 +02:00
parent 9cfd018d0d
commit d99a299bf5
4 changed files with 46 additions and 15 deletions
+2
View File
@@ -43,6 +43,8 @@ coverage/
temp/ temp/
tmp/ tmp/
*.tmp *.tmp
backend/temp/*
!backend/temp/.gitkeep
# MinIO configuration # MinIO configuration
.mc/ .mc/
+5
View File
@@ -6,5 +6,10 @@ if [ ! -d "/app/logs" ]; then
mkdir -p /app/logs mkdir -p /app/logs
fi fi
# Ensure temp directory exists
if [ ! -d "/app/temp" ]; then
mkdir -p /app/temp
fi
# Start the application # Start the application
exec node src/app.js exec node src/app.js
+1 -1
View File
@@ -12,7 +12,7 @@ const execAsync = util.promisify(exec);
class MinIOService { class MinIOService {
constructor(alias = config.minio.defaultAlias) { constructor(alias = config.minio.defaultAlias) {
this.alias = alias; this.alias = alias;
this.tempDir = path.join(__dirname, '../../../temp'); this.tempDir = process.env.TEMP_DIR || path.join(__dirname, '../../temp');
this.ensureTempDir(); this.ensureTempDir();
} }
+38 -14
View File
@@ -1,10 +1,20 @@
const winston = require('winston'); const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file'); const DailyRotateFile = require('winston-daily-rotate-file');
const path = require('path'); const path = require('path');
const fs = require('fs');
const config = require('../config'); const config = require('../config');
const logDir = process.env.LOG_DIR || path.join(__dirname, '../../logs'); 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 // Define log format
const logFormat = winston.format.combine( const logFormat = winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
@@ -72,22 +82,30 @@ const logger = winston.createLogger({
}); });
// Create audit logger for security events // Create audit logger for security events
const auditLogger = winston.createLogger({ let auditLogger;
level: 'info', if (config.app.env === 'production') {
format: logFormat, auditLogger = winston.createLogger({
transports: [ level: 'info',
new DailyRotateFile({ format: logFormat,
filename: path.join(logDir, 'audit-%DATE%.log'), transports: [
datePattern: 'YYYY-MM-DD', new DailyRotateFile({
maxSize: '20m', filename: path.join(logDir, 'audit-%DATE%.log'),
maxFiles: '90d', 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 // Helper function for audit logging
const logAudit = (action, { userId, ip, resource, status, details = {} }) => { const logAudit = (action, { userId, ip, resource, status, details = {} }) => {
auditLogger.info({ const auditEntry = {
audit: true,
action, action,
userId, userId,
ip, ip,
@@ -95,7 +113,13 @@ const logAudit = (action, { userId, ip, resource, status, details = {} }) => {
status, status,
details, details,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
}); };
if (config.app.env === 'production') {
auditLogger.info(auditEntry);
} else {
logger.info('AUDIT:', auditEntry);
}
}; };
module.exports = { module.exports = {