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(); |
|
|
|
|
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(); |
|
|
|
|
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(); |
|
|
|
|
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
|
|
|
|
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.