require('dotenv').config(); const APP_NAME = 'stoeberhunde'; const config = { appName: APP_NAME, port: process.env.PORT || 5000, mongoUri: process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/stoeberhunde', jwtSecret: process.env.STOEBERHUNDE_JWT_SECRET || process.env.JWT_SECRET || 'your-secret-key-change-in-production', jwtExpiresIn: process.env.JWT_EXPIRES_IN || '24h', nodeEnv: process.env.NODE_ENV || 'development', corsOrigin: process.env.CORS_ORIGIN ? process.env.CORS_ORIGIN.split(',') : ['http://localhost:5000'], geocodeUrl: process.env.GEOCODE_URL || 'https://nominatim.openstreetmap.org/search', geocodeUserAgent: process.env.GEOCODE_USER_AGENT || 'stoeberhunde-app/1.0 (admin@localhost)', geocodeMinDelayMs: parseInt(process.env.GEOCODE_MIN_DELAY_MS || '1100', 10), smtpConfigured: !!(process.env.SMTP_HOST && process.env.SMTP_USER && process.env.SMTP_PASS), // Basis fuer Links in E-Mails (Passwort-Reset). MUSS den Unterpfad enthalten, // unter dem die App ausgeliefert wird - der CORS_ORIGIN-Rueckfall kennt ihn // nicht und erzeugt sonst Links, die auf dem Portal statt in der App landen. appUrl: (process.env.APP_URL || `${(process.env.CORS_ORIGIN?.split(',')[0] || 'http://localhost:8082').replace(/\/+$/, '')}/${APP_NAME}` ).replace(/\/+$/, '') }; // Validate required environment variables const requiredVars = ['STOEBERHUNDE_JWT_SECRET', 'MONGO_URI']; const productionVars = ['ADMIN_THORSTEN_PASSWORD']; // Only warn in production // In test environment, use defaults if not set if (config.nodeEnv === 'test') { // Set test defaults if (!process.env.STOEBERHUNDE_JWT_SECRET && !process.env.JWT_SECRET) process.env.STOEBERHUNDE_JWT_SECRET = 'test-secret-key'; if (!process.env.MONGO_URI) process.env.MONGO_URI = 'mongodb://localhost:27017/test'; } else { // Always validate critical vars (except in test) requiredVars.forEach(varName => { // Accept legacy JWT_SECRET as fallback so existing deployments keep working if (!process.env[varName] && !process.env.JWT_SECRET) { console.error(`❌ Fehler: ${varName} muss gesetzt sein!`); console.error(` Tipp: Kopiere .env.example zu .env und fülle die Werte aus.`); process.exit(1); } }); } // Warn about missing production-specific vars if (config.nodeEnv === 'production') { productionVars.forEach(varName => { if (!process.env[varName]) { console.warn(`⚠️ Warnung: ${varName} sollte in Production gesetzt sein!`); } }); // Check for insecure defaults in production. // Nicht nur der eine Default-String: podman-compose.yml setzt z. B. // CHANGE_ME_IN_PRODUCTION, was eine reine Gleichheitspruefung durchlaesst. if (/change[-_ ]?me|change-in-production|your-secret|secret-key/i.test(config.jwtSecret)) { console.error('❌ Fehler: JWT_SECRET verwendet einen Platzhalter-Wert!'); console.error(' Bitte ein zufaelliges Secret setzen, z. B. mit: openssl rand -hex 32'); process.exit(1); } // Ohne APP_URL wird der Link in der Passwort-Reset-Mail aus CORS_ORIGIN // zusammengesetzt. Das funktioniert nur, solange der Unterpfad dem App-Namen // entspricht - bei abweichendem Deployment fuehrt der Link ins Leere. if (!process.env.APP_URL) { console.warn(`⚠️ Warnung: APP_URL ist nicht gesetzt. Reset-Links verwenden "${config.appUrl}".`); } } module.exports = config;