130 lines
4.4 KiB
Python
130 lines
4.4 KiB
Python
"""Permissions endpoints - ServiceManagerWeb"""
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, delete
|
|
from typing import Dict
|
|
import uuid
|
|
|
|
from app.core.database import get_db
|
|
from app.api.deps import get_current_user
|
|
from app.models.user import User, UserRole
|
|
from app.models.permission import TenantPermission, DEFAULT_PERMISSIONS, CLIENT_PERMISSIONS
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/my")
|
|
async def get_my_permissions(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> Dict[str, bool]:
|
|
"""Obtener permisos efectivos del usuario actual."""
|
|
if current_user.role.is_global:
|
|
# Staff interno — devolver permisos del rol por defecto
|
|
role_defaults = DEFAULT_PERMISSIONS.get(current_user.role.value, {})
|
|
return role_defaults
|
|
|
|
# Buscar overrides individuales primero
|
|
result = await db.execute(
|
|
select(TenantPermission).where(
|
|
TenantPermission.tenant_id == current_user.tenant_id,
|
|
TenantPermission.user_id == current_user.id,
|
|
)
|
|
)
|
|
user_overrides = {p.permission: p.granted for p in result.scalars().all()}
|
|
|
|
# Buscar defaults del rol
|
|
result = await db.execute(
|
|
select(TenantPermission).where(
|
|
TenantPermission.tenant_id == current_user.tenant_id,
|
|
TenantPermission.user_id == None,
|
|
TenantPermission.role == current_user.role.value,
|
|
)
|
|
)
|
|
role_defaults = {p.permission: p.granted for p in result.scalars().all()}
|
|
|
|
# Merge: override individual > default del rol > system default
|
|
system_defaults = DEFAULT_PERMISSIONS.get(current_user.role.value, {})
|
|
effective = {**system_defaults, **role_defaults, **user_overrides}
|
|
return effective
|
|
|
|
|
|
@router.get("/user/{user_id}")
|
|
async def get_user_permissions(
|
|
user_id: uuid.UUID,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> Dict[str, bool]:
|
|
"""Obtener permisos efectivos de un usuario específico."""
|
|
if current_user.role not in (UserRole.ADMIN, UserRole.SUPPORT_MANAGER, UserRole.CLIENT_ADMIN):
|
|
raise HTTPException(status_code=403, detail="Sin permisos")
|
|
|
|
target = await db.get(User, user_id)
|
|
if not target:
|
|
raise HTTPException(status_code=404, detail="Usuario no encontrado")
|
|
|
|
# Buscar overrides individuales
|
|
result = await db.execute(
|
|
select(TenantPermission).where(
|
|
TenantPermission.user_id == user_id,
|
|
)
|
|
)
|
|
user_overrides = {p.permission: p.granted for p in result.scalars().all()}
|
|
|
|
# Buscar defaults del rol en el tenant
|
|
result = await db.execute(
|
|
select(TenantPermission).where(
|
|
TenantPermission.tenant_id == target.tenant_id,
|
|
TenantPermission.user_id == None,
|
|
TenantPermission.role == target.role.value,
|
|
)
|
|
)
|
|
role_defaults = {p.permission: p.granted for p in result.scalars().all()}
|
|
|
|
system_defaults = DEFAULT_PERMISSIONS.get(target.role.value, {})
|
|
effective = {**system_defaults, **role_defaults, **user_overrides}
|
|
return effective
|
|
|
|
|
|
@router.put("/user/{user_id}")
|
|
async def update_user_permissions(
|
|
user_id: uuid.UUID,
|
|
data: Dict[str, bool],
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Actualizar permisos individuales de un usuario.
|
|
Solo ADMIN, SUPPORT_MANAGER o CLIENT_ADMIN pueden hacerlo.
|
|
"""
|
|
if current_user.role not in (UserRole.ADMIN, UserRole.SUPPORT_MANAGER, UserRole.CLIENT_ADMIN):
|
|
raise HTTPException(status_code=403, detail="Sin permisos")
|
|
|
|
target = await db.get(User, user_id)
|
|
if not target:
|
|
raise HTTPException(status_code=404, detail="Usuario no encontrado")
|
|
|
|
# Borrar overrides existentes del usuario
|
|
await db.execute(
|
|
delete(TenantPermission).where(
|
|
TenantPermission.user_id == user_id,
|
|
)
|
|
)
|
|
|
|
# Insertar nuevos overrides
|
|
from datetime import datetime
|
|
now = datetime.utcnow()
|
|
for permission, granted in data.items():
|
|
db.add(TenantPermission(
|
|
id=uuid.uuid4(),
|
|
tenant_id=target.tenant_id,
|
|
user_id=user_id,
|
|
role=target.role.value,
|
|
permission=permission,
|
|
granted=granted,
|
|
created_at=now,
|
|
updated_at=now,
|
|
))
|
|
|
|
await db.commit()
|
|
return {"message": "Permisos actualizados"} |