1
|
|
|
<?php declare(strict_types=1);
|
2
|
|
|
|
3
|
|
|
namespace jschreuder\MiddleAuth\Rbac;
|
4
|
|
|
|
5
|
|
|
use jschreuder\MiddleAuth\AuthorizationHandlerInterface;
|
6
|
|
|
use jschreuder\MiddleAuth\AuthorizationMiddlewareInterface;
|
7
|
|
|
use jschreuder\MiddleAuth\AuthorizationRequestInterface;
|
8
|
|
|
use jschreuder\MiddleAuth\AuthorizationResponseInterface;
|
9
|
|
|
use jschreuder\MiddleAuth\Basic\AuthorizationResponse;
|
10
|
|
|
use jschreuder\MiddleAuth\Util\AuthLoggerInterface;
|
11
|
|
|
use jschreuder\MiddleAuth\Util\NullAuthLogger;
|
12
|
|
|
|
13
|
|
|
final class RbacMiddleware implements AuthorizationMiddlewareInterface
|
14
|
|
|
{
|
15
|
|
|
private AuthLoggerInterface $logger;
|
16
|
|
|
|
17
|
12 |
|
public function __construct(
|
18
|
|
|
private RoleProviderInterface $roleProvider,
|
19
|
|
|
?AuthLoggerInterface $logger = null
|
20
|
|
|
)
|
21
|
|
|
{
|
22
|
12 |
|
$this->logger = $logger ?? new NullAuthLogger();
|
23
|
|
|
}
|
24
|
|
|
|
25
|
10 |
|
public function process(
|
26
|
|
|
AuthorizationRequestInterface $request,
|
27
|
|
|
AuthorizationHandlerInterface $handler
|
28
|
|
|
): AuthorizationResponseInterface
|
29
|
|
|
{
|
30
|
10 |
|
$actor = $request->getSubject();
|
31
|
10 |
|
$resource = $request->getResource();
|
32
|
10 |
|
$action = $request->getAction();
|
33
|
|
|
|
34
|
10 |
|
$roles = $this->roleProvider->getRolesForActor($actor);
|
35
|
|
|
|
36
|
10 |
|
$this->logger->debug('RBAC middleware evaluating request', [
|
37
|
10 |
|
'subject_type' => $actor->getType(),
|
38
|
10 |
|
'subject_id' => $actor->getId(),
|
39
|
10 |
|
'resource_type' => $resource->getType(),
|
40
|
10 |
|
'resource_id' => $resource->getId(),
|
41
|
10 |
|
'action' => $action,
|
42
|
10 |
|
'roles_count' => $roles->count(),
|
43
|
10 |
|
]);
|
44
|
|
|
|
45
|
10 |
|
foreach ($roles as $role) {
|
46
|
6 |
|
$this->logger->debug('Checking role permissions', [
|
47
|
6 |
|
'role_name' => $role->getName(),
|
48
|
6 |
|
'permissions_count' => $role->getPermissions()->count(),
|
49
|
6 |
|
]);
|
50
|
|
|
|
51
|
6 |
|
foreach ($role->getPermissions() as $permission) {
|
52
|
|
|
if (
|
53
|
6 |
|
$permission->matchesResource($resource)
|
54
|
6 |
|
&& $permission->matchesAction($action)
|
55
|
|
|
) {
|
56
|
4 |
|
$this->logger->debug('Permission matched', [
|
57
|
4 |
|
'role_name' => $role->getName(),
|
58
|
4 |
|
'resource_type' => $resource->getType(),
|
59
|
4 |
|
'action' => $action,
|
60
|
4 |
|
]);
|
61
|
|
|
|
62
|
4 |
|
return new AuthorizationResponse(
|
63
|
4 |
|
true,
|
64
|
4 |
|
'Access granted by ' . self::class,
|
65
|
4 |
|
self::class
|
66
|
4 |
|
);
|
67
|
|
|
}
|
68
|
|
|
}
|
69
|
|
|
}
|
70
|
|
|
|
71
|
6 |
|
$this->logger->debug('No role permissions matched, delegating to next handler');
|
72
|
|
|
|
73
|
6 |
|
return $handler->handle($request);
|
74
|
|
|
}
|
75
|
|
|
}
|
76
|
|
|
|