from fastapi import APIRouter, Depends, status from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import get_db from app.schemas.tenant import ( TenantConfigCreate, TenantConfigResponse, TenantCreate, TenantResponse, TenantUpdate, ) from app.services import tenant_service router = APIRouter(prefix="/tenants", tags=["tenants"]) @router.post("", response_model=TenantResponse, status_code=status.HTTP_201_CREATED) async def create_tenant( data: TenantCreate, session: AsyncSession = Depends(get_db) ) -> TenantResponse: tenant = await tenant_service.create_tenant(session, data.name, data.slug) return TenantResponse( id=tenant.id, name=tenant.name, slug=tenant.slug, status=tenant.status.value, created_at=tenant.created_at, updated_at=tenant.updated_at, ) @router.get("", response_model=list[TenantResponse]) async def list_tenants(session: AsyncSession = Depends(get_db)) -> list[TenantResponse]: tenants = await tenant_service.list_tenants(session) return [ TenantResponse( id=t.id, name=t.name, slug=t.slug, status=t.status.value, created_at=t.created_at, updated_at=t.updated_at, ) for t in tenants ] @router.get("/{tenant_id}", response_model=TenantResponse) async def get_tenant( tenant_id: str, session: AsyncSession = Depends(get_db) ) -> TenantResponse: tenant = await tenant_service.get_tenant(session, tenant_id) return TenantResponse( id=tenant.id, name=tenant.name, slug=tenant.slug, status=tenant.status.value, created_at=tenant.created_at, updated_at=tenant.updated_at, ) @router.patch("/{tenant_id}", response_model=TenantResponse) async def update_tenant( tenant_id: str, data: TenantUpdate, session: AsyncSession = Depends(get_db), ) -> TenantResponse: tenant = await tenant_service.update_tenant(session, tenant_id, data.name, data.slug) return TenantResponse( id=tenant.id, name=tenant.name, slug=tenant.slug, status=tenant.status.value, created_at=tenant.created_at, updated_at=tenant.updated_at, ) @router.delete("/{tenant_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_tenant(tenant_id: str, session: AsyncSession = Depends(get_db)) -> None: await tenant_service.delete_tenant(session, tenant_id) @router.put("/{tenant_id}/config", response_model=TenantConfigResponse) async def update_tenant_config( tenant_id: str, data: TenantConfigCreate, session: AsyncSession = Depends(get_db), ) -> TenantConfigResponse: config = await tenant_service.update_tenant_config( session, tenant_id, data.llm_provider, data.llm_api_key, data.llm_model, data.llm_base_url, data.max_tokens_per_month or 1000000, ) return TenantConfigResponse( id=config.id, tenant_id=config.tenant_id, llm_provider=config.llm_provider, llm_model=config.llm_model, llm_base_url=config.llm_base_url, max_tokens_per_month=config.max_tokens_per_month, created_at=config.created_at, updated_at=config.updated_at, ) class ProviderTestResponse(BaseModel): provider: str model: str status: str @router.post("/{tenant_id}/test-provider", response_model=ProviderTestResponse) async def test_provider( tenant_id: str, session: AsyncSession = Depends(get_db) ) -> ProviderTestResponse: provider = await tenant_service.get_provider_for_tenant(session, tenant_id) return ProviderTestResponse( provider=provider.__class__.__name__.replace("Provider", "").lower(), model=provider.model, status="ok", )