Completed
Push — master ( cb616f...154d71 )
by Rafael
05:53
created

AccessControlListener::preReadField()   C

Complexity

Conditions 15
Paths 11

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 240

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 48
ccs 0
cts 39
cp 0
rs 5.9166
cc 15
nc 11
nop 1
crap 240

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Definition\FieldDefinition;
15
use Ynlo\GraphQLBundle\Definition\ObjectDefinition;
16
use Ynlo\GraphQLBundle\Definition\QueryDefinition;
17
use Ynlo\GraphQLBundle\Events\GraphQLEvents;
18
use Ynlo\GraphQLBundle\Events\GraphQLFieldEvent;
19
use Ynlo\GraphQLBundle\Events\GraphQLMutationEvent;
20
use Ynlo\GraphQLBundle\Exception\Controlled\ForbiddenError;
21
use Ynlo\GraphQLBundle\Security\Authorization\AccessControlChecker;
22
use Ynlo\GraphQLBundle\Util\TypeUtil;
23
24
class AccessControlListener implements EventSubscriberInterface
25
{
26
    /**
27
     * @var AccessControlChecker
28
     */
29
    protected $accessControlChecker;
30
31
    /**
32
     * @param AccessControlChecker $accessControlChecker
33
     */
34
    public function __construct(AccessControlChecker $accessControlChecker)
35
    {
36
        $this->accessControlChecker = $accessControlChecker;
37
    }
38
39
    /**
40
     * {@inheritDoc}
41
     */
42
    public static function getSubscribedEvents()
43
    {
44
        return [
45
            GraphQLEvents::PRE_READ_FIELD => 'preReadField',
46
            GraphQLEvents::MUTATION_SUBMITTED => 'onSubmitMutation',
47
        ];
48
    }
49
50
    public function onSubmitMutation(GraphQLMutationEvent $event)
51
    {
52
        $operation = $event->getContext()->getDefinition();
53
        if ($this->accessControlChecker->isControlled($operation)
54
            && !$this->accessControlChecker->isGranted($operation, $event->getFormEvent()->getData())
55
        ) {
56
            $message = $this->accessControlChecker->getMessage($operation) ?? null;
57
            throw new ForbiddenError($message);
58
        }
59
    }
60
61
    public function preReadField(GraphQLFieldEvent $event)
62
    {
63
        $definition = $event->getContext()->getDefinition();
64
65
        //check firstly if the user have rights to read the operation
66
        if ($definition instanceof QueryDefinition && $this->accessControlChecker->isControlled($definition)
67
            && !$this->accessControlChecker->isGranted($definition, $event->getContext()->getRoot())
68
        ) {
69
            $event->stopPropagation();
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...vent::stopPropagation() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

69
            /** @scrutinizer ignore-deprecated */ $event->stopPropagation();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
70
            $event->setValue(null);
71
            throw new ForbiddenError($this->accessControlChecker->getMessage($definition));
72
        }
73
74
        //check if user have rights to read the object
75
        if (\is_object($event->getContext()->getRoot())) {
76
            $concreteType = TypeUtil::resolveObjectType($event->getContext()->getEndpoint(), $event->getContext()->getRoot());
77
78
            if ($concreteType) {
79
                $objectDefinition = $event->getContext()->getEndpoint()->getType($concreteType);
80
                if ($this->accessControlChecker->isControlled($objectDefinition)
81
                    && !$this->accessControlChecker->isGranted($objectDefinition, $event->getContext()->getRoot())
82
                ) {
83
                    $event->stopPropagation();
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...vent::stopPropagation() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

83
                    /** @scrutinizer ignore-deprecated */ $event->stopPropagation();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
84
                    $event->setValue(null);
85
                    throw new ForbiddenError($this->accessControlChecker->getMessage($objectDefinition));
86
                }
87
88
                // check access on interfaces
89
                if ($objectDefinition instanceof ObjectDefinition){
90
                    foreach ($objectDefinition->getInterfaces() as $interface){
91
                        $interfaceDef =$event->getContext()->getEndpoint()->getType($interface);
92
                        if ($this->accessControlChecker->isControlled($interfaceDef)
93
                            && !$this->accessControlChecker->isGranted($interfaceDef, $event->getContext()->getRoot())
94
                        ) {
95
                            $event->stopPropagation();
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...vent::stopPropagation() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

95
                            /** @scrutinizer ignore-deprecated */ $event->stopPropagation();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
96
                            $event->setValue(null);
97
                            throw new ForbiddenError($this->accessControlChecker->getMessage($interfaceDef));
98
                        }
99
                    }
100
                }
101
            }
102
        }
103
104
        //check then if the user have rights to read the field
105
        if ($definition instanceof FieldDefinition && $this->accessControlChecker->isControlled($definition)
106
            && !$this->accessControlChecker->isGranted($definition, $event->getContext()->getRoot())
107
        ) {
108
            throw new ForbiddenError($this->accessControlChecker->getMessage($definition));
109
        }
110
    }
111
}
112