""" Router Virtual Box (Fase 2). Endpoint: POST /virtual-boxes → crea VBox GET /virtual-boxes → lista VBox del tenant GET /virtual-boxes/{id} → dettaglio VBox PATCH /virtual-boxes/{id} → aggiorna VBox (incluse caselle) DELETE /virtual-boxes/{id} → elimina VBox PUT /virtual-boxes/{id}/rules → sostituisce regole PUT /virtual-boxes/{id}/mailboxes → imposta caselle reali associate GET /virtual-boxes/{id}/mailboxes → lista caselle reali associate POST /virtual-boxes/{id}/assignments → assegna utenti DELETE /virtual-boxes/{id}/assignments/{user_id} → rimuovi assegnazione GET /virtual-boxes/{id}/assignments → lista utenti assegnati GET /virtual-boxes/my → VBox assegnate all'utente corrente """ import uuid from fastapi import APIRouter, Query from app.dependencies import AdminUser, CurrentUser, DB from app.schemas.virtual_box import ( AssignedUserResponse, MailboxBriefResponse, VirtualBoxAssignmentResponse, VirtualBoxAssignRequest, VirtualBoxCreate, VirtualBoxListResponse, VirtualBoxMailboxAssignRequest, VirtualBoxResponse, VirtualBoxRuleCreate, VirtualBoxUpdate, ) from app.services.virtual_box_service import VirtualBoxService router = APIRouter(prefix="/virtual-boxes", tags=["Virtual Box"]) # ─── CRUD ───────────────────────────────────────────────────────────────────── @router.post( "", response_model=VirtualBoxResponse, status_code=201, summary="Crea una nuova Virtual Box", ) async def create_virtual_box( body: VirtualBoxCreate, current_user: AdminUser, db: DB, ) -> VirtualBoxResponse: service = VirtualBoxService(db) vbox = await service.create(current_user.tenant_id, body, current_user.id) return _to_response(vbox) @router.get( "", response_model=VirtualBoxListResponse, summary="Lista Virtual Box del tenant", ) async def list_virtual_boxes( current_user: AdminUser, db: DB, page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), active_only: bool = Query(False), ) -> VirtualBoxListResponse: service = VirtualBoxService(db) items, total = await service.list_vboxes( current_user.tenant_id, page, page_size, active_only ) return VirtualBoxListResponse( items=[_to_response(v) for v in items], total=total, page=page, page_size=page_size, ) @router.get( "/my", response_model=list[VirtualBoxResponse], summary="Virtual Box assegnate all'utente corrente", ) async def my_virtual_boxes( current_user: CurrentUser, db: DB, ) -> list[VirtualBoxResponse]: service = VirtualBoxService(db) items = await service.list_user_vboxes(current_user.id, current_user.tenant_id) return [_to_response(v) for v in items] @router.get( "/{vbox_id}", response_model=VirtualBoxResponse, summary="Dettaglio Virtual Box", ) async def get_virtual_box( vbox_id: uuid.UUID, current_user: AdminUser, db: DB, ) -> VirtualBoxResponse: service = VirtualBoxService(db) vbox = await service.get(vbox_id, current_user.tenant_id) return _to_response(vbox) @router.patch( "/{vbox_id}", response_model=VirtualBoxResponse, summary="Aggiorna Virtual Box", description=( "Aggiorna i metadati della Virtual Box. " "Se `mailbox_ids` è fornito, sostituisce completamente le caselle PEC associate." ), ) async def update_virtual_box( vbox_id: uuid.UUID, body: VirtualBoxUpdate, current_user: AdminUser, db: DB, ) -> VirtualBoxResponse: service = VirtualBoxService(db) vbox = await service.update(vbox_id, current_user.tenant_id, body) return _to_response(vbox) @router.delete( "/{vbox_id}", status_code=204, summary="Elimina Virtual Box", ) async def delete_virtual_box( vbox_id: uuid.UUID, current_user: AdminUser, db: DB, ) -> None: service = VirtualBoxService(db) await service.delete(vbox_id, current_user.tenant_id) # ─── Regole ─────────────────────────────────────────────────────────────────── @router.put( "/{vbox_id}/rules", response_model=VirtualBoxResponse, summary="Sostituisce le regole di una Virtual Box", description="Rimpiazza completamente il set di regole. Inviare lista vuota per azzerarle.", ) async def replace_rules( vbox_id: uuid.UUID, body: list[VirtualBoxRuleCreate], current_user: AdminUser, db: DB, ) -> VirtualBoxResponse: service = VirtualBoxService(db) vbox = await service.replace_rules(vbox_id, current_user.tenant_id, body) return _to_response(vbox) # ─── Caselle Reali ──────────────────────────────────────────────────────────── @router.put( "/{vbox_id}/mailboxes", response_model=VirtualBoxResponse, summary="Imposta le caselle PEC reali associate alla Virtual Box", description=( "Sostituisce completamente l'elenco delle caselle PEC reali collegate. " "Inviare una lista vuota per rimuovere tutte le associazioni." ), ) async def set_mailboxes( vbox_id: uuid.UUID, body: VirtualBoxMailboxAssignRequest, current_user: AdminUser, db: DB, ) -> VirtualBoxResponse: service = VirtualBoxService(db) vbox = await service.set_mailboxes(vbox_id, current_user.tenant_id, body.mailbox_ids) return _to_response(vbox) @router.get( "/{vbox_id}/mailboxes", response_model=list[MailboxBriefResponse], summary="Lista caselle PEC reali associate alla Virtual Box", ) async def list_mailboxes( vbox_id: uuid.UUID, current_user: AdminUser, db: DB, ) -> list[MailboxBriefResponse]: service = VirtualBoxService(db) mailboxes = await service.list_mailboxes(vbox_id, current_user.tenant_id) return [MailboxBriefResponse.model_validate(m) for m in mailboxes] # ─── Assegnazioni ───────────────────────────────────────────────────────────── @router.post( "/{vbox_id}/assignments", response_model=list[VirtualBoxAssignmentResponse], status_code=201, summary="Assegna utenti a una Virtual Box", ) async def assign_users( vbox_id: uuid.UUID, body: VirtualBoxAssignRequest, current_user: AdminUser, db: DB, ) -> list[VirtualBoxAssignmentResponse]: service = VirtualBoxService(db) assignments = await service.assign_users( vbox_id, current_user.tenant_id, body.user_ids, current_user.id ) return [VirtualBoxAssignmentResponse.model_validate(a) for a in assignments] @router.delete( "/{vbox_id}/assignments/{user_id}", status_code=204, summary="Rimuovi assegnazione utente", ) async def unassign_user( vbox_id: uuid.UUID, user_id: uuid.UUID, current_user: AdminUser, db: DB, ) -> None: service = VirtualBoxService(db) await service.unassign_user(vbox_id, current_user.tenant_id, user_id) @router.get( "/{vbox_id}/assignments", response_model=list[AssignedUserResponse], summary="Lista utenti assegnati a una Virtual Box", ) async def list_assigned_users( vbox_id: uuid.UUID, current_user: AdminUser, db: DB, ) -> list[AssignedUserResponse]: service = VirtualBoxService(db) rows = await service.list_assigned_users(vbox_id, current_user.tenant_id) return [AssignedUserResponse(**row) for row in rows] # ─── Helper ─────────────────────────────────────────────────────────────────── def _to_response(vbox) -> VirtualBoxResponse: """Costruisce la risposta includendo regole, conteggio assegnazioni e caselle reali.""" from app.schemas.virtual_box import VirtualBoxRuleResponse rules = [VirtualBoxRuleResponse.model_validate(r) for r in (vbox.rules or [])] mailboxes = [ MailboxBriefResponse.model_validate(m) for m in (vbox.mailboxes or []) ] return VirtualBoxResponse( id=vbox.id, tenant_id=vbox.tenant_id, name=vbox.name, description=vbox.description, label=vbox.label, is_active=vbox.is_active, created_by=vbox.created_by, created_at=vbox.created_at, updated_at=vbox.updated_at, rules=rules, assignment_count=len(vbox.assignments or []), mailboxes=mailboxes, )