When building JoRooms—a multi-tenant hotel booking ecosystem—we faced a challenge: How do we manage access for Super Admins, Hotel Managers, and Agents without creating a "spaghetti" of if/else statements?
The answer: Dynamic Role-Based Access Control (RBAC) using Spatie Laravel Permission.
🛠 The Architecture
We didn’t just want "Fixed Roles." We built a Flexible Role Engine where permissions are granular, and roles are simply "containers" for those permissions.
The Tech Stack:
Backend: Laravel & Spatie (The Source of Truth)
Logic: Laravel Policies (For multi-tenant hotel_id scoping)
Frontend: React (Conditional Rendering based on the User's Permission Snapshot)
🔑 Key Implementation Highlights
The Permissions Matrix
Instead of checking if($user->isManager()), we check if($user->can('manage-rooms')). This decouples the identity from the action.Multi-Tenant Scoping (The "Hotel Boundary")
A manager at Hotel A should never edit rooms at Hotel B. We solve this by combining Spatie permissions with Laravel Policies:Flexible UI
On the React side, we don't just hide buttons; we sync the user’s permission set to the state, ensuring a seamless and secure UX.
💡 Why This Matters for Product Growth
A flexible RBAC system isn't just a "dev task"—it's a business feature. It allows us to:
Upsell: Create "Premium" roles with advanced reporting access.
Onboard Faster: Custom roles for specific agent tiers.
Security: Follow the "Principle of Least Privilege" (PoLP).
The Result? A secure, multi-tenant environment that can scale from 10 hotels to 10,000 without a single line of code change in the authorization logic.
🏗 How are you handling complex authorization in your SaaS?
Are you team Policies, Gate-only, or a Custom Engine? Let’s discuss in the comments! 👇
Top comments (0)