Completed
Push — master ( 540370...4c31d8 )
by Rafael
06:09
created

AccessControlListener   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 15
eloc 30
dl 0
loc 70
ccs 0
cts 49
cp 0
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A onSubmitMutation() 0 8 3
A __construct() 0 3 1
B preReadField() 0 33 10
A getSubscribedEvents() 0 5 1
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\EventListener\GraphQL;
12
13
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14
use Ynlo\GraphQLBundle\Events\GraphQLEvents;
15
use Ynlo\GraphQLBundle\Events\GraphQLFieldEvent;
16
use Ynlo\GraphQLBundle\Events\GraphQLMutationEvent;
17
use Ynlo\GraphQLBundle\Exception\Controlled\ForbiddenError;
18
use Ynlo\GraphQLBundle\Security\Authorization\AccessControlChecker;
19
use Ynlo\GraphQLBundle\Util\TypeUtil;
20
21
class AccessControlListener implements EventSubscriberInterface
22
{
23
    /**
24
     * @var AccessControlChecker
25
     */
26
    protected $accessControlChecker;
27
28
    /**
29
     * @param AccessControlChecker $accessControlChecker
30
     */
31
    public function __construct(AccessControlChecker $accessControlChecker)
32
    {
33
        $this->accessControlChecker = $accessControlChecker;
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    public static function getSubscribedEvents()
40
    {
41
        return [
42
            GraphQLEvents::PRE_READ_FIELD => 'preReadField',
43
            GraphQLEvents::MUTATION_SUBMITTED => 'onSubmitMutation',
44
        ];
45
    }
46
47
    public function onSubmitMutation(GraphQLMutationEvent $event)
48
    {
49
        $operation = $event->getContext()->getDefinition();
50
        if ($this->accessControlChecker->isControlled($operation)
51
            && !$this->accessControlChecker->isGranted($operation, $event->getFormEvent()->getData())
52
        ) {
53
            $message = $this->accessControlChecker->getMessage($operation) ?? null;
54
            throw new ForbiddenError($message);
55
        }
56
    }
57
58
    public function preReadField(GraphQLFieldEvent $event)
59
    {
60
        //check firstly if the user have rights to read the operation
61
        $node = $event->getContext()->getNode();
62
        if ($node && $this->accessControlChecker->isControlled($node)
63
            && !$this->accessControlChecker->isGranted($node, $event->getContext()->getRoot())
64
        ) {
65
            $event->stopPropagation();
66
            $event->setValue(null);
67
            throw new ForbiddenError($this->accessControlChecker->getMessage($node));
68
        }
69
70
        //check if user have rights to read the object
71
        if (\is_object($event->getContext()->getRoot())) {
72
            $concreteType = TypeUtil::resolveObjectType($event->getContext()->getEndpoint(), $event->getContext()->getRoot());
73
            if ($concreteType) {
74
                $objectDefinition = $event->getContext()->getEndpoint()->getType($concreteType);
75
                if ($this->accessControlChecker->isControlled($objectDefinition)
76
                    && !$this->accessControlChecker->isGranted($objectDefinition, $event->getContext()->getRoot())
77
                ) {
78
                    $event->stopPropagation();
79
                    $event->setValue(null);
80
                    throw new ForbiddenError($this->accessControlChecker->getMessage($objectDefinition));
81
                }
82
            }
83
        }
84
85
        //check then if the user have rights to read the field
86
        $field = $event->getContext()->getDefinition();
87
        if ($this->accessControlChecker->isControlled($field)
88
            && !$this->accessControlChecker->isGranted($field, $event->getContext()->getRoot())
89
        ) {
90
            throw new ForbiddenError($this->accessControlChecker->getMessage($field));
91
        }
92
    }
93
}
94