SecurableMethodInvoker   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 3
Bugs 2 Features 0
Metric Value
wmc 5
c 3
b 2
f 0
lcom 1
cbo 8
dl 0
loc 71
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A invoke() 0 19 4
1
<?php
2
3
namespace Tonic\Component\ApiLayer\JsonRpcExtensions\Security\Method;
4
5
use Doctrine\Common\Annotations\Reader;
6
use Symfony\Component\PropertyAccess\PropertyAccessor;
7
use Tonic\Component\ApiLayer\JsonRpc\Method\MethodInvokerInterface;
8
use Tonic\Component\ApiLayer\JsonRpcExtensions\Security\Annotation\Attribute;
9
use Tonic\Component\ApiLayer\JsonRpcExtensions\Security\Exception\AccessDeniedException;
10
use Tonic\Component\ApiLayer\JsonRpcExtensions\Security\GuardInterface;
11
use Tonic\Component\ApiLayer\JsonRpcExtensions\Security\UserProviderInterface;
12
use Tonic\Component\Reflection\ReflectionFunctionFactory;
13
14
/**
15
 * Decorator for method invoker, which allows to secure method invokation.
16
 */
17
class SecurableMethodInvoker implements MethodInvokerInterface
18
{
19
    /**
20
     * @var MethodInvokerInterface
21
     */
22
    private $methodInvoker;
23
24
    /**
25
     * @var UserProviderInterface
26
     */
27
    private $userProvider;
28
29
    /**
30
     * @var GuardInterface
31
     */
32
    private $guard;
33
34
    /**
35
     * @var Reader
36
     */
37
    private $annotationReader;
38
39
    /**
40
     * @var PropertyAccessor
41
     */
42
    private $propertyAccessor;
43
44
    /**
45
     * @param MethodInvokerInterface $methodInvoker
46
     * @param UserProviderInterface  $userProvider
47
     * @param GuardInterface         $guard
48
     * @param Reader                 $annotationReader
49
     * @param PropertyAccessor       $propertyAccessor
50
     */
51
    public function __construct(
52
        MethodInvokerInterface $methodInvoker,
53
        UserProviderInterface $userProvider,
54
        GuardInterface $guard,
55
        Reader $annotationReader,
56
        PropertyAccessor $propertyAccessor
57
    ) {
58
        $this->methodInvoker = $methodInvoker;
59
        $this->userProvider = $userProvider;
60
        $this->guard = $guard;
61
        $this->annotationReader = $annotationReader;
62
        $this->propertyAccessor = $propertyAccessor;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function invoke(callable $callable, $requestObject)
69
    {
70
        /** @var Attribute $attributeAnnotation */
71
        $attributeAnnotation = $this->annotationReader->getMethodAnnotation(ReflectionFunctionFactory::createReflectionMethodFromCallable($callable), Attribute::class);
72
        $attributeName = $attributeAnnotation->name;
73
        $attributeValue = $this->propertyAccessor->getValue($requestObject, $attributeAnnotation->valueAt);
74
75
        $userId = $this->userProvider->getUserId();
76
        if ((!is_array($attributeValue)) && (!$this->guard->isGranted($userId, $attributeName, $attributeValue))) {
77
            throw new AccessDeniedException();
78
        }
79
80
        if (is_array($attributeValue)) {
81
            $attributeValue = $this->guard->filterGranted($userId, $attributeName, $attributeValue);
82
            $this->propertyAccessor->setValue($requestObject, $attributeAnnotation->valueAt, $attributeValue);
83
        }
84
85
        return $this->methodInvoker->invoke($callable, $requestObject);
86
    }
87
}
88