"""Reseller-Selbstverwaltung: ein Reseller verwaltet ausschließlich die von ihm angelegten Firmen (Firmen-Ebene, keine personenbezogenen Daten). RLS (app.reseller_id) erzwingt, dass nur eigene Firmen sichtbar/änderbar sind – ein Zugriff auf eine fremde Firmen-ID läuft ins Leere (404). """ from uuid import UUID from fastapi import APIRouter, Depends from fastapi import HTTPException from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.core.dependencies import require_role from app.models.audit_log import AuditLog from app.models.company import Company from app.models.user import User, UserRole from app.schemas.reseller import TenantCreate, TenantOut, TenantUpdate from app.services.tenant_service import tenant_service router = APIRouter(prefix="/reseller", tags=["Reseller"]) _reseller_roles = (UserRole.RESELLER,) @router.get("/companies", response_model=list[TenantOut]) async def list_my_companies( current_user: User = require_role(*_reseller_roles), db: AsyncSession = Depends(get_db), ): return await tenant_service.list_tenants(db) @router.post("/companies", response_model=TenantOut, status_code=201) async def create_company( data: TenantCreate, current_user: User = require_role(*_reseller_roles), db: AsyncSession = Depends(get_db), ): company = await tenant_service.create_tenant( data, actor=current_user, db=db, reseller_id=current_user.id, ) # Antwort aus der frisch erstellten Firma (Kennzahlen 1 Admin, 0 aktiv) return TenantOut( id=company.id, name=company.name, slug=company.slug, plan=company.plan, is_active=company.is_active, country=company.country, reseller_id=company.reseller_id, reseller_name=f"{current_user.first_name} {current_user.last_name}".strip(), user_count=1, active_user_count=0, admin_email=data.admin_email, ) @router.patch("/companies/{company_id}", response_model=TenantOut) async def update_company( company_id: UUID, data: TenantUpdate, current_user: User = require_role(*_reseller_roles), db: AsyncSession = Depends(get_db), ): company = await db.get(Company, company_id) # RLS gibt nur eigene Firmen frei → fremde/unbekannte ID = nicht sichtbar if company is None or company.reseller_id != current_user.id: raise HTTPException(status_code=404, detail="Firma nicht gefunden.") changes = data.model_dump(exclude_none=True) # Eigentümerschaft ist geprüft → Schreiben (inkl. AuditLog) unter kurzem Bypass, # da der Reseller keine app.company_id besitzt (audit_logs ist company-gefenced). await db.execute(text("SET LOCAL app.bypass_rls = 'on'")) try: for field, value in changes.items(): setattr(company, field, value) if changes: db.add(AuditLog( company_id=company.id, user_id=current_user.id, action="tenant_updated", entity_type="company", entity_id=company.id, new_value=changes, )) await db.flush() finally: await db.execute(text("SET LOCAL app.bypass_rls = 'off'")) tenants = {t.id: t for t in await tenant_service.list_tenants(db)} return tenants[company.id]