New /api/v1/infra/stack/status probes all stack apps/APIs/SW; Infra UI groups proc-cards by VM; wire vm123 router; menu INFRA COD and Serviços IaaS · Infra as Code labels. Co-authored-by: Cursor <cursoragent@cursor.com>
281 lines
6.6 KiB
Python
281 lines
6.6 KiB
Python
"""RBAC helpers for Ligbox Ops Desk — Spec 003 + 027."""
|
|
|
|
from __future__ import annotations
|
|
|
|
# Ops (Spec 003)
|
|
OPS_ROLES = frozenset({"super_admin", "ops_lead", "technician", "noc"})
|
|
|
|
# Comercial (Spec 027)
|
|
SALES_ROLES = frozenset({"sales_admin", "sales_support"})
|
|
|
|
# Negócio / plataforma (Spec 027)
|
|
BUSINESS_ROLES = frozenset(
|
|
{
|
|
"finance",
|
|
"marketing",
|
|
"seo",
|
|
"developer",
|
|
"devops",
|
|
"security_analyst",
|
|
"content_editor",
|
|
"agentic_operator",
|
|
}
|
|
)
|
|
|
|
# Sistema (não humanos)
|
|
SYSTEM_ROLES = frozenset({"api_service", "agent_system"})
|
|
|
|
ALL_ROLES = OPS_ROLES | SALES_ROLES | BUSINESS_ROLES | SYSTEM_ROLES
|
|
|
|
# Funções humanas (login Desk)
|
|
HUMAN_ROLES = OPS_ROLES | SALES_ROLES | BUSINESS_ROLES
|
|
|
|
# Atribuíveis no cadastro Spec 004 (exceto super_admin)
|
|
ASSIGNABLE_ROLES = HUMAN_ROLES - {"super_admin"}
|
|
|
|
# Compatibilidade com código existente
|
|
ROLES = HUMAN_ROLES
|
|
|
|
ROLE_LABELS: dict[str, str] = {
|
|
"super_admin": "Super Admin",
|
|
"ops_lead": "Chefe Ops",
|
|
"technician": "Suporte",
|
|
"noc": "NOC",
|
|
"sales_admin": "Sales Admin",
|
|
"sales_support": "Sales Support",
|
|
"finance": "Financeiro",
|
|
"marketing": "Marketing",
|
|
"seo": "SEO",
|
|
"developer": "Developer",
|
|
"devops": "DevOps",
|
|
"security_analyst": "Segurança / SOC",
|
|
"content_editor": "Conteúdo / CMS",
|
|
"agentic_operator": "Operador Agentes IA",
|
|
"api_service": "API Service",
|
|
"agent_system": "Agent System",
|
|
}
|
|
|
|
|
|
def is_valid_role(role: str) -> bool:
|
|
return role in ALL_ROLES
|
|
|
|
|
|
def is_assignable_role(role: str) -> bool:
|
|
return role in ASSIGNABLE_ROLES
|
|
|
|
|
|
def can_read_tickets(role: str) -> bool:
|
|
return role in HUMAN_ROLES
|
|
|
|
|
|
def can_patch_ticket(role: str, ticket: dict, username: str) -> bool:
|
|
if role in ("super_admin", "ops_lead"):
|
|
return True
|
|
if role == "technician":
|
|
assignee = ticket.get("assigned_to")
|
|
return assignee is None or assignee == username
|
|
return False
|
|
|
|
|
|
def can_assign_ticket(role: str, assignee: str | None, username: str) -> bool:
|
|
if role in ("super_admin", "ops_lead"):
|
|
return True
|
|
if role == "technician":
|
|
return assignee in (None, username)
|
|
return False
|
|
|
|
|
|
def can_run_audit(role: str) -> bool:
|
|
return role in ("super_admin", "ops_lead")
|
|
|
|
|
|
def can_read_audit_overview(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"noc",
|
|
"developer",
|
|
"devops",
|
|
"security_analyst",
|
|
"agentic_operator",
|
|
)
|
|
|
|
|
|
def can_read_audit_scorecard(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"noc",
|
|
"developer",
|
|
"security_analyst",
|
|
"agentic_operator",
|
|
)
|
|
|
|
|
|
def can_read_cloudflare_dns(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"technician",
|
|
"noc",
|
|
"seo",
|
|
"devops",
|
|
"developer",
|
|
)
|
|
|
|
|
|
def can_read_funnel(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"technician",
|
|
"noc",
|
|
"sales_admin",
|
|
"sales_support",
|
|
"finance",
|
|
"marketing",
|
|
"seo",
|
|
"developer",
|
|
"devops",
|
|
"agentic_operator",
|
|
)
|
|
|
|
|
|
def can_read_session_timeline(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"technician",
|
|
"sales_admin",
|
|
"sales_support",
|
|
"finance",
|
|
"marketing",
|
|
"seo",
|
|
"developer",
|
|
"devops",
|
|
"agentic_operator",
|
|
)
|
|
|
|
|
|
def can_list_webhook_events(role: str, source: str | None = None) -> bool:
|
|
if role == "noc":
|
|
return source in (None, "wazuh", "vm112-security")
|
|
if role == "security_analyst":
|
|
return source in (None, "wazuh", "vm112-security", "vm112")
|
|
if role == "finance":
|
|
return source in (None, "billing", "vm112")
|
|
if role == "developer":
|
|
return source in (None, "vm112", "wazuh")
|
|
return role in HUMAN_ROLES
|
|
|
|
|
|
def can_read_crm_leads(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"technician",
|
|
"sales_admin",
|
|
"sales_support",
|
|
"marketing",
|
|
"seo",
|
|
)
|
|
|
|
|
|
def can_read_assist(role: str) -> bool:
|
|
return role in ("super_admin", "ops_lead", "technician", "sales_admin", "sales_support")
|
|
|
|
|
|
def can_assist_takeover(role: str) -> bool:
|
|
return role in ("super_admin", "ops_lead", "technician")
|
|
|
|
|
|
def can_assist_handoff(role: str, username: str) -> bool:
|
|
return role in ("super_admin", "ops_lead", "technician")
|
|
|
|
|
|
def can_manage_users(role: str) -> bool:
|
|
return role == "super_admin"
|
|
|
|
|
|
def can_manage_vm112_domains(role: str) -> bool:
|
|
"""Admin Desk — domínios orquestrados VM112 (Spec 017)."""
|
|
return role in ("super_admin", "ops_lead", "devops")
|
|
|
|
|
|
def should_mask_sensitive(role: str) -> bool:
|
|
return role in ("noc", "sales_support")
|
|
|
|
|
|
def can_read_migration(role: str) -> bool:
|
|
return role in ("super_admin", "ops_lead", "technician", "noc", "devops")
|
|
|
|
|
|
def can_manage_migration(role: str) -> bool:
|
|
return role in ("super_admin", "ops_lead", "technician")
|
|
|
|
|
|
def can_read_billing(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"noc",
|
|
"finance",
|
|
"sales_admin",
|
|
"sales_support",
|
|
)
|
|
|
|
|
|
def can_validate_billing(role: str) -> bool:
|
|
"""Transicionar billing_state — Spec 023 / FR-027-005 / FR-027-009."""
|
|
return role in ("super_admin", "ops_lead", "finance", "sales_admin")
|
|
|
|
|
|
def can_manage_billing(role: str) -> bool:
|
|
return can_validate_billing(role)
|
|
|
|
|
|
def can_create_foss_order(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"ops_lead",
|
|
"finance",
|
|
"sales_admin",
|
|
"sales_support",
|
|
)
|
|
|
|
|
|
def can_access_foss_admin(role: str) -> bool:
|
|
return role in ("super_admin", "finance", "sales_admin")
|
|
|
|
|
|
def can_access_openadmin(role: str) -> bool:
|
|
return role in ("super_admin", "devops", "sales_admin")
|
|
|
|
|
|
def can_openpanel_autologin(role: str) -> bool:
|
|
return role in (
|
|
"super_admin",
|
|
"sales_admin",
|
|
"sales_support",
|
|
"marketing",
|
|
"seo",
|
|
"content_editor",
|
|
"technician",
|
|
)
|
|
|
|
|
|
def can_openpanel_provision(role: str) -> bool:
|
|
return role in ("super_admin", "devops", "sales_admin", "sales_support")
|
|
|
|
|
|
def can_openpanel_delete(role: str) -> bool:
|
|
return role in ("super_admin", "devops")
|
|
|
|
|
|
def roles_meta() -> dict:
|
|
"""Metadados para UI — labels e funções atribuíveis no cadastro."""
|
|
return {
|
|
"labels": ROLE_LABELS,
|
|
"assignable": sorted(ASSIGNABLE_ROLES),
|
|
"human": sorted(HUMAN_ROLES),
|
|
}
|