Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

Commit 47e17f8

Browse files
committed
Rewrite of AssertionSet and moved dynamic creation of AssertionSet to assert method of AuthorizationService.
1 parent c695e41 commit 47e17f8

File tree

5 files changed

+365
-334
lines changed

5 files changed

+365
-334
lines changed

docs/06. Using the Authorization Service.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,62 @@ This in the background will create an instance of ZfcRbac\Assertion\AssertionSet
237237

238238
ZfcRbac\Assertion\AssertionSet class is basically a container for multiple assertions as well as assertion condition.
239239
An instance of the class get's actually created automatically when you specify multiple assertions (see above)
240-
in the background, but you can also extend the class or create your own instance containing your custom assertions
240+
in the background, but you can also create your own instance containing your custom assertions
241241
and specify that in assertion map instead.
242242

243+
So you can create a factory for your assertion set like this for example:
244+
245+
```php
246+
247+
use Interop\Container\ContainerInterface;
248+
use Zend\ServiceManager\FactoryInterface;
249+
use Zend\ServiceManager\ServiceLocatorInterface;
250+
use ZfcRbac\Assertion\AssertionSet;
251+
252+
class MyAssertionSetFactory implements FactoryInterface
253+
{
254+
/**
255+
* {@inheritDoc}
256+
*
257+
* @return AssertionSet
258+
*/
259+
public function __invoke(ContainerInterface $container, $name, array $options = null)
260+
{
261+
$assertionManager = $container->get('ZfcRbac\Assertion\AssertionPluginManager');
262+
$assertion1 = $assertionManager->get('myAssertion1');
263+
$assertion2 = $assertionManager->get('myAssertion2');
264+
265+
// create instance, set condition and add assertions
266+
$assertionSet = new AssertionSet([
267+
'assertions' => [$assertion1, $assertion2],
268+
'condition' => AssertionSet::CONDITION_OR
269+
]);
270+
return $assertionSet;
271+
}
272+
273+
/**
274+
* {@inheritDoc}
275+
*
276+
* For use with zend-servicemanager v2; proxies to __invoke().
277+
*
278+
* @param ServiceLocatorInterface $container
279+
* @return \ZfcRbac\Assertion\AssertionSet
280+
*/
281+
public function createService(ServiceLocatorInterface $container)
282+
{
283+
// Retrieve the parent container when under zend-servicemanager v2
284+
if (method_exists($container, 'getServiceLocator')) {
285+
$container = $container->getServiceLocator() ?: $container;
286+
}
287+
288+
return $this($container, AssertionSet::class);
289+
}
290+
}
291+
292+
```
293+
294+
And then add it to assertion manager and assertion map config:
295+
243296
```php
244297
return [
245298
'zfc_rbac' => [

src/ZfcRbac/Assertion/AssertionSet.php

Lines changed: 14 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
* @author David Havl
2727
* @licence MIT
2828
*/
29-
30-
class AssertionSet implements AssertionInterface, \IteratorAggregate
29+
class AssertionSet implements AssertionInterface
3130
{
3231
/**
3332
* Condition constants
@@ -51,121 +50,29 @@ class AssertionSet implements AssertionInterface, \IteratorAggregate
5150
* @param array|AssertionInterface[] $assertions An array of assertions.
5251
*/
5352
public function __construct(array $assertions = array())
54-
{
55-
$this->setAssertions($assertions);
56-
}
57-
58-
/**
59-
* Set assertions.
60-
*
61-
* @param AssertionInterface[] $assertions The assertions to set
62-
*
63-
* @return $this
64-
*/
65-
public function setAssertions(array $assertions)
6653
{
6754
$this->assertions = [];
6855

6956
// if definition contains condition, set it.
7057
if (isset($assertions['condition'])) {
71-
if ($assertions['condition'] != self::CONDITION_AND && $assertions['condition'] != self::CONDITION_OR) {
58+
if ($assertions['condition'] != AssertionSet::CONDITION_AND
59+
&& $assertions['condition'] != AssertionSet::CONDITION_OR) {
7260
throw new InvalidArgumentException('Invalid assertion condition given.');
7361
}
74-
$this->setCondition($assertions['condition']);
62+
$this->condition = $assertions['condition'];
7563
}
76-
7764
// if there are multiple assertions under a key 'assertions', get them.
7865
if (isset($assertions['assertions']) && is_array($assertions['assertions'])) {
7966
$assertions = $assertions['assertions'];
8067
}
81-
8268
// set each assertion
8369
foreach ($assertions as $name => $assertion) {
84-
$this->setAssertion($assertion, is_int($name) ? null : $name);
85-
}
86-
return $this;
87-
}
88-
89-
/**
90-
* Set an assertion.
91-
*
92-
* @param string|AssertionInterface $assertion The assertion instance or it's name
93-
* @param string $name A name/alias
94-
* @return $this
95-
*/
96-
public function setAssertion(AssertionInterface $assertion, $name = null)
97-
{
98-
if (null !== $name) {
99-
$this->assertions[$name] = $assertion;
100-
} else {
101-
$this->assertions[] = $assertion;
102-
}
103-
}
104-
105-
/**
106-
* Returns true if the assertion if defined.
107-
*
108-
* @param string $name The assertion name
109-
*
110-
* @return bool true if the assertion is defined, false otherwise
111-
*/
112-
public function hasAssertion($name)
113-
{
114-
return isset($this->assertions[$name]);
115-
}
116-
117-
/**
118-
* Gets a assertion value.
119-
*
120-
* @param string $name The assertion name
121-
*
122-
* @return AssertionInterface The assertion instance
123-
*
124-
* @throws InvalidArgumentException if the assertion is not defined
125-
*/
126-
public function getAssertion($name)
127-
{
128-
if (!$this->hasAssertion($name)) {
129-
throw new InvalidArgumentException(sprintf('The assertion "%s" is not defined.', $name));
70+
if (is_int($name)) {
71+
$this->assertions[] = $assertion;
72+
} else {
73+
$this->assertions[$name] = $assertion;
74+
}
13075
}
131-
return $this->assertions[$name];
132-
}
133-
134-
/**
135-
* Gets all assertions.
136-
*
137-
* @return AssertionInterface[] The assertion instance
138-
*/
139-
public function getAssertions()
140-
{
141-
return $this->assertions;
142-
}
143-
144-
/**
145-
* @return string
146-
*/
147-
public function getCondition()
148-
{
149-
return $this->condition;
150-
}
151-
152-
/**
153-
* Set condition
154-
*
155-
* @param string $condition
156-
*/
157-
public function setCondition($condition)
158-
{
159-
$this->condition = $condition;
160-
}
161-
162-
/**
163-
* Retrieve an external iterator
164-
* @return \ArrayIterator
165-
*/
166-
public function getIterator()
167-
{
168-
return new \ArrayIterator($this->assertions);
16976
}
17077

17178
/**
@@ -177,6 +84,10 @@ public function getIterator()
17784
*/
17885
public function assert(AuthorizationService $authorizationService, $context = null)
17986
{
87+
if (empty($this->assertions)) {
88+
return true;
89+
}
90+
18091
if (AssertionSet::CONDITION_AND === $this->condition) {
18192
foreach ($this->assertions as $assertion) {
18293
if (!$assertion->assert($authorizationService, $context)) {
@@ -197,9 +108,6 @@ public function assert(AuthorizationService $authorizationService, $context = nu
197108
return false;
198109
}
199110

200-
throw new InvalidArgumentException(sprintf(
201-
'Condition must be either "AND" or "OR", %s given',
202-
is_object($this->condition) ? get_class($this->condition) : gettype($this->condition)
203-
));
111+
return false;
204112
}
205113
}

src/ZfcRbac/Service/AuthorizationService.php

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,31 +78,6 @@ public function __construct(Rbac $rbac, RoleService $roleService, AssertionPlugi
7878
*/
7979
public function setAssertion($permission, $assertion)
8080
{
81-
// if is name of the assertion, retrieve an actual instance from assertion plugin manager
82-
if (is_string($assertion)) {
83-
$assertion = $this->assertionPluginManager->get($assertion);
84-
} elseif (is_array($assertion)) { // else if multiple assertion definition, create assertion set.
85-
86-
// move assertion definition under a key 'assertions'.
87-
if (!isset($assertion['assertions'])) {
88-
$assertion['assertions'] = (array)$assertion;
89-
}
90-
91-
if (!is_array($assertion['assertions'])) {
92-
$assertion['assertions'] = (array)$assertion['assertions'];
93-
}
94-
95-
// retrieve an actual instance from assertion plugin manager if necessary
96-
foreach ($assertion['assertions'] as $key => $value) {
97-
if (is_string($value)) {
98-
$assertion['assertions'][$key] = $this->assertionPluginManager->get($value);
99-
}
100-
}
101-
102-
// create assertion set
103-
$assertion = new AssertionSet($assertion);
104-
}
105-
10681
$this->assertions[(string) $permission] = $assertion;
10782
}
10883

@@ -114,10 +89,7 @@ public function setAssertion($permission, $assertion)
11489
*/
11590
public function setAssertions(array $assertions)
11691
{
117-
$this->assertions = [];
118-
foreach ($assertions as $permissionName => $assertionData) {
119-
$this->setAssertion($permissionName, $assertionData);
120-
}
92+
$this->assertions = $assertions;
12193
}
12294

12395
/**
@@ -168,8 +140,8 @@ public function isGranted($permission, $context = null)
168140
}
169141

170142
/**
171-
* @param string|callable|AssertionInterface $assertion
172-
* @param mixed $context
143+
* @param string|callable|array|AssertionInterface $assertion
144+
* @param mixed $context
173145
* @return bool
174146
* @throws Exception\InvalidArgumentException If an invalid assertion is passed
175147
*/
@@ -179,6 +151,27 @@ protected function assert($assertion, $context = null)
179151
return $assertion($this, $context);
180152
} elseif ($assertion instanceof AssertionInterface) {
181153
return $assertion->assert($this, $context);
154+
} elseif (is_string($assertion)) { // retrieve an actual instance from assertion plugin manager
155+
$assertion = $this->assertionPluginManager->get($assertion);
156+
return $assertion->assert($this, $context);
157+
} elseif (is_array($assertion)) { // else if multiple assertion definition, create assertion set.
158+
// move assertion definition under a key 'assertions'.
159+
if (!isset($assertion['assertions'])) {
160+
$assertion['assertions'] = (array)$assertion;
161+
}
162+
// convert to an array
163+
if (!is_array($assertion['assertions'])) {
164+
$assertion['assertions'] = (array)$assertion['assertions'];
165+
}
166+
// retrieve an actual instance from assertion plugin manager if necessary
167+
foreach ($assertion['assertions'] as $key => $value) {
168+
if (is_string($value)) {
169+
$assertion['assertions'][$key] = $this->assertionPluginManager->get($value);
170+
}
171+
}
172+
// create assertion set
173+
$assertion = new AssertionSet($assertion);
174+
return $assertion->assert($this, $context);
182175
}
183176

184177
throw new Exception\InvalidArgumentException(sprintf(

0 commit comments

Comments
 (0)