Skip to main content
Vito uses two overlapping role systems:
  1. System roles (UserRole enum) — stored in the users.role column. Controls access to the Filament admin panel and super-admin features.
  2. Tenant roles (Role enum + Spatie Permission) — scoped to a tenant membership. Controls what actions a staff member can perform within a business.

System roles

Defined in App\Domain\Identity\Enums\UserRole:
The super_admin role can also be granted by listing an email in the APP_SUPER_ADMINS environment variable (comma-separated). This takes precedence over the database role column.

Tenant roles and permissions

Tenant-scoped roles are managed by Spatie Laravel Permission and defined in App\Domain\Access\Enums\Role:

Permission list

Permissions are defined in App\Domain\Access\Enums\Permission and assigned to roles in config/rbac.php:

Role presets

config/rbac.php defines presets for common staff roles tied to a plan capability:

Checking permissions in code

In PHP (Spatie)

Checking system role

In Filament resources

Filament resources respect Laravel’s Gate. Use canAccess or canViewAny methods that delegate to the registered Policy:

Tenant ownership middleware

The tenant.ownership middleware (EnsureTenantOwnership) is applied to all protected tenant API routes:
For every route-model-bound parameter, the middleware verifies that the model’s tenant_id belongs to one of the authenticated user’s tenants. On a mismatch:
  1. A TENANT_OWNERSHIP_VIOLATION event is logged to the security log channel.
  2. The request is aborted with 404 (not 403) to avoid disclosing resource existence.
Models covered: Product, Order, Coupon, MenuSection, Lead, Campaign.

Impersonation

Super-admins can impersonate tenant users directly from the Filament admin panel. The original admin session is preserved in impersonator_id and impersonator_name session keys.

Leaving impersonation

The ImpersonationController::leave method:
  1. Verifies that an active impersonation session exists (impersonator_id in session).
  2. Logs the impersonation_ended event with the original admin ID, impersonated user ID, IP, and user agent.
  3. Clears the impersonation session keys.
  4. Logs out the impersonated user and restores the original admin session.
  5. Regenerates the session ID to prevent session fixation.
If the original admin account cannot be found after impersonation ends (e.g., it was deleted), the session is fully invalidated and the browser is redirected to /login. This failure is logged at emergency severity.