2025-12-03 11:02:31 +01:00
|
|
|
"""Tenant management endpoints."""
|
|
|
|
|
|
|
|
|
|
import uuid
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, HTTPException, status
|
|
|
|
|
from sqlalchemy import select
|
|
|
|
|
|
|
|
|
|
from app.db import AsyncSessionDep
|
|
|
|
|
from app.models.tenant import Tenant
|
|
|
|
|
from app.schemas.tenant import TenantCreate, TenantResponse
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/tenants", tags=["Tenants"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --- Helper functions (embryonic service layer) ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def create_tenant(db: AsyncSessionDep, tenant_in: TenantCreate) -> Tenant:
|
|
|
|
|
"""Create a new tenant in the database."""
|
|
|
|
|
tenant = Tenant(
|
|
|
|
|
name=tenant_in.name,
|
|
|
|
|
domain=tenant_in.domain,
|
|
|
|
|
)
|
|
|
|
|
db.add(tenant)
|
|
|
|
|
await db.commit()
|
|
|
|
|
await db.refresh(tenant)
|
|
|
|
|
return tenant
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def get_tenants(db: AsyncSessionDep) -> list[Tenant]:
|
|
|
|
|
"""Retrieve all tenants from the database."""
|
|
|
|
|
result = await db.execute(select(Tenant).order_by(Tenant.created_at.desc()))
|
|
|
|
|
return list(result.scalars().all())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def get_tenant_by_id(db: AsyncSessionDep, tenant_id: uuid.UUID) -> Tenant | None:
|
|
|
|
|
"""Retrieve a tenant by ID."""
|
|
|
|
|
result = await db.execute(select(Tenant).where(Tenant.id == tenant_id))
|
|
|
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --- Route handlers (thin controllers) ---
|
|
|
|
|
|
|
|
|
|
|
2025-12-08 12:37:28 +01:00
|
|
|
@router.post("", response_model=TenantResponse, status_code=status.HTTP_201_CREATED)
|
2025-12-03 11:02:31 +01:00
|
|
|
async def create_tenant_endpoint(
|
|
|
|
|
tenant_in: TenantCreate,
|
|
|
|
|
db: AsyncSessionDep,
|
|
|
|
|
) -> Tenant:
|
|
|
|
|
"""
|
|
|
|
|
Create a new tenant.
|
|
|
|
|
|
|
|
|
|
- **name**: Unique tenant name (required)
|
|
|
|
|
- **domain**: Optional domain for the tenant
|
|
|
|
|
"""
|
|
|
|
|
return await create_tenant(db, tenant_in)
|
|
|
|
|
|
|
|
|
|
|
2025-12-08 12:37:28 +01:00
|
|
|
@router.get("", response_model=list[TenantResponse])
|
2025-12-03 11:02:31 +01:00
|
|
|
async def list_tenants_endpoint(db: AsyncSessionDep) -> list[Tenant]:
|
|
|
|
|
"""
|
|
|
|
|
List all tenants.
|
|
|
|
|
|
|
|
|
|
Returns a list of all registered tenants.
|
|
|
|
|
"""
|
|
|
|
|
return await get_tenants(db)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/{tenant_id}", response_model=TenantResponse)
|
|
|
|
|
async def get_tenant_endpoint(
|
|
|
|
|
tenant_id: uuid.UUID,
|
|
|
|
|
db: AsyncSessionDep,
|
|
|
|
|
) -> Tenant:
|
|
|
|
|
"""
|
|
|
|
|
Get a tenant by ID.
|
|
|
|
|
|
|
|
|
|
Returns the tenant with the specified UUID.
|
|
|
|
|
"""
|
|
|
|
|
tenant = await get_tenant_by_id(db, tenant_id)
|
|
|
|
|
if tenant is None:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail=f"Tenant {tenant_id} not found",
|
|
|
|
|
)
|
|
|
|
|
return tenant
|