This commit is contained in:
betalabor.de
2026-04-24 20:13:01 +02:00
parent e39e905157
commit cd2172a0d3
3 changed files with 34 additions and 18 deletions

View File

@@ -17,11 +17,13 @@ services:
- HOST=0.0.0.0 - HOST=0.0.0.0
- PORT=4321 - PORT=4321
- NODE_ENV=production - NODE_ENV=production
# --- E-Mail SMTP Konfiguration (für Login Codes) --- # Diese Variablen werden dynamisch aus dem Portainer 'Env'-Tab gelesen:
# Entferne die Rauten (#) und trage deine echten Mail-Daten ein, - SESSION_SECRET=${SESSION_SECRET}
# damit die App E-Mails versenden kann: - APP_URL=${APP_URL}
# - SMTP_HOST=smtp.dein-provider.de - SMTP_HOST=${SMTP_HOST}
# - SMTP_PORT=587 - SMTP_PORT=${SMTP_PORT}
# - SMTP_USER=deine_email@domain.de - SMTP_SECURE=${SMTP_SECURE}
# - SMTP_PASS=dein_passwort - SMTP_USER=${SMTP_USER}
# - SMTP_FROM=Lebenslauf App <deine_email@domain.de> - SMTP_PASS=${SMTP_PASS}
- SMTP_FROM=${SMTP_FROM}
- OTP_EXPIRES_MINUTES=${OTP_EXPIRES_MINUTES:-10}

View File

@@ -4,20 +4,34 @@ import { upsertUser, setOTP, consumeOTP, createSession, getSession, deleteSessio
const SESSION_COOKIE = 'lv_session'; const SESSION_COOKIE = 'lv_session';
const SESSION_DAYS = 30; const SESSION_DAYS = 30;
const OTP_MINUTES = parseInt(import.meta.env.OTP_EXPIRES_MINUTES || '10');
// ── Mailer ──────────────────────────────────────────────────────────── function getEnv(key: string, metaFallback?: any): string | undefined {
if (typeof process !== 'undefined' && process.env && process.env[key]) {
return process.env[key];
}
return metaFallback;
}
const rawOtp = getEnv('OTP_EXPIRES_MINUTES', import.meta.env.OTP_EXPIRES_MINUTES) || '10';
const OTP_MINUTES = isNaN(parseInt(rawOtp)) ? 10 : parseInt(rawOtp);
// ─ Mailer ────────────────────────────────────────────────────────────
let _transport: nodemailer.Transporter | null = null; let _transport: nodemailer.Transporter | null = null;
function getTransport() { function getTransport() {
if (!_transport) { if (!_transport) {
const smtpUser = getEnv('SMTP_USER', import.meta.env.SMTP_USER);
const smtpPass = getEnv('SMTP_PASS', import.meta.env.SMTP_PASS);
const rawPort = getEnv('SMTP_PORT', import.meta.env.SMTP_PORT) || '587';
const smtpPort = isNaN(parseInt(rawPort)) ? 587 : parseInt(rawPort);
_transport = nodemailer.createTransport({ _transport = nodemailer.createTransport({
host: import.meta.env.SMTP_HOST || 'localhost', host: getEnv('SMTP_HOST', import.meta.env.SMTP_HOST) || 'localhost',
port: parseInt(import.meta.env.SMTP_PORT || '587'), port: smtpPort,
secure: import.meta.env.SMTP_SECURE === 'true', secure: getEnv('SMTP_SECURE', import.meta.env.SMTP_SECURE) === 'true',
auth: import.meta.env.SMTP_USER ? { auth: smtpUser ? {
user: import.meta.env.SMTP_USER, user: smtpUser,
pass: import.meta.env.SMTP_PASS, pass: smtpPass || '',
} : undefined, } : undefined,
tls: { tls: {
rejectUnauthorized: false rejectUnauthorized: false
@@ -50,7 +64,7 @@ export async function sendOTP(email: string, lang: string = 'de'): Promise<{ ok:
</div>`; </div>`;
await getTransport().sendMail({ await getTransport().sendMail({
from: import.meta.env.SMTP_FROM || 'Lebenslauf-App <noreply@localhost>', from: getEnv('SMTP_FROM', import.meta.env.SMTP_FROM) || 'Lebenslauf-App <noreply@localhost>',
to: email, to: email,
subject, subject,
html, html,

View File

@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
import type { CV, CVData, CVSettings } from '../types'; import type { CV, CVData, CVSettings } from '../types';
import { DEFAULT_DATA, DEFAULT_SETTINGS } from '../types'; import { DEFAULT_DATA, DEFAULT_SETTINGS } from '../types';
const DB_PATH = import.meta.env.DB_PATH || join(process.cwd(), 'data', 'lebenslauf.db'); const DB_PATH = process.env.DB_PATH || import.meta.env.DB_PATH || join(process.cwd(), 'data', 'lebenslauf.db');
const dir = dirname(DB_PATH); const dir = dirname(DB_PATH);
if (!existsSync(dir)) mkdirSync(dir, { recursive: true }); if (!existsSync(dir)) mkdirSync(dir, { recursive: true });