kundencenter/migrations/036_impersonation.sql

8 lines
447 B
MySQL
Raw Permalink Normal View History

feat(customers): Impersonation ("als Kunde ansehen") mit Kennzeichnung und Audit Umsetzung von Ticket #35: Superadmin/Admin kann auf der Kundenseite "Als Kunde ansehen" wählen und sieht das Kundencenter zeitlich begrenzt (60 min) genau so, wie der Kunde es sieht - mit sichtbarem Banner und jederzeitigem "Zurück zur Verwaltung". Technisch keine zweite Anmeldung: die bestehende Staff-Sitzung wird um Impersonation-Felder erweitert (Migration 036). loadAuth() schaltet den Principal währenddessen echt auf kind='customer' mit einer Mitgliedschaft (Rolle "owner") in genau dieser Organisation um - eine tatsächliche Rechteeinschränkung, keine bloß andere Oberfläche: staff-only-Endpunkte sind währenddessen wirklich nicht mehr erreichbar (can() liefert für kind='customer' grundsätzlich false), und canInOrg-geschützte Routen funktionieren unverändert für genau diese eine Organisation. Die echte Staff-Identität (AuthContext.user) bleibt für das Audit unverändert erhalten. - POST /admin/customers/:id/impersonate (Recht customers.impersonate, nur admin/superadmin): Grund Pflichtfeld, setzt die Sitzung, protokolliert customer.impersonate.start mit beiden Identitäten (actorId = echter Staff-Nutzer, orgId = Kunde). - loadAuth() erkennt eine abgelaufene Impersonation automatisch, setzt die Sitzung zurück (kein harter Logout) und protokolliert customer.impersonate.end mit reason "expired". - POST /auth/impersonate/stop: manuelles Beenden, reason "manual". - Web: Banner in (app)/layout.tsx mit Grund und "Zurück"-Button; Formular mit Grund-Eingabe auf der Kundenseite. Gegen die echte Produktionsdatenbank end-to-end verifiziert: Start/Stopp, staff-only-Endpunkt während Impersonation korrekt mit 403 abgelehnt, eigene Organisation lesbar (200), fremde Organisation weiterhin 404 (keine Existenz verraten), künstlich abgelaufene Sitzung fällt automatisch auf die Staff-Identität zurück, Audit-Einträge zeigen durchgehend beide Identitäten. Erfüllt die im Ticket vorgegebenen Testschritte vollständig. Testsuite 58/59 (vorbestehende, unabhängige Flakiness in orders.test.ts). Audit-Kette und Backup+Wiederherstellungstest danach weiterhin grün. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 10:59:25 +02:00
-- Support-/Admin-Impersonation ("als Kunde ansehen"): zeitlich begrenzt, mit Grund, auf der bestehenden
-- Sitzung des Staff-Nutzers (kein zweiter Login nötig, "zurück" ist einfach die Sitzung zurücksetzen).
ALTER TABLE sessions
ADD COLUMN impersonating_org_id CHAR(36) NULL,
ADD COLUMN impersonation_reason VARCHAR(300) NULL,
ADD COLUMN impersonation_started_at DATETIME(3) NULL,
ADD COLUMN impersonation_expires_at DATETIME(3) NULL;