feat: Reseller-Rolle + SUPER_ADMIN-Mandantenübersicht
Mandantenfähigkeit ausgebaut: - Neue Rolle RESELLER (company_id NULL); companies.reseller_id + is_active - RLS-Erweiterung (Migration 0034): companies/users zusätzlich auf app.reseller_id gefenced → Reseller sieht/verwaltet DB-seitig nur eigene Firmen, keine personenbezogenen Zeit-/Abwesenheitsdaten (DSGVO: nur Verwaltung) - get_current_user setzt app.reseller_id + Bypass aus für RESELLER - tenant_service: Firma + Erst-Admin (Einladung), Übersicht mit Kennzahlen - Router /reseller/* (Self-Service) und /admin/* (SUPER_ADMIN: Mandanten + Reseller) - Login-Sperre bei deaktiviertem Mandanten - Frontend: TenantsPage (/admin/tenants), eigene ResellerCompaniesPage (/reseller), rollenbasierte Login-Weiterleitung, Nav "Mandanten" für SUPER_ADMIN - 4 neue Tests inkl. Cross-Reseller-RLS-Isolation; 172/172 grün Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,15 @@ async def get_current_user(
|
||||
# Every other role gets the RLS fence applied: set company_id and disable
|
||||
# bypass so subsequent queries in the same transaction are automatically
|
||||
# filtered to the user's company.
|
||||
if user.role != UserRole.SUPER_ADMIN and user.company_id is not None:
|
||||
if user.role == UserRole.RESELLER:
|
||||
# Reseller ist an keine Firma gebunden (company_id IS NULL), darf aber
|
||||
# NICHT alles sehen. Statt company_id setzen wir app.reseller_id und
|
||||
# deaktivieren den Bypass → RLS-Policies geben nur Firmen frei, deren
|
||||
# reseller_id == diesem User entspricht (plus deren User zum Verwalten).
|
||||
safe_reseller_id = str(_uuid.UUID(str(user.id)))
|
||||
await db.execute(text(f"SET LOCAL app.reseller_id = '{safe_reseller_id}'"))
|
||||
await db.execute(text("SET LOCAL app.bypass_rls = 'off'"))
|
||||
elif user.role != UserRole.SUPER_ADMIN and user.company_id is not None:
|
||||
# Sicherheits-Invariante: safe_company_id muss eine valide UUID sein.
|
||||
# Der _uuid.UUID()-Round-Trip verhindert SQL-Injection auch bei zukünftigen
|
||||
# Refactorings (z.B. falls user.company_id einmal ein String aus einem
|
||||
|
||||
Reference in New Issue
Block a user