73 lines
3.4 KiB
JavaScript
73 lines
3.4 KiB
JavaScript
require('dotenv').config();
|
||
|
||
const APP_NAME = 'nachsuche';
|
||
|
||
const config = {
|
||
appName: APP_NAME,
|
||
port: process.env.PORT || 5000,
|
||
mongoUri: process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/tracking-leaders',
|
||
jwtSecret: process.env.NACHSUCHE_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 || 'tracking-leaders-app/1.0 (admin@localhost)',
|
||
geocodeMinDelayMs: parseInt(process.env.GEOCODE_MIN_DELAY_MS || '1100', 10),
|
||
// E-Mail / SMTP (required for password-reset emails; optional otherwise)
|
||
smtpConfigured: !!(process.env.SMTP_HOST && process.env.SMTP_USER && process.env.SMTP_PASS),
|
||
// Basis für Links in E-Mails (Passwort-Reset). MUSS den Unterpfad enthalten,
|
||
// unter dem die App ausgeliefert wird – der CORS_ORIGIN-Rückfall 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:8080').replace(/\/+$/, '')}/${APP_NAME}`
|
||
).replace(/\/+$/, '')
|
||
};
|
||
|
||
// Validate required environment variables
|
||
const requiredVars = ['NACHSUCHE_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.NACHSUCHE_JWT_SECRET && !process.env.JWT_SECRET) process.env.NACHSUCHE_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 Gleichheitsprüfung durchlässt.
|
||
if (/change[-_ ]?me|change-in-production|your-secret|changeme|secret-key/i.test(config.jwtSecret)) {
|
||
console.error('❌ Fehler: JWT_SECRET verwendet einen Platzhalter-Wert!');
|
||
console.error(' Bitte ein zufälliges 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 führt 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;
|