Add client-side Permission class and resolved_permissions to rsxapp

Refactor date/time classes to reduce code redundancy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-01-13 08:35:06 +00:00
parent f70ca09f78
commit 8ef798c30f
11 changed files with 783 additions and 466 deletions

View File

@@ -102,7 +102,7 @@ class User_Model extends Rsx_Site_Model_Abstract
use SoftDeletes;
/**
* Cached supplementary permissions for this user
* Cached supplementary permissions for this user (avoids repeated DB queries)
* @var array|null
*/
protected $_supplementary_permissions = null;
@@ -238,38 +238,53 @@ class User_Model extends Rsx_Site_Model_Abstract
// =========================================================================
/**
* Check if user has a specific permission
* Get all resolved permissions for this user
*
* Resolution order:
* 1. DISABLED role = deny all
* 2. Supplementary DENY = deny
* 3. Supplementary GRANT = grant
* 4. Role default permissions = grant if included
* 5. Deny
* Returns the final permission array after applying:
* 1. Role default permissions
* 2. Supplementary GRANTs (added)
* 3. Supplementary DENYs (removed)
*
* @return array Array of permission IDs the user has
*/
public function get_resolved_permissions(): array
{
// Disabled users have no permissions
if ($this->role_id === self::ROLE_DISABLED) {
return [];
}
// Start with role default permissions
$permissions = $this->role_id__permissions ?? [];
// Load supplementary overrides (DB query is cached)
$supplementary = $this->_load_supplementary_permissions();
// Add supplementary GRANTs
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 for consistent ordering
sort($permissions);
return $permissions;
}
/**
* Check if user has a specific permission
*
* @param int $permission Permission constant (PERM_*)
* @return bool
*/
public function has_permission(int $permission): bool
{
// Disabled users have no permissions
if ($this->role_id === self::ROLE_DISABLED) {
return false;
}
// Check supplementary DENY (overrides everything)
if ($this->has_supplementary_deny($permission)) {
return false;
}
// Check supplementary GRANT
if ($this->has_supplementary_grant($permission)) {
return true;
}
// Check role default permissions
$role_permissions = $this->role_id_permissions ?? [];
return in_array($permission, $role_permissions, true);
return in_array($permission, $this->get_resolved_permissions(), true);
}
/**
@@ -360,9 +375,9 @@ class User_Model extends Rsx_Site_Model_Abstract
}
/**
* Clear cached supplementary permissions (call after modifying)
* Clear cached supplementary permissions (call after modifying user_permissions table)
*/
public function clear_supplementary_cache(): void
public function clear_permission_cache(): void
{
$this->_supplementary_permissions = null;
}