From 6f69534047a5fac9923d2a67f6ed0f7dc7fe20a4 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 13 Jan 2026 08:45:38 +0000 Subject: [PATCH] Add upstream migration guide for Permission/resolved_permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../permission_resolved_01_13.txt | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100755 app/RSpade/upstream_changes/permission_resolved_01_13.txt diff --git a/app/RSpade/upstream_changes/permission_resolved_01_13.txt b/app/RSpade/upstream_changes/permission_resolved_01_13.txt new file mode 100755 index 000000000..a0bf9a983 --- /dev/null +++ b/app/RSpade/upstream_changes/permission_resolved_01_13.txt @@ -0,0 +1,125 @@ +PERMISSION SYSTEM - RESOLVED PERMISSIONS - MIGRATION GUIDE +Date: 2026-01-13 + +SUMMARY + The framework now provides a client-side Permission class for JavaScript + permission checking. This uses a new get_resolved_permissions() method on + User_Model that returns pre-computed permissions (role defaults with + supplementary grants/denies applied). The resolved permissions array is + automatically included in window.rsxapp.resolved_permissions. + + If your application has forked User_Model, you must add the new method. + +AFFECTED FILES + Applications with a forked User_Model (e.g., /rsx/models/user_model.php) + that extends the framework's User_Model need to ensure the parent class + method is accessible. + + If your User_Model OVERRIDES has_permission(), update it to use the new + pattern. + +CHANGES REQUIRED + + 1. If You Have NOT Forked User_Model + + No action required. The framework's User_Model already has the new + method and your application will inherit it automatically. + + 2. If You Have Forked User_Model (extends framework User_Model) + + Ensure your class does NOT override has_permission() or if it does, + update it to use get_resolved_permissions(): + + BEFORE (if overridden): + public function has_permission(int $permission): bool + { + // Custom logic + if ($this->role_id === self::ROLE_DISABLED) { + return false; + } + if ($this->has_supplementary_deny($permission)) { + return false; + } + if ($this->has_supplementary_grant($permission)) { + return true; + } + return in_array($permission, $this->role_id__permissions ?? [], true); + } + + AFTER: + public function has_permission(int $permission): bool + { + return in_array($permission, $this->get_resolved_permissions(), true); + } + + If you need custom permission logic, override get_resolved_permissions() + instead of has_permission(). + + 3. If You Have Completely Replaced User_Model (not extending framework) + + Add the get_resolved_permissions() method to your model: + + /** + * Get all resolved permissions for this user + * + * @return array Array of permission IDs the user has + */ + public function get_resolved_permissions(): array + { + // Return empty for disabled users + if ($this->role_id === self::ROLE_DISABLED) { + return []; + } + + // Start with role default permissions + $permissions = $this->role_id__permissions ?? []; + + // Add supplementary GRANTs + $supplementary = $this->_load_supplementary_permissions(); + foreach ($supplementary['grants'] as $perm_id) { + if (!in_array($perm_id, $permissions, true)) { + $permissions[] = $perm_id; + } + } + + // Remove supplementary DENYs + $permissions = array_values(array_diff($permissions, $supplementary['denies'])); + + sort($permissions); + return $permissions; + } + + Then update has_permission() to use it: + + public function has_permission(int $permission): bool + { + return in_array($permission, $this->get_resolved_permissions(), true); + } + +NEW FEATURES AVAILABLE + + PHP: + $user->get_resolved_permissions() // Returns [1, 2, 3, ...] permission IDs + + JavaScript: + Permission.is_logged_in() + Permission.has_permission(User_Model.PERM_EDIT_DATA) + Permission.has_any_permission([User_Model.PERM_EDIT_DATA, User_Model.PERM_VIEW_DATA]) + Permission.has_all_permissions([...]) + Permission.has_role(User_Model.ROLE_MANAGER) + Permission.can_admin_role(User_Model.ROLE_USER) + Permission.get_resolved_permissions() + + window.rsxapp: + window.rsxapp.resolved_permissions // Array of permission IDs + +VERIFICATION + 1. Load any authenticated page + 2. Open browser console + 3. Verify: window.rsxapp.resolved_permissions is an array of integers + 4. Verify: Permission.has_permission(User_Model.PERM_VIEW_DATA) returns boolean + 5. If you have a forked User_Model, verify no PHP errors on page load + +REFERENCE + php artisan rsx:man acls + php artisan rsx:man rsxapp