125 lines
3.4 KiB
PHP
125 lines
3.4 KiB
PHP
<?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() ?? [];
|
|
}
|
|
}
|