implemented operation based permissions
This commit is contained in:
124
core/lib/Security/Authorization/PermissionChecker.php
Normal file
124
core/lib/Security/Authorization/PermissionChecker.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace KTXC\Security\Authorization;
|
||||
|
||||
use KTXC\SessionIdentity;
|
||||
|
||||
/**
|
||||
* Permission Checker
|
||||
* Provides granular permission checking with support for wildcards
|
||||
*/
|
||||
class PermissionChecker
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SessionIdentity $sessionIdentity
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Check if user has a specific permission
|
||||
* Supports wildcards: user_manager.users.* matches all user actions
|
||||
*
|
||||
* @param string $permission Permission to check (e.g., "user_manager.users.create")
|
||||
* @param mixed $resource Optional resource for resource-based permissions
|
||||
* @return bool
|
||||
*/
|
||||
public function can(string $permission, mixed $resource = null): bool
|
||||
{
|
||||
$identity = $this->sessionIdentity->identity();
|
||||
|
||||
if (!$identity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get user permissions from identity
|
||||
$userPermissions = $identity->getPermissions() ?? [];
|
||||
|
||||
// Super admin bypass - check for admin role
|
||||
$roles = $identity->getRoles() ?? [];
|
||||
if (in_array('admin', $roles) || in_array('system.admin', $roles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exact match
|
||||
if (in_array($permission, $userPermissions)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wildcard match: user_manager.users.* allows user_manager.users.create
|
||||
foreach ($userPermissions as $userPerm) {
|
||||
if (str_ends_with($userPerm, '.*')) {
|
||||
$prefix = substr($userPerm, 0, -2);
|
||||
if (str_starts_with($permission, $prefix . '.')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Full wildcard: * grants all permissions
|
||||
if (in_array('*', $userPermissions)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has ANY of the permissions (OR logic)
|
||||
*
|
||||
* @param array $permissions Array of permissions to check
|
||||
* @param mixed $resource Optional resource for resource-based permissions
|
||||
* @return bool
|
||||
*/
|
||||
public function canAny(array $permissions, mixed $resource = null): bool
|
||||
{
|
||||
if (empty($permissions)) {
|
||||
return true; // No permissions required
|
||||
}
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
if ($this->can($permission, $resource)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has ALL permissions (AND logic)
|
||||
*
|
||||
* @param array $permissions Array of permissions to check
|
||||
* @param mixed $resource Optional resource for resource-based permissions
|
||||
* @return bool
|
||||
*/
|
||||
public function canAll(array $permissions, mixed $resource = null): bool
|
||||
{
|
||||
if (empty($permissions)) {
|
||||
return true; // No permissions required
|
||||
}
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
if (!$this->can($permission, $resource)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all permissions for the current user
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserPermissions(): array
|
||||
{
|
||||
$identity = $this->sessionIdentity->identity();
|
||||
|
||||
if (!$identity) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $identity->getPermissions() ?? [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user