@php $policy = $accessPolicyConfig ?? []; $baseRoles = $policy['base_roles'] ?? ['admin', 'manager', 'accountant', 'officer', 'applicant', 'user']; $dayLabels = $policy['day_labels'] ?? [1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat', 7 => 'Sun']; $globalIps = $policy['global_ips'] ?? []; if ($globalIps === []) { $globalIps = ['']; } $roleIps = $policy['role_ips'] ?? []; foreach ($baseRoles as $roleKey) { if (! isset($roleIps[$roleKey])) { $roleIps[$roleKey] = []; } } $roleWindows = $policy['role_login_windows'] ?? []; $sensitiveRoutes = $policy['sensitive_routes'] ?? []; if ($sensitiveRoutes === []) { $sensitiveRoutes = ['']; } $policyTurboAttr = \App\Support\Navigation\WorkspaceEmbed::isEmbedded() ? ['data-turbo-frame' => $accessRolesTurboFrame ?? '_top'] : []; @endphp

Access Policies

Control login windows, trusted devices, and IP restrictions for sensitive loan modules. These rules apply on top of role permissions.

Device governance {{ ($policy['device_governance_enabled'] ?? false) ? 'ON' : 'OFF' }} IP restrictions {{ ($policy['ip_restrictions_enabled'] ?? false) ? 'ON' : 'OFF' }}

Session timeout

10 min inactivity · auto logout

High-risk pages

Setup, accounting, financial

IP restriction

Sensitive routes when enabled

Login windows

Per base role below

Unique credentials

No shared staff logins

$val) {{ $attr }}="{{ $val }}" @endforeach x-data="{ globalIps: @js($globalIps), roleIps: @js($roleIps), sensitiveRoutes: @js($sensitiveRoutes), selectedRole: @js($baseRoles[0] ?? 'admin'), addGlobalIp() { this.globalIps.push(''); }, removeGlobalIp(i) { this.globalIps.splice(i, 1); if (!this.globalIps.length) this.globalIps.push(''); }, addRoleIp(role) { if (!this.roleIps[role]) this.roleIps[role] = []; this.roleIps[role].push(''); }, removeRoleIp(role, i) { if (this.roleIps[role]) this.roleIps[role].splice(i, 1); }, addSensitiveRoute() { this.sensitiveRoutes.push(''); }, removeSensitiveRoute(i) { this.sensitiveRoutes.splice(i, 1); if (!this.sensitiveRoutes.length) this.sensitiveRoutes.push(''); } }"> @csrf

Policy switches

Super admins and device master-key holders bypass login-window and IP checks.

Global IP allowlist

IPs or CIDR (e.g. 192.168.1.0/24). Empty = no global list.

Role login windows

Uses each user's effective base role.

@foreach ($baseRoles as $role) @php $window = $roleWindows[$role] ?? ['enabled' => true, 'days' => [1,2,3,4,5], 'start' => '06:00', 'end' => '20:00']; $enabledDays = $window['days'] ?? []; @endphp

{{ $role }}

@foreach ($dayLabels as $dayNum => $dayLabel) @endforeach
@endforeach

Per-role IP overrides

Merged with global allowlist.

@foreach ($baseRoles as $role)

No extra IPs for this role.

@endforeach

Sensitive route patterns

Wildcards supported (loan.accounting*).

@php $moduleRoleGateConfig = $moduleRoleGateConfig ?? ['modules' => [], 'base_roles' => []]; $moduleGateModules = $moduleRoleGateConfig['modules'] ?? []; $moduleGateBaseRoles = $moduleRoleGateConfig['base_roles'] ?? []; @endphp @if ($moduleGateModules !== [] && $moduleGateBaseRoles !== [])
$val) {{ $attr }}="{{ $val }}" @endforeach> @csrf

Module visibility by base role

This organization only. Add or remove a base tier (for example Officer) without changing the person's access role. They still need the matching permission (for Accounting: accounting.view to see it, accounting.create to raise a requisition). Other organizations keep their own list.

@foreach ($moduleGateBaseRoles as $baseRole) @endforeach @foreach ($moduleGateModules as $module) @foreach ($moduleGateBaseRoles as $baseRole) @php $slug = $baseRole['slug']; @endphp @endforeach @endforeach
Module{{ $baseRole['name'] }}

{{ $module['label'] }}

{{ $module['description'] }}

@if ($module['is_custom'])

Custom for this organization

@else

Using system default

@endif

Clearing every box for a module restores the system default. Directors still follow Admin/Manager when those tiers are checked.

@endif