Add Redis-based permission caching for users and subusers
- Introduced Redis-backed caching for user and subuser permission evaluations in the `route_t` trait, reducing database queries. - Enhanced `Redis` class with methods for permission caching: `cache_permission`, `get_permission`, and `clear_permission`. - Added test coverage for the new caching logic in `PermissionRedisCacheTest.php`. - Implemented Redis caching for authentication sessions with `cache_auth_session`, `get_auth_session`, and `clear_auth_session`. - Improved CORS handling for preflight requests in `index.php`.
This commit is contained in:
@@ -346,7 +346,25 @@ trait route_t
|
||||
}
|
||||
// Expose resolved target customer in response meta for subuser requests
|
||||
$response->add_meta('target_customer_number', (int)$resolvedCustomer);
|
||||
$subuser_has_permission = $subuser->hasPermission($permission->subusers_node_key);
|
||||
|
||||
$cacheKey = "subuser:{$subuser->id}:{$resolvedCustomer}:{$permission->subusers_node_key->name}";
|
||||
if (!isset(self::$__perm_subuser_grant_cache[$cacheKey])) {
|
||||
$cached = null;
|
||||
if (defined('redis')) {
|
||||
$cached = redis->get_permission($cacheKey);
|
||||
}
|
||||
if ($cached !== null) {
|
||||
self::$__perm_subuser_grant_cache[$cacheKey] = $cached;
|
||||
} else {
|
||||
$subuser_has_permission = $subuser->hasPermission($permission->subusers_node_key);
|
||||
if (defined('redis')) {
|
||||
redis->cache_permission($cacheKey, $subuser_has_permission);
|
||||
}
|
||||
self::$__perm_subuser_grant_cache[$cacheKey] = $subuser_has_permission;
|
||||
}
|
||||
}
|
||||
$subuser_has_permission = self::$__perm_subuser_grant_cache[$cacheKey];
|
||||
|
||||
if (!$subuser_has_permission && $throwOnDeny) {
|
||||
(new logs_o())->add('global', 'global', 1, $subuser->id ?? 0, 'PERMISSION_DENIED', 'Permission denied via subuser node: ' . $permission->permission . ' (Node: ' . $permission->subusers_node_key->name . ', Customer: ' . $resolvedCustomer . ')');
|
||||
$response->error('Permission denied for subuser. Missing permission: ' . $permission->permission . ' (Customer context: ' . $resolvedCustomer . ')', 403);
|
||||
@@ -365,10 +383,25 @@ trait route_t
|
||||
}
|
||||
$perm_string = $permission instanceof permission_node ? $permission->permission : $permission;
|
||||
$userCacheKey = (string)$user->id . ':' . $perm_string;
|
||||
$redisKey = "user:{$user->id}:{$perm_string}";
|
||||
|
||||
if (!isset(self::$__perm_user_cache[$userCacheKey])) {
|
||||
self::$__perm_user_cache[$userCacheKey] = (bool)$user->hasPermission($perm_string);
|
||||
$cached = null;
|
||||
if (defined('redis')) {
|
||||
$cached = redis->get_permission($redisKey);
|
||||
}
|
||||
if ($cached !== null) {
|
||||
self::$__perm_user_cache[$userCacheKey] = $cached;
|
||||
} else {
|
||||
$allowed = (bool)$user->hasPermission($perm_string);
|
||||
if (defined('redis')) {
|
||||
redis->cache_permission($redisKey, $allowed);
|
||||
}
|
||||
self::$__perm_user_cache[$userCacheKey] = $allowed;
|
||||
}
|
||||
}
|
||||
$allowed = (bool)self::$__perm_user_cache[$userCacheKey];
|
||||
|
||||
if (!$allowed && $throwOnDeny) {
|
||||
(new logs_o())->add('global', 'global', 1, $user->id, 'PERMISSION_DENIED', 'Permission denied. Missing permission: ' . $perm_string);
|
||||
$response->error('Permission denied. Missing permission: ' . $perm_string . ' for user: ' . $user->id . ' In group: ' . $user->group_id->value(), 403);
|
||||
|
||||
Reference in New Issue
Block a user