Crafting a Permission-Aware Navigation for Laravel SaaS
Creating a multi-tenant SaaS application with Laravel involves numerous challenges, especially when it comes to navigation. Unlike simple navigation systems, a multi-tenant application requires a dynamic, permission-based approach that adapts to the user's role and company.
The Challenge
In a role-based access system, navigation must be tailored to different user types:
- Admins: Access to admin panels.
- Company Owners: Access to all modules, such as Orders and Accounting.
- Employees: Limited access based on permissions.
Each module includes sub-pages with distinct permission needs. The system must also adapt when users switch companies, ensuring seamless navigation on both desktop and mobile devices. Importantly, users should never encounter a 403 error; they should be redirected to an accessible page.
System Architecture
The navigation structure is built through a series of steps:
- LayoutController: Initiates layout requests.
- LayoutDataService: Manages navigation contexts with methods like
getNav()for different levels andgetFirstAllowedRouteName()for smart redirects. - Middleware: Shares layout data with the frontend.
- Vue Frontend: Renders the navigation for desktop and mobile.
Backend: LayoutDataService
The core of the system is the LayoutDataService, which handles navigation across different contexts, ensuring consistency and accuracy.
Menu Item Structure
Each menu item includes:
- Translated label
- Target URL
- Permission slug
- Route name
- Icon file
- Active state indicator
- Company-specific flag
Permission Filtering
The checkUserAndCompanyPolicy() method ensures proper access:
- Admins have full access.
- Public items are accessible to authenticated users.
- Company-specific checks cater to user roles and permissions.
Handling Different User Types
Navigation is tailored to three user types:
- Admin: Access to admin-specific modules.
- Owner: Full access to business modules.
- Employee: Limited to permitted modules.
Owners see all modules, even if subscriptions lapse, with blocking handled at the page level.
Sub-Menu Routing
Modules route users to default sub-pages, with permissions controlling sub-route visibility, ensuring employees see only permitted sections.
First Allowed Route (FAR) Pattern
This pattern avoids 403 errors by redirecting users to accessible pages based on roles and permissions.
User-Configurable Default Pages
Users can set a preferred landing page per company, updated automatically if permissions change.
Data Flow to Frontend
Everything needed for frontend rendering is delivered in a single request, ensuring efficiency and reducing API calls.
Desktop and Mobile Navigation
- Desktop: Utilizes a two-tier header for module and sub-page navigation.
- Mobile: Employs a hierarchical tree structure with a slide-out menu.
State Management and Testing
No complex state management is needed; reactive refs handle state changes. Comprehensive testing ensures security and functionality, with test cases covering various scenarios.
Key Takeaway
The complexity is managed on the backend, allowing the frontend to focus on rendering. This approach ensures an efficient, scalable navigation system for Laravel SaaS applications.
LaraFoundry, an open-source framework, exemplifies this methodology, offering a seamless solution for SaaS navigation challenges.