126 lines
4.3 KiB
Python
126 lines
4.3 KiB
Python
"""
|
|
Servizio CRUD per i preset di permessi (sottoruoli nominati).
|
|
|
|
Admin e supervisor possono creare, modificare ed eliminare preset per il proprio tenant.
|
|
"""
|
|
|
|
import uuid
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.exceptions import ConflictError, ForbiddenError, NotFoundError
|
|
from app.models.permission_preset import PermissionPreset
|
|
from app.models.user import User
|
|
from app.schemas.permission_preset import PermissionPresetCreate, PermissionPresetUpdate
|
|
|
|
|
|
class PermissionPresetService:
|
|
def __init__(self, db: AsyncSession) -> None:
|
|
self.db = db
|
|
|
|
def _require_supervisor_or_admin(self, user: User) -> None:
|
|
if not user.is_supervisor_or_admin:
|
|
raise ForbiddenError("Solo amministratori e supervisori possono gestire i preset")
|
|
|
|
async def list_presets(self, tenant_id: uuid.UUID) -> list[PermissionPreset]:
|
|
"""Ritorna tutti i preset del tenant ordinati per nome."""
|
|
result = await self.db.execute(
|
|
select(PermissionPreset)
|
|
.where(PermissionPreset.tenant_id == tenant_id)
|
|
.order_by(PermissionPreset.name)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def get_preset(self, preset_id: uuid.UUID, tenant_id: uuid.UUID) -> PermissionPreset:
|
|
"""Recupera un preset per ID verificando che appartenga al tenant."""
|
|
preset = await self.db.get(PermissionPreset, preset_id)
|
|
if not preset or preset.tenant_id != tenant_id:
|
|
raise NotFoundError("preset")
|
|
return preset
|
|
|
|
async def create_preset(
|
|
self,
|
|
tenant_id: uuid.UUID,
|
|
data: PermissionPresetCreate,
|
|
created_by: User,
|
|
) -> PermissionPreset:
|
|
"""Crea un nuovo preset. Il nome deve essere unico per tenant."""
|
|
self._require_supervisor_or_admin(created_by)
|
|
|
|
# Verifica unicita' nome
|
|
existing = await self.db.execute(
|
|
select(PermissionPreset).where(
|
|
PermissionPreset.tenant_id == tenant_id,
|
|
PermissionPreset.name == data.name,
|
|
)
|
|
)
|
|
if existing.scalar_one_or_none():
|
|
raise ConflictError(f"Esiste gia' un preset con nome '{data.name}'")
|
|
|
|
preset = PermissionPreset(
|
|
tenant_id=tenant_id,
|
|
name=data.name,
|
|
description=data.description,
|
|
can_read=data.can_read,
|
|
can_send=data.can_send,
|
|
can_manage=data.can_manage,
|
|
can_conserve=data.can_conserve,
|
|
created_by=created_by.id,
|
|
)
|
|
self.db.add(preset)
|
|
await self.db.flush()
|
|
await self.db.refresh(preset)
|
|
return preset
|
|
|
|
async def update_preset(
|
|
self,
|
|
preset_id: uuid.UUID,
|
|
tenant_id: uuid.UUID,
|
|
data: PermissionPresetUpdate,
|
|
updated_by: User,
|
|
) -> PermissionPreset:
|
|
"""Aggiorna un preset esistente."""
|
|
self._require_supervisor_or_admin(updated_by)
|
|
|
|
preset = await self.get_preset(preset_id, tenant_id)
|
|
|
|
# Verifica unicita' nome se cambia
|
|
if data.name is not None and data.name != preset.name:
|
|
existing = await self.db.execute(
|
|
select(PermissionPreset).where(
|
|
PermissionPreset.tenant_id == tenant_id,
|
|
PermissionPreset.name == data.name,
|
|
)
|
|
)
|
|
if existing.scalar_one_or_none():
|
|
raise ConflictError(f"Esiste gia' un preset con nome '{data.name}'")
|
|
preset.name = data.name
|
|
|
|
if data.description is not None:
|
|
preset.description = data.description
|
|
if data.can_read is not None:
|
|
preset.can_read = data.can_read
|
|
if data.can_send is not None:
|
|
preset.can_send = data.can_send
|
|
if data.can_manage is not None:
|
|
preset.can_manage = data.can_manage
|
|
if data.can_conserve is not None:
|
|
preset.can_conserve = data.can_conserve
|
|
|
|
await self.db.flush()
|
|
await self.db.refresh(preset)
|
|
return preset
|
|
|
|
async def delete_preset(
|
|
self,
|
|
preset_id: uuid.UUID,
|
|
tenant_id: uuid.UUID,
|
|
deleted_by: User,
|
|
) -> None:
|
|
"""Elimina un preset."""
|
|
self._require_supervisor_or_admin(deleted_by)
|
|
preset = await self.get_preset(preset_id, tenant_id)
|
|
await self.db.delete(preset)
|
|
await self.db.flush()
|