feat(PROJ-46): E-Mail als primärer Login-Identifier für Tenant-User

Tenant-User (tenant_id IS NOT NULL) melden sich künftig per E-Mail an statt
per Username — behebt Verwechslungen wie im Support-Fall vom 2026-06-13
(Login schlug trotz Passwort-Reset fehl, weil E-Mail statt Username
verwendet wurde). Nicht-Tenant-User (Superadmin/System) können weiterhin
Username ODER E-Mail nutzen.

Neue Store.VerifyLogin() prüft erst per E-Mail (alle User), fällt dann auf
Username zurück (nur tenant_id IS NULL). VerifyPassword() bleibt für den
IMAP-Server-Login-Pfad (PROJ-26) unverändert. Bewusster Breaking Change für
Tenant-User, Datenqualität vorab geprüft (0 Kollisionen).

Security-Nachtrag: bcrypt-Dummy-Compare im "user not found"-Pfad ergänzt,
um Timing-basierte Identifier-Enumeration zu verhindern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-07-03 23:37:20 +02:00
co-authored by Claude Sonnet 5
parent 804cd62201
commit 767373b206
18 changed files with 1710 additions and 14 deletions
+2
View File
@@ -107,6 +107,8 @@ func New(cfg Config) (*Store, error) {
_, _ = s.db.Exec(ctx, `ALTER TABLE emails ADD COLUMN IF NOT EXISTS storage_id BIGINT REFERENCES storage_objects(id)`)
// PROJ-51: archiving_rules table + retain_until_source column
s.initRetentionRulesSchema(ctx)
// PROJ-43: tenant_routing_rules table (pattern-based tenant assignment)
s.initTenantRoutingRulesSchema(ctx)
// PROJ-50: DSGVO Löschersuchen
s.initDSGVOSchema(ctx)
}