Lewati ke konten utama
Versi: Saat ini

Users and Groups (RBAC Model)

Honeyframe uses a two-axis Role-Based Access Control (RBAC) model that decouples licensing from security permissions.

The Two-Axis Model

Security in Honeyframe is structured around two independent axes:

  1. Seat Types (Licensing Axis): Defines the user's licensing tier and default capabilities.
  2. Group Permissions (Security Axis): Defines specific access to resources (projects, datasets, dashboards) via group membership.

Seat Types

Seat types are assigned at the user level and represent their primary role within the platform. They drive implicit organization-wide permissions.

  • Admin: Platform administrators with full access to organization settings, users, and all resources.
  • Builder: Users who can create and manage project assets, flows, and metadata.
  • Analyst: Users focused on data exploration and dashboarding. Can view projects and interact with data.
  • Viewer: Read-only users who consume dashboards and project overviews.

The seat type is stored in the seat_type column of the users table. Implicit grants for each seat type are defined in paas/backend/services/permissions.py.

Groups and Permissions

Permissions are never granted directly to users; instead, they are granted to groups. Users inherit permissions by being members of one or more groups.

Groups

Groups are defined in the hubstudio.groups table. A group can be:

  • Local: Managed entirely within the Honeyframe platform.
  • LDAP-Mapped: Mapped to an external directory via the ldap_dn column, allowing membership to be synchronized with enterprise identity providers.

Permissions

The hubstudio.group_permissions table maps groups to specific capabilities. A permission grant consists of:

  • Permission Type: A dot-separated string defining the resource and action (e.g., project.edit, dashboard.view).
  • Target ID: (Optional) Scopes the permission to a specific object (e.g., a specific dashboard_id). If the Target ID is NULL, the permission is granted organization-wide.

Resolution Logic

The single source of truth for all permission checks is user_has_permission() in paas/backend/services/permissions.py. The resolution follows this precedence:

  1. Superadmin: Bypasses all checks.
  2. Admin Seat: Bypasses all checks for the organization.
  3. Implicit Grants: Grants based on the user's seat type (e.g., Builders implicitly get project.edit).
  4. Group Grants: Explicit rows in group_permissions matching the user's group memberships.

Superadmin (global privilege)

is_superadmin is a global flag — it bypasses every org-scoped check, across all organizations — and is distinct from the org-scoped admin role/seat. Because granting it is a full privilege escalation, it is governed by stricter rules than ordinary role changes (v0.0.89):

  • SSO sign-up never grants it. All four SSO auto-create paths (Google, Microsoft, generic OIDC, SAML) insert new users with is_superadmin = FALSE; the seeded role (default viewer) is the only privilege a first-time SSO sign-in receives. (A prior defect auto-granted superadmin on first SSO sign-in; this was fixed and is now guarded by a static test that asserts is_superadmin = FALSE across every SSO insert path.)
  • Only a superadmin can grant it. PATCH /api/users/{id} accepts an is_superadmin field, but writes to it are gated behind caller.is_superadmin — holding org.admin is not sufficient. In the UI the Make SA / Revoke SA action is visible only to superadmins and hidden on the caller's own row.
  • Self-revoke is blocked. A superadmin cannot remove their own is_superadmin, mirroring the self-deactivate guard so the last superadmin can't lock the platform out.

Frontend Implementation

The frontend provides utilities for declarative and programmatic permission gates.

  • usePermission() Hook: A React hook for checking permissions within components to show/hide UI elements.
    • Source: paas/frontend/src/hooks/usePermission.ts
  • <ProtectedRoute> Component: A wrapper component used in route definitions to prevent unauthorized access to entire pages.
    • Source: paas/frontend/src/components/ProtectedRoute.tsx

The frontend fetches the user's flat permission list from the /api/groups/me/permissions endpoint (see paas/backend/routers/groups.py).