Files
HartOMat/backend/app/domains/tenants/router.py
T
Hartmut 251dd703ed feat(B2): add tenant model + migrations 035/036 + RLS policies
Migration 035: tenants table with 'Schaeffler' default seed.
Migration 036: tenant_id FK on all tables, RLS policies, backfill.
New domains/tenants/ with CRUD router (admin only).
All domain models extended with tenant_id FK.
core/database.py: get_db_for_tenant with RLS context setter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 16:30:41 +01:00

80 lines
2.4 KiB
Python

import uuid
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.utils.auth import require_admin
from app.domains.tenants.schemas import TenantCreate, TenantUpdate, TenantOut
from app.domains.tenants import service
router = APIRouter(prefix="/tenants", tags=["tenants"])
@router.get("/", response_model=list[TenantOut])
async def list_tenants(
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
):
rows = await service.list_tenants(db)
result = []
for row in rows:
tenant = row["tenant"]
out = TenantOut.model_validate(tenant)
out.user_count = row["user_count"]
result.append(out)
return result
@router.get("/{tenant_id}", response_model=TenantOut)
async def get_tenant(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
):
tenant = await service.get_tenant(db, tenant_id)
if not tenant:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")
return TenantOut.model_validate(tenant)
@router.post("/", response_model=TenantOut, status_code=status.HTTP_201_CREATED)
async def create_tenant(
body: TenantCreate,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
):
tenant = await service.create_tenant(db, name=body.name, slug=body.slug, is_active=body.is_active)
return TenantOut.model_validate(tenant)
@router.put("/{tenant_id}", response_model=TenantOut)
async def update_tenant(
tenant_id: uuid.UUID,
body: TenantUpdate,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
):
tenant = await service.update_tenant(
db, tenant_id,
name=body.name,
slug=body.slug,
is_active=body.is_active,
)
if not tenant:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tenant not found")
return TenantOut.model_validate(tenant)
@router.delete("/{tenant_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_tenant(
tenant_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
_: object = Depends(require_admin),
):
ok = await service.delete_tenant(db, tenant_id)
if not ok:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Tenant not found or still has users assigned",
)