Skip to content

Roles and Permissions

Role-based access control (RBAC) using spatie/laravel-permission v7 with PHP enums for type-safe permission management.

The system uses:

  • PHP Enums for type-safe roles and permissions
  • Spatie Permission package for RBAC infrastructure
  • Admin gets every permission via Role::getPermissions() returning Permission::cases() (no wildcard case)
  • FilamentPHP trait for automatic resource authorization
use App\Enums\Role;
$user->assignRole(Role::Admin->value);
$user->assignRole(Role::SupplierManager->value);
use App\Enums\Permission;
// Using enum (recommended)
if ($user->can(Permission::ViewUser->value)) {
// User can view users
}
// Using string
if ($user->can('view_user')) {
// User can view users
}
use App\Enums\Role;
if ($user->hasRole(Role::Admin->value)) {
// User is admin
}

Full system access. Role::Admin->getPermissions() returns Permission::cases() — every permission in the enum. There is no * wildcard case; the admin simply holds all of them.

Property Value
Slug admin
Icon heroicon-o-shield-check
Color danger (red)
Scope Global

Capabilities: All permissions on all resources.

Limited access to supplier-related resources only.

Property Value
Slug supplier-manager
Icon heroicon-o-building-office-2
Color info (blue)
Scope Supplier-scoped

Capabilities:

  • View and update their own Supplier (no create/delete)
  • Full CRUD on Supplier Hotels, Tours, Tour Rates, Activities, Transfers, Services
  • Full CRUD on Stop Sales (their own tours)
  • Read-only on Supplier Contracts (managed by Volāre admins)
  • Read-only on Offers — supplier sees only the offers built on top of their tours (scoped via supplierTourRate.tour.suppliers); pricing fields are hidden in the offer preview (Offers — Pricing Visibility)
  • Read-only on Trips to Deliver — operational booking view for trips assigned to their tours (Trips to Deliver)

Restrictions (no access to):

  • System config (Users, Activity Logs)
  • Travel Products, Bookings (full booking resource — they use the read-only Trips to Deliver view instead)
  • Market config (Markets, Market Products, POIs)
  • Flights (Flight Search, Flight Bookings)
  • Hotels, Airports, Clients, Passengers, Leads, TCAI Profiles

Sales team member who can view assigned bookings and log interactions (attribution workflow).

Property Value
Slug sales-agent
Icon heroicon-o-briefcase
Color success (green)
Scope Global

Permissions (Role::salesAgentPermissions()): view_booking, view_booking_attribution, log_booking_touchpoint, view_assigned_bookings, view_client, view_offer.

Finance team member with access to the Revenue Dashboard and the Budget page (including budget upload).

Property Value
Slug finance
Icon heroicon-o-banknotes
Color warning
Scope Global

Permissions: none. Role::financePermissions() returns an empty array — Finance access is gated entirely by page-level canAccess() checks against the role, not by Spatie permissions.

{action}_{resource}

Actions: view, create, update, delete

Examples:

  • view_user - View user records
  • create_supplier - Create new supplier
  • update_offer - Update offers
  • delete_travel_product - Delete travel products

Standard CRUD permissions (25 resources × 4 = 100) plus 12 non-standard permissions.

Resource View Create Update Delete
User view_user create_user update_user delete_user
Client view_client create_client update_client delete_client
Passenger view_passenger create_passenger update_passenger delete_passenger
Hotel view_hotel create_hotel update_hotel delete_hotel
Supplier Hotel view_supplier_hotel create_supplier_hotel update_supplier_hotel delete_supplier_hotel
Supplier Tour view_supplier_tour create_supplier_tour update_supplier_tour delete_supplier_tour
Supplier Tour Rate view_supplier_tour_rate create_supplier_tour_rate update_supplier_tour_rate delete_supplier_tour_rate
Supplier Activity view_supplier_activity create_supplier_activity update_supplier_activity delete_supplier_activity
Supplier Transfer view_supplier_transfer create_supplier_transfer update_supplier_transfer delete_supplier_transfer
Supplier Service view_supplier_service create_supplier_service update_supplier_service delete_supplier_service
Airport view_airport create_airport update_airport delete_airport
Flight Search view_flight_search create_flight_search update_flight_search delete_flight_search
Market view_market create_market update_market delete_market
Flight Booking view_flight_booking create_flight_booking update_flight_booking delete_flight_booking
Market Product view_market_product create_market_product update_market_product delete_market_product
Supplier view_supplier create_supplier update_supplier delete_supplier
Offer view_offer create_offer update_offer delete_offer
Travel Product view_travel_product create_travel_product update_travel_product delete_travel_product
Booking view_booking create_booking update_booking delete_booking
POI view_poi create_poi update_poi delete_poi
TCAI Profile view_tcai_profile create_tcai_profile update_tcai_profile delete_tcai_profile
Supplier Contract view_supplier_contract create_supplier_contract update_supplier_contract delete_supplier_contract
Stop Sale view_stop_sale create_stop_sale update_stop_sale delete_stop_sale
Supplier Insurance view_supplier_insurance create_supplier_insurance update_supplier_insurance delete_supplier_insurance
Email Configuration view_email_configuration create_email_configuration update_email_configuration delete_email_configuration
Resource Permissions Notes
Lead view_lead, delete_lead Read-only + delete. No create/update – leads come from the public contact form API.
Booking Message view_booking_message, create_booking_message Per-booking VOLĀRE/Supplier conversation. Immutable: read + post only (no update/delete).
Insurance Contract view_insurance_contract Read-only view of issued Intermundial policies.
Booking Attribution view_booking_attribution, update_booking_attribution, lock_booking_attribution, view_assigned_bookings, log_booking_touchpoint, view_sales_performance 6 custom permissions for sales attribution workflow.
AI Tools use_travel_consultant Access to AI travel consultant features.

Add to Filament resources for automatic permission checks:

use App\Filament\Traits\HasResourcePermissions;
class UserResource extends Resource
{
use HasResourcePermissions;
// Resource implementation...
}

The trait automatically:

  • Derives permission prefix from model name (User -> user, FlightBooking -> flight_booking)
  • Hides navigation for unauthorized resources
  • Checks view, create, update, delete permissions
app/Enums/Permission.php
enum Permission: string
{
// ... existing permissions
// New resource (4 permissions)
case ViewInvoice = 'view_invoice';
case CreateInvoice = 'create_invoice';
case UpdateInvoice = 'update_invoice';
case DeleteInvoice = 'delete_invoice';
}
// If Supplier Managers should access the new resource
public static function supplierManagerPermissions(): array
{
return [
// ... existing permissions
self::ViewInvoice,
self::CreateInvoice,
self::UpdateInvoice,
self::DeleteInvoice,
];
}
Terminal window
./vendor/bin/sail artisan db:seed --class=RolesAndPermissionsSeeder

Use Permission enum for type-safe policy checks:

use App\Enums\Permission;
use App\Models\User;
class InvoicePolicy
{
public function viewAny(User $user): bool
{
return $user->can(Permission::ViewInvoice->value);
}
public function create(User $user): bool
{
return $user->can(Permission::CreateInvoice->value);
}
public function update(User $user, Invoice $invoice): bool
{
return $user->can(Permission::UpdateInvoice->value);
}
public function delete(User $user, Invoice $invoice): bool
{
return $user->can(Permission::DeleteInvoice->value);
}
}

Spatie Permission caches roles and permissions. Clear cache after changes:

Terminal window
./vendor/bin/sail artisan permission:cache-reset
  1. Check user has correct role:

    $user->getRoleNames(); // ['admin'] or ['supplier-manager']
  2. Check role has permission:

    $user->getAllPermissions()->pluck('name');
  3. Clear permission cache:

    Terminal window
    ./vendor/bin/sail artisan permission:cache-reset

Ensure resource uses HasResourcePermissions trait:

class DMCResource extends Resource
{
use HasResourcePermissions;
}
File Purpose
app/Enums/Permission.php Permission enum with 112 permissions
app/Enums/Role.php Role enum with Admin, SupplierManager, SalesAgent, and Finance
app/Filament/Traits/HasResourcePermissions.php Filament authorization trait
database/seeders/RolesAndPermissionsSeeder.php Seeds roles and permissions