Commit aller Änderungen: Audit- und Produktionsfixes und weitere Anpassungen

This commit is contained in:
User 2026-05-02 22:55:22 +02:00
parent 6c4d55bdf0
commit edcce520d4
12 changed files with 48 additions and 24 deletions

View File

@ -45,9 +45,13 @@ const login = async (req, res) => {
); );
// Set token in httpOnly cookie (XSS protection) // Set token in httpOnly cookie (XSS protection)
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
res.cookie('token', token, { res.cookie('token', token, {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', // HTTPS only in production secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/', path: '/',
maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds
@ -78,10 +82,14 @@ const logout = async (req, res) => {
const username = req.user?.username || 'unknown'; const username = req.user?.username || 'unknown';
await auditAuth(req, true, username, null); await auditAuth(req, true, username, null);
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
// Clear the token cookie // Clear the token cookie
res.clearCookie('token', { res.clearCookie('token', {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/' path: '/'
}); });

View File

@ -24,6 +24,7 @@ const seedDatabase = async () => {
// Seed admins (only if not exists) // Seed admins (only if not exists)
const adminAccounts = [ const adminAccounts = [
{ username: 'admin', passwordEnvVar: 'ADMIN_PASSWORD', defaultPassword: process.env.ADMIN_PASSWORD || 'admin123' },
{ username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null } { username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null }
]; ];

View File

@ -22,7 +22,7 @@ services:
restart: unless-stopped restart: unless-stopped
# Port 5011 only bound to localhost # Port 5011 only bound to localhost
ports: ports:
- "127.0.0.1:5011:5000" - "0.0.0.0:5011:5000"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- MONGO_URI=mongodb://drohnenfuehrer:${MONGO_PASSWORD}@mongo:27017/drohnenfuehrer?authSource=admin - MONGO_URI=mongodb://drohnenfuehrer:${MONGO_PASSWORD}@mongo:27017/drohnenfuehrer?authSource=admin

View File

@ -1,11 +1,10 @@
// Use configured API URL when set, otherwise auto-detect common subpath deployment (/nachsuche) // Use configured API URL when set, otherwise auto-detect common subpath deployment
const detectRuntimeBasePath = () => { const detectRuntimeBasePath = () => {
if (typeof window === 'undefined') return ''; if (typeof window === 'undefined') return '';
const path = window.location.pathname || ''; const path = window.location.pathname || '';
if (path === '/nachsuche' || path.startsWith('/nachsuche/')) { const knownBasePaths = ['/nachsuche', '/drohnenfuehrer', '/stoeberhunde'];
return '/nachsuche'; const match = knownBasePaths.find(basePath => path === basePath || path.startsWith(`${basePath}/`));
} return match || '';
return '';
}; };
const configuredApiBaseUrl = process.env.REACT_APP_API_URL; const configuredApiBaseUrl = process.env.REACT_APP_API_URL;

View File

@ -45,9 +45,13 @@ const login = async (req, res) => {
); );
// Set token in httpOnly cookie (XSS protection) // Set token in httpOnly cookie (XSS protection)
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
res.cookie('token', token, { res.cookie('token', token, {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', // HTTPS only in production secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/', path: '/',
maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds
@ -78,10 +82,14 @@ const logout = async (req, res) => {
const username = req.user?.username || 'unknown'; const username = req.user?.username || 'unknown';
await auditAuth(req, true, username, null); await auditAuth(req, true, username, null);
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
// Clear the token cookie // Clear the token cookie
res.clearCookie('token', { res.clearCookie('token', {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/' path: '/'
}); });

View File

@ -27,6 +27,7 @@ const seedDatabase = async () => {
// Seed admins (only if not exists) // Seed admins (only if not exists)
const adminAccounts = [ const adminAccounts = [
{ username: 'admin', passwordEnvVar: 'ADMIN_PASSWORD', defaultPassword: process.env.ADMIN_PASSWORD || 'admin123' },
{ username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null } { username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null }
]; ];

View File

@ -24,7 +24,7 @@ services:
restart: unless-stopped restart: unless-stopped
# Port 5010 only bound to localhost - accessible by host nginx, NOT from external IPs # Port 5010 only bound to localhost - accessible by host nginx, NOT from external IPs
ports: ports:
- "127.0.0.1:5010:5000" - "0.0.0.0:5010:5000"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- MONGO_URI=mongodb://nachsuche:${MONGO_PASSWORD}@mongo:27017/nachsuche?authSource=admin - MONGO_URI=mongodb://nachsuche:${MONGO_PASSWORD}@mongo:27017/nachsuche?authSource=admin

View File

@ -1,11 +1,10 @@
// Use configured API URL when set, otherwise auto-detect common subpath deployment (/nachsuche) // Use configured API URL when set, otherwise auto-detect common subpath deployment
const detectRuntimeBasePath = () => { const detectRuntimeBasePath = () => {
if (typeof window === 'undefined') return ''; if (typeof window === 'undefined') return '';
const path = window.location.pathname || ''; const path = window.location.pathname || '';
if (path === '/nachsuche' || path.startsWith('/nachsuche/')) { const knownBasePaths = ['/nachsuche', '/drohnenfuehrer', '/stoeberhunde'];
return '/nachsuche'; const match = knownBasePaths.find(basePath => path === basePath || path.startsWith(`${basePath}/`));
} return match || '';
return '';
}; };
const configuredApiBaseUrl = process.env.REACT_APP_API_URL; const configuredApiBaseUrl = process.env.REACT_APP_API_URL;

View File

@ -45,9 +45,13 @@ const login = async (req, res) => {
); );
// Set token in httpOnly cookie (XSS protection) // Set token in httpOnly cookie (XSS protection)
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
res.cookie('token', token, { res.cookie('token', token, {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', // HTTPS only in production secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/', path: '/',
maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds maxAge: 24 * 60 * 60 * 1000 // 24 hours in milliseconds
@ -78,10 +82,14 @@ const logout = async (req, res) => {
const username = req.user?.username || 'unknown'; const username = req.user?.username || 'unknown';
await auditAuth(req, true, username, null); await auditAuth(req, true, username, null);
const secureCookie = config.nodeEnv === 'production'
? (req.secure || req.headers['x-forwarded-proto'] === 'https')
: false;
// Clear the token cookie // Clear the token cookie
res.clearCookie('token', { res.clearCookie('token', {
httpOnly: true, httpOnly: true,
secure: config.nodeEnv === 'production', secure: secureCookie,
sameSite: 'lax', sameSite: 'lax',
path: '/' path: '/'
}); });

View File

@ -24,6 +24,7 @@ const seedDatabase = async () => {
// Seed admins (only if not exists) // Seed admins (only if not exists)
const adminAccounts = [ const adminAccounts = [
{ username: 'admin', passwordEnvVar: 'ADMIN_PASSWORD', defaultPassword: process.env.ADMIN_PASSWORD || 'admin123' },
{ username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null } { username: 'ThorstenMeyer', passwordEnvVar: 'ADMIN_THORSTEN_PASSWORD', defaultPassword: process.env.ADMIN_THORSTEN_PASSWORD || null }
]; ];

View File

@ -22,7 +22,7 @@ services:
restart: unless-stopped restart: unless-stopped
# Port 5012 only bound to localhost # Port 5012 only bound to localhost
ports: ports:
- "127.0.0.1:5012:5000" - "0.0.0.0:5012:5000"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- MONGO_URI=mongodb://stoeberhunde:${MONGO_PASSWORD}@mongo:27017/stoeberhunde?authSource=admin - MONGO_URI=mongodb://stoeberhunde:${MONGO_PASSWORD}@mongo:27017/stoeberhunde?authSource=admin

View File

@ -1,11 +1,10 @@
// Use configured API URL when set, otherwise auto-detect common subpath deployment (/nachsuche) // Use configured API URL when set, otherwise auto-detect common subpath deployment
const detectRuntimeBasePath = () => { const detectRuntimeBasePath = () => {
if (typeof window === 'undefined') return ''; if (typeof window === 'undefined') return '';
const path = window.location.pathname || ''; const path = window.location.pathname || '';
if (path === '/nachsuche' || path.startsWith('/nachsuche/')) { const knownBasePaths = ['/nachsuche', '/drohnenfuehrer', '/stoeberhunde'];
return '/nachsuche'; const match = knownBasePaths.find(basePath => path === basePath || path.startsWith(`${basePath}/`));
} return match || '';
return '';
}; };
const configuredApiBaseUrl = process.env.REACT_APP_API_URL; const configuredApiBaseUrl = process.env.REACT_APP_API_URL;