Passed
Push — master ( 1f9581...d48de4 )
by Chauncey
02:35 queued 29s
created

AbstractAuthorizer::setAcl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Charcoal\User;
4
5
use InvalidArgumentException;
6
7
// From PSR-3
8
use Psr\Log\LoggerAwareInterface;
9
use Psr\Log\LoggerAwareTrait;
10
11
// From 'laminas/laminas-permissions-acl'
12
use Laminas\Permissions\Acl\Acl;
13
use Laminas\Permissions\Acl\Exception\ExceptionInterface as AclExceptionInterface;
14
use Laminas\Permissions\Acl\Resource\ResourceInterface as AclResourceInterface;
15
use Laminas\Permissions\Acl\Role\RoleInterface as AclRoleInterface;
16
17
// From 'charcoal-user'
18
use Charcoal\User\UserInterface;
19
20
/**
21
 * The base Authorizer service
22
 *
23
 * The authorizer service helps with user authorization (permission checking).
24
 *
25
 * ## Constructor dependencies
26
 *
27
 * Constructor dependencies are passed as an array of `key => value` pair.
28
 * The required dependencies are:
29
 *
30
 * - `logger` A PSR3 logger instance.
31
 * - `acl` A Laminas ACL (Access-Control-List) instance.
32
 *
33
 * ## Checking permissions
34
 *
35
 * To check if a given ACL (passed in constructor) allows a list of permissions (aka privileges):
36
 *
37
 * - `xxx(UserInterface $user, string[] $aclPermissions)`
38
 */
39
abstract class AbstractAuthorizer implements
40
    AuthorizerInterface,
41
    LoggerAwareInterface
42
{
43
    use LoggerAwareTrait;
44
45
    /**
46
     * The ACL service.
47
     *
48
     * @var Acl
49
     */
50
    private $acl;
51
52
    /**
53
     * @param array $data Class dependencies.
54
     */
55
    public function __construct(array $data)
56
    {
57
        $this->setLogger($data['logger']);
58
        $this->setAcl($data['acl']);
59
    }
60
61
    /**
62
     * Check if access is granted to the role for all permissions.
63
     *
64
     * @param  AclRoleInterface|string          $role       One ACL role to check.
65
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
66
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
67
     * @return boolean|null Returns TRUE if and only if all the $privileges are granted against the $role.
68
     *     Returns NULL if no applicable role, resource, or permissions could be checked.
69
     */
70 View Code Duplication
    public function isRoleGrantedAll($role, $resource, $privileges)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
    {
72
        $privileges = (array)$privileges;
73
        $result     = null;
74
75
        try {
76
            foreach ($privileges as $privilege) {
77
                if (!$this->isAllowed($role, $resource, $privilege)) {
78
                    return false;
79
                }
80
81
                $result = true;
82
            }
83
84
            return $result;
85
        } catch (AclExceptionInterface $e) {
86
            $this->logger->error('[ACL] '.$e->getMessage());
87
        }
88
89
        return null;
90
    }
91
92
    /**
93
     * Check if access is granted to all roles for all permissions.
94
     *
95
     * @param  AclRoleInterface|string|array    $roles      One or many ACL roles to check.
96
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
97
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
98
     * @return boolean|null Returns TRUE if and only if all the $privileges are granted against all $roles.
99
     *     Returns NULL if no applicable roles, resource, or permissions could be checked.
100
     */
101 View Code Duplication
    public function allRolesGrantedAll($roles, $resource, $privileges)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102
    {
103
        $roles      = (array)$roles;
104
        $privileges = (array)$privileges;
105
        $result     = null;
106
107
        foreach ($roles as $role) {
108
            if (!$this->isRoleGrantedAll($role, $resource, $privileges)) {
109
                return false;
110
            }
111
112
            $result = true;
113
        }
114
115
        return $result;
116
    }
117
118
    /**
119
     * Check if access is granted to any one of the roles for all permissions.
120
     *
121
     * @param  AclRoleInterface|string|array    $roles      One or many ACL roles to check.
122
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
123
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
124
     * @return boolean|null Returns TRUE if and only if all the $privileges are granted against any one of the $roles.
125
     *     Returns NULL if no applicable roles, resource, or permissions could be checked.
126
     */
127
    public function anyRolesGrantedAll($roles, $resource, $privileges)
128
    {
129
        $roles      = (array)$roles;
130
        $privileges = (array)$privileges;
131
        $result     = null;
132
133
        foreach ($roles as $role) {
134
            if ($this->isRoleGrantedAll($role, $resource, $privileges)) {
135
                return true;
136
            }
137
138
            $result = false;
139
        }
140
141
        return $result;
142
    }
143
144
    /**
145
     * Check if access is granted to the role for any one of the permissions.
146
     *
147
     * @param  AclRoleInterface|string          $role       One ACL role to check.
148
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
149
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
150
     * @return boolean|null Returns TRUE if any one of the $privileges are granted against the $role.
151
     *     Returns NULL if no applicable role, resource, or permissions could be checked.
152
     */
153 View Code Duplication
    public function isRoleGrantedAny($role, $resource, $privileges)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155
        $privileges = (array)$privileges;
156
        $result     = null;
157
158
        try {
159
            foreach ($privileges as $privilege) {
160
                if ($this->isAllowed($role, $resource, $privilege)) {
161
                    return true;
162
                }
163
164
                $result = false;
165
            }
166
167
            return $result;
168
        } catch (AclExceptionInterface $e) {
169
            $this->logger->error('[ACL] '.$e->getMessage());
170
        }
171
172
        return null;
173
    }
174
175
    /**
176
     * Check if access is granted to all roles for any one of the permissions.
177
     *
178
     * @param  AclRoleInterface|string|array    $roles      One or many ACL roles to check.
179
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
180
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
181
     * @return boolean|null Returns TRUE if any one of the $privileges are granted against all $roles.
182
     *     Returns NULL if no applicable roles, resource, or permissions could be checked.
183
     */
184 View Code Duplication
    public function allRolesGrantedAny($roles, $resource, $privileges)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186
        $roles      = (array)$roles;
187
        $privileges = (array)$privileges;
188
        $result     = null;
189
190
        foreach ($roles as $role) {
191
            if (!$this->isRoleGrantedAny($role, $resource, $privileges)) {
192
                return false;
193
            }
194
195
            $result = true;
196
        }
197
198
        return $result;
199
    }
200
201
    /**
202
     * Check if access is granted to any one of the roles for any one of the permissions.
203
     *
204
     * @param  AclRoleInterface|string|array    $roles      One or many ACL roles to check.
205
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
206
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
207
     * @return boolean|null
208
     *     Returns TRUE if any one of the $privileges are granted against any one of the $roles.
209
     *     Returns NULL if no applicable roles, resource, or permissions could be checked.
210
     */
211
    public function anyRolesGrantedAny($roles, $resource, $privileges)
212
    {
213
        $roles      = (array)$roles;
214
        $privileges = (array)$privileges;
215
        $result     = null;
216
217
        foreach ($roles as $role) {
218
            if ($this->isRoleGrantedAny($role, $resource, $privileges)) {
219
                return true;
220
            }
221
222
            $result = false;
223
        }
224
225
        return $result;
226
    }
227
228
    /**
229
     * Check if access is granted to the user's role(s) for permissions.
230
     *
231
     * @param  UserInterface                    $user       The user to check.
232
     * @param  AclResourceInterface|string|null $resource   One ACL resource to check.
233
     * @param  string|string[]                  $privileges One or many ACL privileges to check.
234
     * @return boolean|null
235
     *     Returns TRUE if and only if the $privileges are granted against one of the roles of the $user.
236
     *     Returns NULL if no applicable roles, resource, or permissions could be checked.
237
     */
238
    public function isUserGranted(UserInterface $user, $resource, $privileges)
239
    {
240
        return $this->anyRolesGrantedAll($user['roles'], $resource, $privileges);
241
    }
242
243
244
245
    // Helpers from \Laminas\Permissions\Acl\Acl
246
    // =========================================================================
247
248
    /**
249
     * Check if the role has access to the resource and privilege.
250
     *
251
     * This method is a proxy to {@see \Laminas\Permissions\Acl\Acl::isAllowed()}.
252
     *
253
     * @param  AclRoleInterface|string     $role      The ACL role to check.
254
     *     If $role is NULL, then the ACL will check for a "blacklist" rule
255
     *     (allow everything to all).
256
     * @param  AclResourceInterface|string $resource  The ACL resource to check.
257
     *     If $resource is NULL, then the ACL will check for a "blacklist" rule
258
     *     (allow everything to all).
259
     * @param  string                      $privilege The ACL privilege to check.
260
     *     If $privilege is NULL, then the ACL returns TRUE if and only if
261
     *     the $role is allowed all privileges on the $resource.
262
     * @return boolean Returns TRUE if and only if the $role has access to the $resource.
263
     */
264
    public function isAllowed($role = null, $resource = null, $privilege = null)
265
    {
266
        return $this->getAcl()->isAllowed($role, $resource, $privilege);
267
    }
268
269
    /**
270
     * Determine if the role is registered.
271
     *
272
     * @see \Laminas\Permissions\Acl\Acl::hasRole()
273
     *
274
     * @param  RoleInterface|string $role The ACL role to check.
275
     * @return boolean Returns TRUE if and only if the $role exists in the registry.
276
     */
277
    public function hasRole($role)
278
    {
279
        return $this->getAcl()->hasRole($role);
280
    }
281
282
    /**
283
     * Determine if the role inherits from another role.
284
     *
285
     * @see \Laminas\Permissions\Acl\Acl::inheritsRole()
286
     *
287
     * @param  RoleInterface|string $role        The ACL role to check.
288
     * @param  RoleInterface|string $inherit     The ACL role to check $role against.
289
     * @param  boolean              $onlyParents Whether the $role must inherit directly from $inherit.
290
     * @return boolean Returns TRUE if and only if $role inherits from $inherit.
291
     */
292
    public function inheritsRole($role, $inherit, $onlyParents = false)
293
    {
294
        return $this->getAcl()->inheritsRole($role, $inherit, $onlyParents);
295
    }
296
297
    /**
298
     * Determine if the resource is registered.
299
     *
300
     * @see \Laminas\Permissions\Acl\Acl::hasResource()
301
     *
302
     * @param  AclResourceInterface|string $resource The ACL resource to check.
303
     * @return boolean Returns TRUE if and only if the $resource exists in the ACL.
304
     */
305
    public function hasResource($resource)
306
    {
307
        return $this->getAcl()->hasResource($resource);
308
    }
309
310
    /**
311
     * Determine if the resource inherits from another resource.
312
     *
313
     * @see \Laminas\Permissions\Acl\Acl::inheritsResource()
314
     *
315
     * @param  AclResourceInterface|string $resource   The ACL resource to check.
316
     * @param  AclResourceInterface|string $inherit    The ACL resource to check $resource against.
317
     * @param  boolean                     $onlyParent Whether the $resource must inherit directly from $inherit.
318
     * @return boolean Returns TRUE if and only if $resource inherits from $inherit.
319
     */
320
    public function inheritsResource($resource, $inherit, $onlyParent = false)
321
    {
322
        return $this->getAcl()->inheritsResource($resource, $inherit, $onlyParent);
323
    }
324
325
326
327
    // Dependencies
328
    // =========================================================================
329
330
    /**
331
     * @return Acl
332
     */
333
    protected function getAcl()
334
    {
335
        return $this->acl;
336
    }
337
338
    /**
339
     * @param  Acl $acl The ACL service.
340
     * @return void
341
     */
342
    private function setAcl(Acl $acl)
343
    {
344
        $this->acl = $acl;
345
    }
346
}
347