142 lines
3.8 KiB
Python
142 lines
3.8 KiB
Python
"""
|
|
TenantPermission Model - ServiceManagerWeb
|
|
|
|
Permisos dinámicos por tenant.
|
|
- Si user_id es None → aplica al rol completo (default del tenant)
|
|
- Si user_id tiene valor → override individual para ese usuario
|
|
"""
|
|
from sqlalchemy import String, Boolean, ForeignKey, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
from typing import Optional
|
|
import uuid
|
|
|
|
from app.core.database import Base, GUID
|
|
|
|
|
|
CLIENT_PERMISSIONS = [
|
|
# Permisos funcionales
|
|
"view_tickets",
|
|
"create_tickets",
|
|
"close_tickets",
|
|
"view_reports",
|
|
"manage_tenant_users",
|
|
"create_issues",
|
|
# Permisos de navegación - cliente
|
|
"nav:tickets",
|
|
"nav:organization",
|
|
"nav:usuarios",
|
|
]
|
|
|
|
INTERNAL_PERMISSIONS = [
|
|
# Permisos de navegación - interno
|
|
"nav:tickets",
|
|
"nav:users",
|
|
"nav:tenants",
|
|
"nav:categories",
|
|
"nav:systems",
|
|
"nav:sla",
|
|
"nav:audit",
|
|
"nav:reports",
|
|
]
|
|
|
|
DEFAULT_PERMISSIONS = {
|
|
"CLIENT_ADMIN": {
|
|
# Funcionales — todo ON
|
|
"view_tickets": True,
|
|
"create_tickets": True,
|
|
"close_tickets": True,
|
|
"view_reports": True,
|
|
"manage_tenant_users": True,
|
|
"create_issues": True,
|
|
# Navegación cliente — todo ON
|
|
"nav:tickets": True,
|
|
"nav:organization": True,
|
|
"nav:usuarios": True,
|
|
},
|
|
"CLIENT_USER": {
|
|
# Funcionales
|
|
"view_tickets": True,
|
|
"create_tickets": True,
|
|
"close_tickets": False,
|
|
"view_reports": False,
|
|
"manage_tenant_users": False,
|
|
"create_issues": False,
|
|
# Navegación cliente
|
|
"nav:tickets": True,
|
|
"nav:organization": False,
|
|
"nav:usuarios": False,
|
|
},
|
|
"ADMIN": {
|
|
# Navegación interna — todo ON
|
|
"nav:tickets": True,
|
|
"nav:users": True,
|
|
"nav:tenants": True,
|
|
"nav:categories": True,
|
|
"nav:systems": True,
|
|
"nav:sla": True,
|
|
"nav:audit": True,
|
|
"nav:reports": True,
|
|
},
|
|
"SUPPORT_MANAGER": {
|
|
"nav:tickets": True,
|
|
"nav:users": True,
|
|
"nav:tenants": False,
|
|
"nav:categories": True,
|
|
"nav:systems": True,
|
|
"nav:sla": True,
|
|
"nav:audit": True,
|
|
"nav:reports": True,
|
|
},
|
|
"AGENT": {
|
|
"nav:tickets": True,
|
|
"nav:users": False,
|
|
"nav:tenants": False,
|
|
"nav:categories": False,
|
|
"nav:systems": False,
|
|
"nav:sla": False,
|
|
"nav:audit": False,
|
|
"nav:reports": False,
|
|
},
|
|
"AUDITOR": {
|
|
"nav:tickets": True,
|
|
"nav:users": False,
|
|
"nav:tenants": False,
|
|
"nav:categories": False,
|
|
"nav:systems": False,
|
|
"nav:sla": False,
|
|
"nav:audit": True,
|
|
"nav:reports": True,
|
|
},
|
|
}
|
|
|
|
|
|
class TenantPermission(Base):
|
|
__tablename__ = "tenant_permissions"
|
|
|
|
tenant_id: Mapped[uuid.UUID] = mapped_column(
|
|
GUID(),
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
)
|
|
user_id: Mapped[Optional[uuid.UUID]] = mapped_column(
|
|
GUID(),
|
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
nullable=True,
|
|
)
|
|
role: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
permission: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
granted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
|
|
|
tenant: Mapped["Tenant"] = relationship("Tenant")
|
|
user: Mapped[Optional["User"]] = relationship("User")
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint(
|
|
"tenant_id", "role", "user_id", "permission",
|
|
name="uq_tenant_permission"
|
|
),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
scope = f"user:{self.user_id}" if self.user_id else f"role:{self.role}"
|
|
return f"<TenantPermission({scope} {self.permission}={'✓' if self.granted else '✗'})>" |