mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 20:55:41 +02:00
vboxes fix
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
"""
|
||||
Router tag (Label).
|
||||
|
||||
Endpoint:
|
||||
- GET /labels – elenca i tag del tenant
|
||||
- POST /labels – crea un nuovo tag (admin)
|
||||
- PATCH /labels/{id} – modifica un tag (admin)
|
||||
- DELETE /labels/{id} – elimina un tag (admin)
|
||||
|
||||
- GET /messages/{id}/labels – tag di un messaggio
|
||||
- PUT /messages/{id}/labels – imposta i tag di un messaggio (sostituisce)
|
||||
- POST /messages/{id}/labels/add – aggiunge tag a un messaggio
|
||||
- POST /messages/{id}/labels/remove – rimuove tag da un messaggio
|
||||
|
||||
- POST /messages/bulk-labels – aggiunge/rimuove tag in blocco
|
||||
|
||||
Permessi:
|
||||
- GET /labels: tutti gli utenti autenticati
|
||||
- POST/PATCH/DELETE: solo admin
|
||||
- Operazioni su messaggi: utenti con accesso alla casella del messaggio
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, status
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.core.exceptions import ForbiddenError, NotFoundError
|
||||
from app.dependencies import AdminUser, CurrentUser, DB
|
||||
from app.models.message import Message
|
||||
from app.schemas.label import (
|
||||
LabelCreate,
|
||||
LabelResponse,
|
||||
LabelUpdate,
|
||||
MessageBulkLabelRequest,
|
||||
MessageBulkLabelResponse,
|
||||
MessageLabelAddRequest,
|
||||
MessageLabelRemoveRequest,
|
||||
MessageLabelSetRequest,
|
||||
)
|
||||
from app.services.label_service import LabelService
|
||||
|
||||
router = APIRouter(tags=["Labels"])
|
||||
|
||||
|
||||
# ─── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
async def _check_message_access(
|
||||
message_id: uuid.UUID,
|
||||
current_user,
|
||||
db,
|
||||
) -> Message:
|
||||
"""Verifica che il messaggio esista e l'utente vi abbia accesso."""
|
||||
result = await db.execute(
|
||||
select(Message).where(
|
||||
Message.id == message_id,
|
||||
Message.tenant_id == current_user.tenant_id,
|
||||
)
|
||||
)
|
||||
message = result.scalar_one_or_none()
|
||||
if not message:
|
||||
raise NotFoundError(f"Messaggio {message_id} non trovato")
|
||||
|
||||
if not current_user.is_admin:
|
||||
from app.services.permission_service import PermissionService
|
||||
perm_svc = PermissionService(db)
|
||||
if not await perm_svc.check_can_read(current_user, message.mailbox_id):
|
||||
raise ForbiddenError("Accesso al messaggio non autorizzato")
|
||||
|
||||
return message
|
||||
|
||||
|
||||
# ─── CRUD Label ───────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/labels", response_model=list[LabelResponse])
|
||||
async def list_labels(
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> list[LabelResponse]:
|
||||
"""Elenca tutti i tag del tenant corrente."""
|
||||
svc = LabelService(db)
|
||||
labels = await svc.list_labels(current_user.tenant_id)
|
||||
return [LabelResponse.model_validate(l) for l in labels]
|
||||
|
||||
|
||||
@router.post("/labels", response_model=LabelResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_label(
|
||||
data: LabelCreate,
|
||||
current_user: AdminUser,
|
||||
db: DB,
|
||||
) -> LabelResponse:
|
||||
"""Crea un nuovo tag (solo admin)."""
|
||||
svc = LabelService(db)
|
||||
label = await svc.create_label(current_user.tenant_id, data)
|
||||
return LabelResponse.model_validate(label)
|
||||
|
||||
|
||||
@router.patch("/labels/{label_id}", response_model=LabelResponse)
|
||||
async def update_label(
|
||||
label_id: uuid.UUID,
|
||||
data: LabelUpdate,
|
||||
current_user: AdminUser,
|
||||
db: DB,
|
||||
) -> LabelResponse:
|
||||
"""Modifica un tag esistente (solo admin)."""
|
||||
svc = LabelService(db)
|
||||
label = await svc.update_label(current_user.tenant_id, label_id, data)
|
||||
return LabelResponse.model_validate(label)
|
||||
|
||||
|
||||
@router.delete("/labels/{label_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_label(
|
||||
label_id: uuid.UUID,
|
||||
current_user: AdminUser,
|
||||
db: DB,
|
||||
) -> None:
|
||||
"""Elimina un tag (solo admin). Viene rimosso automaticamente da tutti i messaggi."""
|
||||
svc = LabelService(db)
|
||||
await svc.delete_label(current_user.tenant_id, label_id)
|
||||
|
||||
|
||||
# ─── Tag su singolo messaggio ─────────────────────────────────────────────────
|
||||
|
||||
@router.get("/messages/{message_id}/labels", response_model=list[LabelResponse])
|
||||
async def get_message_labels(
|
||||
message_id: uuid.UUID,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> list[LabelResponse]:
|
||||
"""Elenca i tag assegnati a un messaggio."""
|
||||
await _check_message_access(message_id, current_user, db)
|
||||
svc = LabelService(db)
|
||||
labels = await svc.get_message_labels(message_id, current_user.tenant_id)
|
||||
return [LabelResponse.model_validate(l) for l in labels]
|
||||
|
||||
|
||||
@router.put("/messages/{message_id}/labels", response_model=list[LabelResponse])
|
||||
async def set_message_labels(
|
||||
message_id: uuid.UUID,
|
||||
data: MessageLabelSetRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> list[LabelResponse]:
|
||||
"""
|
||||
Sostituisce tutti i tag di un messaggio.
|
||||
Passare una lista vuota per rimuovere tutti i tag.
|
||||
"""
|
||||
await _check_message_access(message_id, current_user, db)
|
||||
svc = LabelService(db)
|
||||
labels = await svc.set_message_labels(
|
||||
message_id, current_user.tenant_id, data.label_ids
|
||||
)
|
||||
return [LabelResponse.model_validate(l) for l in labels]
|
||||
|
||||
|
||||
@router.post("/messages/{message_id}/labels/add", response_model=list[LabelResponse])
|
||||
async def add_message_labels(
|
||||
message_id: uuid.UUID,
|
||||
data: MessageLabelAddRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> list[LabelResponse]:
|
||||
"""Aggiunge tag a un messaggio senza rimuovere quelli esistenti."""
|
||||
await _check_message_access(message_id, current_user, db)
|
||||
svc = LabelService(db)
|
||||
labels = await svc.add_message_labels(
|
||||
message_id, current_user.tenant_id, data.label_ids
|
||||
)
|
||||
return [LabelResponse.model_validate(l) for l in labels]
|
||||
|
||||
|
||||
@router.post("/messages/{message_id}/labels/remove", response_model=list[LabelResponse])
|
||||
async def remove_message_labels(
|
||||
message_id: uuid.UUID,
|
||||
data: MessageLabelRemoveRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> list[LabelResponse]:
|
||||
"""Rimuove specifici tag da un messaggio."""
|
||||
await _check_message_access(message_id, current_user, db)
|
||||
svc = LabelService(db)
|
||||
labels = await svc.remove_message_labels(
|
||||
message_id, current_user.tenant_id, data.label_ids
|
||||
)
|
||||
return [LabelResponse.model_validate(l) for l in labels]
|
||||
|
||||
|
||||
# ─── Bulk labels ──────────────────────────────────────────────────────────────
|
||||
|
||||
@router.post("/messages/bulk-labels", response_model=MessageBulkLabelResponse)
|
||||
async def bulk_labels(
|
||||
data: MessageBulkLabelRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> MessageBulkLabelResponse:
|
||||
"""
|
||||
Aggiunge o rimuove tag da più messaggi in blocco.
|
||||
|
||||
- action="add": aggiunge i tag ai messaggi indicati
|
||||
- action="remove": rimuove i tag dai messaggi indicati
|
||||
|
||||
I messaggi non accessibili all'utente vengono silenziosamente ignorati.
|
||||
"""
|
||||
if not data.message_ids or not data.label_ids:
|
||||
return MessageBulkLabelResponse(updated=0)
|
||||
|
||||
# Per utenti non-admin filtra per caselle accessibili
|
||||
message_ids = [str(mid) for mid in data.message_ids]
|
||||
if not current_user.is_admin:
|
||||
from app.services.permission_service import PermissionService
|
||||
perm_svc = PermissionService(db)
|
||||
visible = await perm_svc.get_visible_mailboxes(current_user)
|
||||
visible_set = set(visible) if visible else set()
|
||||
|
||||
# Filtra i messaggi per caselle visibili
|
||||
result = await db.execute(
|
||||
select(Message.id).where(
|
||||
Message.id.in_(data.message_ids),
|
||||
Message.tenant_id == current_user.tenant_id,
|
||||
Message.mailbox_id.in_(visible_set),
|
||||
)
|
||||
)
|
||||
filtered_ids = list(result.scalars().all())
|
||||
else:
|
||||
filtered_ids = data.message_ids
|
||||
|
||||
svc = LabelService(db)
|
||||
if data.action == "add":
|
||||
updated = await svc.bulk_add_labels(
|
||||
filtered_ids, current_user.tenant_id, data.label_ids
|
||||
)
|
||||
else:
|
||||
updated = await svc.bulk_remove_labels(
|
||||
filtered_ids, current_user.tenant_id, data.label_ids
|
||||
)
|
||||
|
||||
return MessageBulkLabelResponse(updated=updated)
|
||||
Reference in New Issue
Block a user