fcf4ecc324
Die drei letzten wichtigen Features für ein produktionsreifes 1.0.0: ## 1. Passwort vergessen-Flow Der klassische Selfservice-Reset per Email – sowohl für Mitarbeiter als auch für Portal-Kunden. User können sich nicht mehr aussperren, Admin muss nicht mehr manuell eingreifen. - Neues Link "Passwort vergessen?" auf Login-Seite - PasswordResetRequest: Email + Typ-Auswahl (Mitarbeiter / Portal) - PasswordResetConfirm: Token-basierte Bestätigung + neues Passwort (min 6 Zeichen) - Token ist 2 Stunden gültig, dann muss neu angefordert werden - Token ist kryptografisch sicher (crypto.randomBytes(32)) - User-Enumeration-Schutz: Backend gibt immer 200 zurück, egal ob Email existiert - Nach erfolgreichem Reset werden ALLE bestehenden Sessions gekickt (tokenInvalidatedAt gesetzt) – falls jemand parallel eingeloggt war DB: - User.passwordResetToken + passwordResetExpiresAt - Customer.portalPasswordResetToken + portalPasswordResetExpiresAt ## 2. Rate-Limiting gegen Brute-Force Mit express-rate-limit: - Login: 10 Versuche pro 15 Minuten pro IP. Erfolgreiche zählen nicht mit. - Passwort-Reset-Request: 5 Versuche pro Stunde pro IP (Mail-Flut verhindern) Sowohl Mitarbeiter-Login als auch Portal-Login geschützt. ## 3. Auto-Geburtstagsgrüße per Cron Das autoBirthdayGreeting-Flag hatten wir schon, aber kein Scheduler der ihn wirklich abschickt. Jetzt: - Läuft täglich um 08:00 Uhr - Findet Kunden mit heutigem Geburtstag + autoBirthdayGreeting=true - Nur Email-Kanal (Messenger brauchen Browser-Klick) - Catch-up 30s nach Server-Start: wenn Server am Geburtstag down war, wird beim nächsten Boot nachgeholt - lastBirthdayGreetingYear verhindert Doppelversand Dependencies: node-cron, @types/node-cron, express-rate-limit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
59 lines
1.6 KiB
JSON
59 lines
1.6 KiB
JSON
{
|
|
"name": "opencrm-backend",
|
|
"version": "1.0.0",
|
|
"description": "OpenCRM Backend API",
|
|
"main": "dist/index.js",
|
|
"prisma": {
|
|
"seed": "tsx prisma/seed.ts"
|
|
},
|
|
"scripts": {
|
|
"dev": "tsx watch src/index.ts",
|
|
"build": "tsc",
|
|
"start": "node dist/index.js",
|
|
"db:migrate": "prisma migrate dev",
|
|
"db:push": "prisma db push",
|
|
"db:seed": "tsx prisma/seed.ts",
|
|
"db:studio": "prisma studio",
|
|
"db:backup": "tsx prisma/backup-data.ts",
|
|
"db:restore": "tsx prisma/restore-data.ts",
|
|
"seed:defaults": "tsx scripts/seed-factory-defaults.ts"
|
|
},
|
|
"dependencies": {
|
|
"@prisma/client": "^5.22.0",
|
|
"adm-zip": "^0.5.16",
|
|
"archiver": "^7.0.1",
|
|
"bcryptjs": "^2.4.3",
|
|
"cors": "^2.8.5",
|
|
"dotenv": "^16.4.5",
|
|
"express": "^4.21.1",
|
|
"express-rate-limit": "^8.4.0",
|
|
"express-validator": "^7.2.0",
|
|
"imapflow": "^1.2.8",
|
|
"jsonwebtoken": "^9.0.2",
|
|
"mailparser": "^3.9.3",
|
|
"multer": "^1.4.5-lts.1",
|
|
"node-cron": "^4.2.1",
|
|
"nodemailer": "^7.0.13",
|
|
"pdf-lib": "^1.17.1",
|
|
"pdfkit": "^0.17.2",
|
|
"undici": "^6.23.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/adm-zip": "^0.5.7",
|
|
"@types/archiver": "^7.0.0",
|
|
"@types/bcryptjs": "^2.4.6",
|
|
"@types/cors": "^2.8.17",
|
|
"@types/express": "^4.17.25",
|
|
"@types/jsonwebtoken": "^9.0.7",
|
|
"@types/mailparser": "^3.4.6",
|
|
"@types/multer": "^1.4.12",
|
|
"@types/node": "^22.9.0",
|
|
"@types/node-cron": "^3.0.11",
|
|
"@types/nodemailer": "^7.0.9",
|
|
"@types/pdfkit": "^0.17.4",
|
|
"prisma": "^5.22.0",
|
|
"tsx": "^4.19.2",
|
|
"typescript": "^5.6.3"
|
|
}
|
|
}
|