Skip to content

Roles and Permissions

Role-based access control (RBAC) using spatie/laravel-permission v6 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
  • Wildcard permissions for admin full access
  • 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 via wildcard (*) permission.

PropertyValue
Slugadmin
Iconheroicon-o-shield-check
Colordanger (red)
ScopeGlobal

Capabilities: All permissions on all resources.

Limited access to supplier-related resources only.

PropertyValue
Slugsupplier-manager
Iconheroicon-o-building-office-2
Colorinfo (blue)
ScopeSupplier-scoped

Capabilities:

  • View and update their own Supplier (no create/delete)
  • Full CRUD on Supplier Hotels, Tours, Tour Rates, Activities, Transfers, Services

Restrictions (no access to):

  • System config (Users, Activity Logs)
  • Product management (Offers, Travel Products, Bookings)
  • Market config (Markets, Market Products, POIs)
  • Flights (Flight Search, Flight Bookings)
  • Hotels, Airports, Clients, Passengers, TCAI Profiles
{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 (21 resources x 4 = 84) plus 1 special permission.

ResourceViewCreateUpdateDelete
Userview_usercreate_userupdate_userdelete_user
Clientview_clientcreate_clientupdate_clientdelete_client
Passengerview_passengercreate_passengerupdate_passengerdelete_passenger
Hotelview_hotelcreate_hotelupdate_hoteldelete_hotel
Supplier Hotelview_supplier_hotelcreate_supplier_hotelupdate_supplier_hoteldelete_supplier_hotel
Supplier Tourview_supplier_tourcreate_supplier_tourupdate_supplier_tourdelete_supplier_tour
Supplier Tour Rateview_supplier_tour_ratecreate_supplier_tour_rateupdate_supplier_tour_ratedelete_supplier_tour_rate
Supplier Activityview_supplier_activitycreate_supplier_activityupdate_supplier_activitydelete_supplier_activity
Supplier Transferview_supplier_transfercreate_supplier_transferupdate_supplier_transferdelete_supplier_transfer
Supplier Serviceview_supplier_servicecreate_supplier_serviceupdate_supplier_servicedelete_supplier_service
Airportview_airportcreate_airportupdate_airportdelete_airport
Flight Searchview_flight_searchcreate_flight_searchupdate_flight_searchdelete_flight_search
Marketview_marketcreate_marketupdate_marketdelete_market
Flight Bookingview_flight_bookingcreate_flight_bookingupdate_flight_bookingdelete_flight_booking
Market Productview_market_productcreate_market_productupdate_market_productdelete_market_product
Supplierview_suppliercreate_supplierupdate_supplierdelete_supplier
Offerview_offercreate_offerupdate_offerdelete_offer
Travel Productview_travel_productcreate_travel_productupdate_travel_productdelete_travel_product
Bookingview_bookingcreate_bookingupdate_bookingdelete_booking
POIview_poicreate_poiupdate_poidelete_poi
TCAI Profileview_tcai_profilecreate_tcai_profileupdate_tcai_profiledelete_tcai_profile
CategoryPermissionDescription
AI Toolsuse_travel_consultantAccess 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;
}
FilePurpose
app/Enums/Permission.phpPermission enum with 85 permissions (84 CRUD + 1 special)
app/Enums/Role.phpRole enum with Admin and SupplierManager
app/Filament/Traits/HasResourcePermissions.phpFilament authorization trait
database/seeders/RolesAndPermissionsSeeder.phpSeeds roles and permissions