1
|
|
|
<?php declare(strict_types=1);
|
2
|
|
|
|
3
|
|
|
namespace jschreuder\MiddleAuth\Abac;
|
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 AbacMiddleware implements AuthorizationMiddlewareInterface
|
14
|
|
|
{
|
15
|
12 |
|
public function __construct(
|
16
|
|
|
private PolicyProviderInterface $policyProvider,
|
17
|
|
|
private ?AuthLoggerInterface $logger = null
|
18
|
|
|
)
|
19
|
|
|
{
|
20
|
12 |
|
if (is_null($logger)) {
|
21
|
8 |
|
$this->logger = new NullAuthLogger();
|
22
|
|
|
}
|
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
|
10 |
|
$context = $request->getContext();
|
34
|
|
|
|
35
|
10 |
|
$policies = $this->policyProvider->getPolicies($actor, $resource, $action, $context);
|
36
|
|
|
|
37
|
10 |
|
$this->logger->debug('ABAC middleware evaluating request', [
|
|
|
|
|
38
|
10 |
|
'subject_type' => $actor->getType(),
|
39
|
10 |
|
'subject_id' => $actor->getId(),
|
40
|
10 |
|
'resource_type' => $resource->getType(),
|
41
|
10 |
|
'resource_id' => $resource->getId(),
|
42
|
10 |
|
'action' => $action,
|
43
|
10 |
|
'policies_count' => $policies->count(),
|
44
|
10 |
|
'context_keys' => array_keys($context),
|
45
|
10 |
|
]);
|
46
|
|
|
|
47
|
10 |
|
foreach ($policies as $policy) {
|
48
|
6 |
|
$policyDescription = $policy->getDescription();
|
49
|
6 |
|
$this->logger->debug('Evaluating policy', ['policy_description' => $policyDescription]);
|
50
|
|
|
|
51
|
6 |
|
if ($policy->evaluate($actor, $resource, $action, $context)) {
|
52
|
4 |
|
$this->logger->debug('Policy granted access', ['policy_description' => $policyDescription ?? $policy->getDescription()]);
|
53
|
|
|
|
54
|
4 |
|
return new AuthorizationResponse(
|
55
|
4 |
|
true,
|
56
|
4 |
|
'Access granted by ' . self::class,
|
57
|
4 |
|
self::class
|
58
|
4 |
|
);
|
59
|
|
|
}
|
60
|
|
|
}
|
61
|
|
|
|
62
|
6 |
|
$this->logger->debug('No policies granted access, delegating to next handler');
|
63
|
|
|
|
64
|
6 |
|
return $handler->handle($request);
|
65
|
|
|
}
|
66
|
|
|
}
|
67
|
|
|
|
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.