Authentication & Authorization
Session-Based Auth
The Portal uses session-based authentication. Users log in at /login (the Signin Livewire component), which sets session variables:
session('userid')— The user’s IDsession('usertype')— Integer role code (see below)session('internal_user_id')— Set for internal/staff users
Logout is handled by RegistrationController@logout at /logout.
User Types (Roles)
Defined in app/Constants/Role.php:
| Value | Constant | Display Name (UK) | Display Name (US) |
|---|---|---|---|
| 1 | ADMIN | Administrator | Administrator |
| 2 | LANDLORD | Landlord | Property Owner |
| 3 | USER | User | User |
| 4 | MODERATOR | Moderator | Moderator |
| 5 | MANAGER | Manager | Manager |
| 6 | MODERATOR_ADMIN | Admin | Admin |
| 7 | OPERATOR | Operator | Operator |
| 8 | BUSINESSTOBUSINESS | BusinessToBusiness | BusinessToBusiness |
| 9 | POWER_USER | Power User | Power User |
These are stored as the role column on the users table.
Middleware
Four session-check middleware classes control panel access. They are registered as aliases in the kernel and used in routes/web.php.
AdminSession (app/Http/Middleware/Admin.php)
Allows: session('usertype') == 1 OR session('internal_user_id') is set
Redirects to: /loginAdmin users with usertype == 1 are the original superadmins. Internal users (staff members stored in the internal_users table) also get access. For Filament routes (internal-admin*), the middleware additionally calls Auth::login() to authenticate the user into Laravel’s auth system.
LandlordSession (app/Http/Middleware/Landlord.php)
Allows: session('usertype') in [2, 7]
Redirects to: /loginAlso checks the USE_BOOST_CREDITS feature flag and stores the result in the session. Restricts B2B dashboard access to allowed user IDs.
ModeratorSession (app/Http/Middleware/Moderator.php)
Allows: session('usertype') in [4, 5, 6, 7, 9]
Redirects to: /loginAllows moderators, managers, moderator admins, operators, and power users.
BusinessToBusinessSession (app/Http/Middleware/BusinessToBusiness.php)
Allows: session('usertype') == 8
Redirects to: /loginPermission System (Admin Panel)
Beyond basic usertype checks, admin routes use a granular permission system via the CheckPermission middleware.
How It Works
- Superadmins (
usertype == 1) bypass all permission checks. - Internal users with
adminrole bypass all permission checks. - Internal users with
managerrole bypass all checks exceptuser-management. - Other internal users must have the specific permission slug assigned to one of their roles.
Database Tables
internal_users— Staff user accounts (separate from the mainuserstable)internal_roles— Role definitions (model:Role)internal_permissions— Permission definitions (model:Permission)internal_role_user— Many-to-many: internal users to rolesinternal_permission_role— Many-to-many: roles to permissions
Models
InternalUser(app/Models/InternalUser.php) — ExtendsAuthenticatable, hasroles()relationship,hasRole()andhasPermission()methods.Role(app/Models/Role.php) — Maps tointernal_roles, haspermissions()andusers()relationships.Permission(app/Models/Permission.php) — Maps tointernal_permissions, hasroles()relationship.
Permission Slugs Used in Routes
From routes/web.php, the following permission slugs are enforced:
user-management— Admin user managementdrops— Push notification dropsconcierge— Concierge enquiry managementdocuments— Document managementhouses— House listing managementinsights— Analytics dashboardagents— Agent managementstudents— Student managementperks— Perks and events managementcustomer-support— Customer support and contract uploadsnotifications— Notification managementuniversity-expansion— University expansion tools
Caching
Permission lookups are cached for 1 hour per internal user ID using Laravel’s Cache::remember():
user_has_admin_role_{id}user_has_manager_role_{id}user_permissions_{id}
Filament Auth
The Filament panel at /internal-admin uses the AdminSession middleware as its authMiddleware. This means the same session-based authentication applies. When accessing Filament routes, the Admin middleware also calls Auth::login() with the session user to satisfy Filament’s built-in auth requirements.
Password Reset
/forgot— ForgotPassword Livewire component/resetPassword— ResetPassword Livewire component/reset/{id}— ResetPasswordContainer (token-based reset)