"""Permission delegation routes — CRUD API for temporary permission handovers.""" from __future__ import annotations import uuid from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.db import get_db from app.deps import require_permission from app.schemas.delegation import DelegationCreate, DelegationUpdate from app.services import delegation_service router = APIRouter(prefix="/api/v1/delegations", tags=["delegations"]) @router.get("") async def list_delegations( direction: str = Query("all", pattern="^(from|to|all)$"), db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("delegations:read")), ): """List delegations for the current user.""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) items = await delegation_service.list_delegations(db, tenant_id, user_id, direction) return {"items": items, "total": len(items)} @router.post("", status_code=status.HTTP_201_CREATED) async def create_delegation( body: DelegationCreate, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("delegations:write")), ): """Create a new permission delegation.""" tenant_id = uuid.UUID(current_user["tenant_id"]) from_user_id = uuid.UUID(current_user["user_id"]) try: return await delegation_service.create_delegation( db, tenant_id, from_user_id=from_user_id, to_user_id=uuid.UUID(body.to_user_id), start_at=body.start_at, end_at=body.end_at, scope=body.scope, ) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) from e @router.put("/{delegation_id}") async def update_delegation( delegation_id: str, body: DelegationUpdate, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("delegations:write")), ): """Update an existing delegation.""" tenant_id = uuid.UUID(current_user["tenant_id"]) try: return await delegation_service.update_delegation( db, tenant_id, delegation_id, start_at=body.start_at, end_at=body.end_at, scope=body.scope, active=body.active, ) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) from e @router.delete("/{delegation_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_delegation( delegation_id: str, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("delegations:write")), ): """Delete a delegation.""" tenant_id = uuid.UUID(current_user["tenant_id"]) try: await delegation_service.delete_delegation(db, tenant_id, delegation_id) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) from e @router.get("/active") async def check_active_delegation( db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("delegations:read")), ): """Check if the current user has any active delegations.""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) is_active = await delegation_service.is_delegation_active(db, user_id, tenant_id) active_list = await delegation_service.get_active_delegations(db, user_id, tenant_id) return { "is_active": is_active, "active_delegations": active_list, "count": len(active_list), }