Passwort-Komplexität + Portal-Credentials-UX
validatePasswordComplexity (12 Zeichen, Groß/Klein/Zahl/Sonderzeichen) zentral in passwordGenerator.ts; jetzt erzwungen in setPortalPassword, confirmPasswordReset, register, createUser, updateUser. Neue Endpoints: - POST /customers/:id/portal/password/generate → 16-Zeichen Zufallspasswort - POST /customers/:id/portal/send-credentials → Versand per Mail (nur wenn portalEnabled aktiv) Frontend (CustomerDetail): Generate-Button vor Setzen, Send-Credentials nach gesetztem Passwort, Live-Komplexitäts-Hint (✓/○) während Eingabe, alert() durch Toast-Notifications ersetzt. Live-verifiziert: schwaches Passwort → 400 mit Detail-Fehler, komplexes Passwort → 200, Generator liefert 16-Zeichen-Passwort. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import * as authService from '../services/auth.service.js';
|
||||
import { AuthRequest, ApiResponse } from '../types/index.js';
|
||||
import prisma from '../lib/prisma.js';
|
||||
import { emit as emitSecurityEvent, contextFromRequest } from '../services/securityMonitor.service.js';
|
||||
import { validatePasswordComplexity } from '../utils/passwordGenerator.js';
|
||||
|
||||
// Refresh-Token-Cookie-Konfiguration. Der Cookie:
|
||||
// - httpOnly → kein JavaScript-Zugriff → bei XSS nicht klaubar
|
||||
@@ -223,10 +224,11 @@ export async function confirmPasswordReset(req: Request, res: Response): Promise
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.length < 6) {
|
||||
const complexity = validatePasswordComplexity(password);
|
||||
if (!complexity.ok) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Das Passwort muss mindestens 6 Zeichen lang sein',
|
||||
error: 'Passwort erfüllt Mindestanforderungen nicht: ' + complexity.errors.join(', '),
|
||||
} as ApiResponse);
|
||||
return;
|
||||
}
|
||||
@@ -355,6 +357,15 @@ export async function register(req: Request, res: Response): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
const complexity = validatePasswordComplexity(password);
|
||||
if (!complexity.ok) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Passwort erfüllt Mindestanforderungen nicht: ' + complexity.errors.join(', '),
|
||||
} as ApiResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await authService.createUser({
|
||||
email,
|
||||
password,
|
||||
|
||||
Reference in New Issue
Block a user