Skip to content

Authorization

The CPR backend uses Spatie Laravel Permission for role-based access control (RBAC).

Roles

There are 7 predefined roles in the system:

RoleDescriptionKey Access Areas
adminFull system accessEverything + admin.access
doctorPatient care providerPatients, consultations, medical records, prescriptions
nurseClinical supportPatients, vitals, basic medical records
receptionistFront deskRegistration, appointments, queue management
pharmacistMedication managementPharmacy, dispensing, inventory
lab_technicianLab operationsLaboratory tests, processing
billing_staffFinancial operationsBilling, transactions, accounts

Permission Naming Convention

Permissions follow the pattern: {module}.{action}

Available Modules and Actions

ModuleActions
userscreate, read, update, delete
rolescreate, read, update, delete
branchescreate, read, update, delete
patientscreate, read, update, delete
appointmentscreate, read, update, delete
medical-recordscreate, read, update, delete
consultationscreate, read, update, delete
laboratorycreate, read, update, delete
pharmacycreate, read, update, delete
billingcreate, read, update, delete
reportsread
settingsread, update
vitalscreate, read, update, delete
inventorycreate, read, update, delete
adminaccess

How Authorization Is Enforced

Route-Level (Middleware)

Admin-only routes use the permission middleware:

php
// routes/api.php
Route::middleware(['auth:sanctum', 'permission:admin.access'])->group(function () {
    Route::apiResource('branches', BranchController::class);
});

Branch Isolation

The EnsureBranchContext middleware enforces that users can only access data from branches they're assigned to:

php
// Middleware resolves branch from (in priority order):
// 1. X-Branch-Id header
// 2. branch_id query parameter
// 3. User's default_branch_id

// Returns 400 if no branch context provided
// Returns 403 if user doesn't have access to the branch

In Controllers/Services

You can check permissions programmatically:

php
// Check if user has a permission
$user->hasPermissionTo('patients.create');

// Check if user has a role
$user->hasRole('admin');

// Check if user has any of the given roles
$user->hasAnyRole(['admin', 'doctor']);

Branch Access

Users are assigned to branches via the branch_users pivot table. A user can:

  • Work at multiple branches (many-to-many)
  • Have a default branch (default_branch_id on the user)
  • Switch branches via POST /api/v1/auth/switch-branch

The EnsureBranchContext middleware validates that the authenticated user has access to the requested branch before allowing the request to proceed.

Adding New Permissions

  1. Add the permission to RoleSeeder:
    php
    'new-module' => ['create', 'read', 'update', 'delete'],
  2. Assign it to the appropriate roles in the same seeder
  3. Run php artisan db:seed --class=RoleSeeder
  4. Use the permission in routes or code:
    php
    Route::middleware('permission:new-module.create')->post('/new-module', ...);

Guard Configuration

All permissions use the web guard (configured in Spatie's config):

php
// config/auth.php
'defaults' => [
    'guard' => 'web',
],

Sanctum authenticates the token and then uses the web guard for permission checks.

CPR - Clinical Patient Records