Manager::setNoArgumentsDefaultAction()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Canvas\Acl;
6
7
use Phalcon\Db;
0 ignored issues
show
Bug introduced by
The type Phalcon\Db was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Phalcon\Db\AdapterInterface as DbAdapter;
0 ignored issues
show
Bug introduced by
The type Phalcon\Db\AdapterInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Phalcon\Acl\Exception;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Phalcon\Acl\Resource;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\Resource was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Phalcon\Acl;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Phalcon\Acl\Role;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\Role was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Phalcon\Acl\RoleInterface;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\RoleInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Canvas\Models\Companies;
15
use Canvas\Models\Apps;
16
use Canvas\Models\Roles as RolesDB;
17
use Canvas\Models\AccessList as AccessListDB;
18
use Canvas\Models\Resources as ResourcesDB;
19
use Phalcon\Acl\Adapter;
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\Adapter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use BadMethodCallException;
21
use Canvas\Exception\ModelException;
22
use Canvas\Models\ResourcesAccesses;
23
use Phalcon\Di;
24
25
/**
26
 * Class Manager.
27
 *
28
 * Manages Geweaer Multi tenant ACL lists in database
29
 *
30
 * @package Canvas\Acl
31
 *
32
 * @property Users $userData
33
 * @property Request $request
34
 */
35
class Manager extends Adapter
36
{
37
    /**
38
     * @var DbAdapter
39
     */
40
    protected $connection;
41
42
    /**
43
     * Roles table.
44
     * @var string
45
     */
46
    protected $roles;
47
48
    /**
49
     * Resources table.
50
     * @var string
51
     */
52
    protected $resources;
53
54
    /**
55
     * Resources Accesses table.
56
     * @var string
57
     */
58
    protected $resourcesAccesses;
59
60
    /**
61
     * Access List table.
62
     * @var string
63
     */
64
    protected $accessList;
65
66
    /**
67
     * Roles Inherits table.
68
     * @var string
69
     */
70
    protected $rolesInherits;
71
72
    /**
73
     * Default action for no arguments is allow.
74
     * @var int
75
     */
76
    protected $noArgumentsDefaultAction = Acl::ALLOW;
77
78
    /**
79
     * Company Object.
80
     *
81
     * @var Companies
82
     */
83
    protected $company;
84
85
    /**
86
     * App Objc.
87
     *
88
     * @var Apps
89
     */
90
    protected $app;
91
92
    /**
93
     * Class constructor.
94
     *
95
     * @param  array $options Adapter config
96
     * @throws Exception
97
     */
98 1
    public function __construct(array $options)
99
    {
100 1
        $this->connection = $options['db'];
101 1
    }
102
103
    /**
104
     * Set current user Company.
105
     *
106
     * @param Companies $company
107
     * @return void
108
     */
109
    public function setCompany(Companies $company) : void
110
    {
111
        $this->company = $company;
112
    }
113
114
    /**
115
     * Set current user app.
116
     *
117
     * @param Apps $app
118
     * @return void
119
     */
120
    public function setApp(Apps $app) : void
121
    {
122
        $this->app = $app;
123
    }
124
125
    /**
126
     * Get the current App.
127
     *
128
     * @return void
129
     */
130
    public function getApp() : Apps
131
    {
132
        if (!is_object($this->app)) {
133
            $this->app = Di::getDefault()->getApp();
134
        }
135
136
        return $this->app;
137
    }
138
139
    /**
140
     * Get the current App.
141
     *
142
     * @return void
143
     */
144
    public function getCompany() : Companies
145
    {
146
        if (!is_object($this->company)) {
147
            if (!Di::getDefault()->has('userData')) {
148
                $this->company = new Companies();
149
                $this->company->id = 1;
150
                $this->company->name = 'Canvas';
151
            } else {
152
                $this->company = Di::getDefault()->get('userData')->getDefaultCompany();
153
            }
154
        }
155
156
        return $this->company;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     *
162
     * Example:
163
     * <code>
164
     * $acl->addRole(new Phalcon\Acl\Role('administrator'), 'consultor');
165
     * $acl->addRole('administrator', 'consultor');
166
     * </code>
167
     *
168
     * @param  \Phalcon\Acl\Role|string $role
169
     * @param  int   $scope
170
     * @param  string                   $accessInherits
171
     * @return boolean
172
     * @throws \Phalcon\Acl\Exception
173
     */
174
    public function addRole($role, $scope = 0, $accessInherits = null) : bool
175
    {
176
        if (is_string($role)) {
177
            $role = $this->setAppByRole($role);
178
179
            $role = new Role($role, ucwords($role) . ' Role');
180
        }
181
182
        if (!$role instanceof RoleInterface) {
183
            throw new Exception('Role must be either an string or implement RoleInterface');
184
        }
185
186
        if (!RolesDB::exist($role)) {
187
            $rolesDB = new RolesDB();
188
            $rolesDB->name = $role->getName();
189
            $rolesDB->description = $role->getDescription() ?? $role->getName();
190
            $rolesDB->companies_id = $this->getCompany()->getId();
191
            $rolesDB->apps_id = $this->getApp()->getId();
192
            $rolesDB->scope = $scope;
193
            $rolesDB->saveOrFail();
194
195
            $accessListDB = new AccessListDB();
196
            $accessListDB->roles_name = $role->getName();
197
            $accessListDB->roles_id = $rolesDB->getId();
198
            $accessListDB->resources_name = '*';
199
            $accessListDB->access_name = '*';
200
            $accessListDB->allowed = $this->_defaultAccess;
201
            $accessListDB->apps_id = $this->getApp()->getId();
202
            $accessListDB->saveOrFail();
203
        }
204
205
        if ($accessInherits) {
206
            return $this->addInherit($role->getName(), $accessInherits);
207
        }
208
209
        return true;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     *
215
     * @param  string  $roleName
216
     * @return boolean
217
     */
218
    public function isRole($roleName) : bool
219
    {
220
        return RolesDB::isRole($roleName);
221
    }
222
223
    /**
224
     * {@inheritdoc}
225
     *
226
     * @param  string  $resourceName
227
     * @return boolean
228
     */
229
    public function isResource($resourceName) : bool
230
    {
231
        return ResourcesDB::isResource($resourceName);
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     *
237
     * @param  string $roleName
238
     * @param  string $roleToInherit
239
     * @throws \Phalcon\Acl\Exception
240
     */
241
    public function addInherit($roleName, $roleToInherit) : bool
242
    {
243
        return RolesDB::addInherit($roleName, $roleToInherit);
244
    }
245
246
    /**
247
     * Given a resource with a dot CRM.Leads , it will set the app.
248
     *
249
     * @param string $resource
250
     * @return void
251
     */
252
    protected function setAppByResource(string $resource) : string
253
    {
254
        //echeck if we have a dot , taht means we are sending the specific app to use
255
        if (strpos($resource, '.') !== false) {
256
            $appResource = explode('.', $resource);
257
            $resource = $appResource[1];
258
            $appName = $appResource[0];
259
260
            //look for the app and set it
261
            if ($app = Apps::getACLApp($appName)) {
262
                $this->setApp($app);
263
            }
264
        }
265
266
        return $resource;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resource returns the type string which is incompatible with the documented return type void.
Loading history...
267
    }
268
269
    /**
270
     * Given a resource with a dot CRM.Leads , it will set the app.
271
     *
272
     * @param string $resource
273
     * @return void
274
     */
275
    protected function setAppByRole(string $role) : string
276
    {
277
        //echeck if we have a dot , taht means we are sending the specific app to use
278
        if (strpos($role, '.') !== false) {
279
            $appRole = explode('.', $role);
280
            $role = $appRole[1];
281
            $appName = $appRole[0];
282
283
            //look for the app and set it
284
            if ($app = Apps::getACLApp($appName)) {
285
                $this->setApp($app);
286
            }
287
        }
288
289
        return $role;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $role returns the type string which is incompatible with the documented return type void.
Loading history...
290
    }
291
292
    /**
293
     * {@inheritdoc}
294
     * Example:
295
     * <code>
296
     * //Add a resource to the the list allowing access to an action
297
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), 'search');
298
     * $acl->addResource('customers', 'search');
299
     * //Add a resource  with an access list
300
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), ['create', 'search']);
301
     * $acl->addResource('customers', ['create', 'search']);
302
     * $acl->addResource('App.customers', ['create', 'search']);
303
     * </code>.
304
     *
305
     * @param  \Phalcon\Acl\Resource|string $resource
306
     * @param  array|string                 $accessList
307
     * @return boolean
308
     */
309
    public function addResource($resource, $accessList = null) : bool
310
    {
311
        if (!is_object($resource)) {
312
            //echeck if we have a dot , taht means we are sending the specific app to use
313
            $resource = $this->setAppByResource($resource);
314
315
            $resource = new Resource($resource);
316
        }
317
318
        if (!ResourcesDB::isResource($resource->getName())) {
319
            $resourceDB = new ResourcesDB();
320
            $resourceDB->name = $resource->getName();
321
            $resourceDB->description = $resource->getDescription();
322
            $resourceDB->apps_id = $this->getApp()->getId();
323
            $resourceDB->saveOrFail();
324
        }
325
326
        if ($accessList) {
327
            return $this->addResourceAccess($resource->getName(), $accessList);
328
        }
329
330
        return true;
331
    }
332
333
    /**
334
     * {@inheritdoc}
335
     *
336
     * @param  string       $resourceName
337
     * @param  array|string $accessList
338
     * @return boolean
339
     * @throws \Phalcon\Acl\Exception
340
     */
341
    public function addResourceAccess($resourceName, $accessList) : bool
342
    {
343
        if (!ResourcesDB::isResource($resourceName)) {
344
            throw new Exception("Resource '{$resourceName}' does not exist in ACL");
345
        }
346
347
        $resource = ResourcesDB::getByName($resourceName);
348
349
        if (!is_array($accessList)) {
350
            $accessList = [$accessList];
351
        }
352
353
        foreach ($accessList as $accessName) {
354
            if (!ResourcesAccesses::exist($resource, $accessName)) {
355
                $resourceAccesses = new ResourcesAccesses();
356
                $resourceAccesses->beforeCreate(); //wtf?
357
                $resourceAccesses->resources_name = $resourceName;
358
                $resourceAccesses->access_name = $accessName;
359
                $resourceAccesses->apps_id = $this->getApp()->getId();
360
                $resourceAccesses->resources_id = $resource->getId();
361
                $resourceAccesses->saveOrFail();
362
            }
363
        }
364
        return true;
365
    }
366
367
    /**
368
     * {@inheritdoc}
369
     *
370
     * @return \Phalcon\Acl\Resource[]
371
     */
372
    public function getResources() : \Phalcon\Acl\ResourceInterface
0 ignored issues
show
Bug introduced by
The type Phalcon\Acl\ResourceInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
373
    {
374
        $resources = [];
375
376
        foreach (ResourcesDB::find() as $row) {
377
            $resources[] = new Resource($row->name, $row->description);
378
        }
379
        return $resources;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resources returns the type Phalcon\Acl\Resource[]|array which is incompatible with the type-hinted return Phalcon\Acl\ResourceInterface.
Loading history...
380
    }
381
382
    /**
383
     * {@inheritdoc}
384
     *
385
     * @return RoleInterface[]
386
     */
387
    public function getRoles() : \Phalcon\Acl\RoleInterface
388
    {
389
        $roles = [];
390
391
        foreach (RolesDB::find() as $row) {
392
            $roles[] = new Role($row->name, $row->description);
393
        }
394
        return $roles;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $roles returns the type Phalcon\Acl\Role[]|array which is incompatible with the type-hinted return Phalcon\Acl\RoleInterface.
Loading history...
395
    }
396
397
    /**
398
     * {@inheritdoc}
399
     *
400
     * @param string       $resourceName
401
     * @param array|string $accessList
402
     */
403
    public function dropResourceAccess($resourceName, $accessList)
404
    {
405
        throw new BadMethodCallException('Not implemented yet.');
406
    }
407
408
    /**
409
     * {@inheritdoc}
410
     * You can use '*' as wildcard
411
     * Example:
412
     * <code>
413
     * //Allow access to guests to search on customers
414
     * $acl->allow('guests', 'customers', 'search');
415
     * //Allow access to guests to search or create on customers
416
     * $acl->allow('guests', 'customers', ['search', 'create']);
417
     * //Allow access to any role to browse on products
418
     * $acl->allow('*', 'products', 'browse');
419
     * //Allow access to any role to browse on any resource
420
     * $acl->allow('*', '*', 'browse');
421
     * </code>.
422
     *
423
     * @param string       $roleName
424
     * @param string       $resourceName
425
     * @param array|string $access
426
     * @param mixed $func
427
     */
428
    public function allow($roleName, $resourceName, $access, $func = null)
429
    {
430
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::ALLOW);
431
    }
432
433
    /**
434
     * {@inheritdoc}
435
     * You can use '*' as wildcard
436
     * Example:
437
     * <code>
438
     * //Deny access to guests to search on customers
439
     * $acl->deny('guests', 'customers', 'search');
440
     * //Deny access to guests to search or create on customers
441
     * $acl->deny('guests', 'customers', ['search', 'create']);
442
     * //Deny access to any role to browse on products
443
     * $acl->deny('*', 'products', 'browse');
444
     * //Deny access to any role to browse on any resource
445
     * $acl->deny('*', '*', 'browse');
446
     * </code>.
447
     *
448
     * @param  string       $roleName
449
     * @param  string       $resourceName
450
     * @param  array|string $access
451
     * @param  mixed $func
452
     * @return boolean
453
     */
454
    public function deny($roleName, $resourceName, $access, $func = null)
455
    {
456
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::DENY);
457
    }
458
459
    /**
460
     * {@inheritdoc}
461
     * Example:
462
     * <code>
463
     * //Does Andres have access to the customers resource to create?
464
     * $acl->isAllowed('Andres', 'Products', 'create');
465
     * //Do guests have access to any resource to edit?
466
     * $acl->isAllowed('guests', '*', 'edit');
467
     * </code>.
468
     *
469
     * @param string $role
470
     * @param string $resource
471
     * @param string $access
472
     * @param array  $parameters
473
     * @return bool
474
     */
475
    public function isAllowed($role, $resource, $access, array $parameters = null) : bool
476
    {
477
        $role = $this->setAppByRole($role);
478
        //resoure always overwrites the role app?
479
        $resource = $this->setAppByResource($resource);
480
        $roleObj = RolesDB::getByName($role);
481
482
        $sql = implode(' ', [
483
            'SELECT ' . $this->connection->escapeIdentifier('allowed') . ' FROM access_list AS a',
484
            // role_name in:
485
            'WHERE roles_id IN (',
486
            // given 'role'-parameter
487
            'SELECT roles_id ',
488
            // inherited role_names
489
            'UNION SELECT roles_inherit FROM roles_inherits WHERE roles_id = ?',
490
            // or 'any'
491
            "UNION SELECT '*'",
492
            ')',
493
            // resources_name should be given one or 'any'
494
            "AND resources_name IN (?, '*')",
495
            // access_name should be given one or 'any'
496
            //"AND access_name IN (?, '*')", you need to specify * , we are forcing to check always for permisions
497
            'AND access_name IN (?)',
498
            'AND apps_id = ? ',
499
            'AND roles_id = ? ',
500
            // order be the sum of bools for 'literals' before 'any'
501
            'ORDER BY ' . $this->connection->escapeIdentifier('allowed') . ' DESC',
502
            // get only one...
503
            'LIMIT 1'
504
        ]);
505
506
        // fetch one entry...
507
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, [$roleObj->getId(), $resource, $access, $this->getApp()->getId(), $roleObj->getId()]);
508
509
        if (is_array($allowed)) {
510
            return (bool) $allowed[0];
511
        }
512
513
        /**
514
         * Return the default access action.
515
         */
516
        return (bool) $this->_defaultAccess;
517
    }
518
519
    /**
520
     * Returns the default ACL access level for no arguments provided
521
     * in isAllowed action if there exists func for accessKey.
522
     *
523
     * @return int
524
     */
525
    public function getNoArgumentsDefaultAction() : int
526
    {
527
        return $this->noArgumentsDefaultAction;
528
    }
529
530
    /**
531
     * Sets the default access level for no arguments provided
532
     * in isAllowed action if there exists func for accessKey.
533
     *
534
     * @param int $defaultAccess Phalcon\Acl::ALLOW or Phalcon\Acl::DENY
535
     */
536
    public function setNoArgumentsDefaultAction($defaultAccess)
537
    {
538
        $this->noArgumentsDefaultAction = intval($defaultAccess);
539
    }
540
541
    /**
542
     * Inserts/Updates a permission in the access list.
543
     *
544
     * @param  string  $roleName
545
     * @param  string  $resourceName
546
     * @param  string  $accessName
547
     * @param  integer $action
548
     * @return boolean
549
     * @throws \Phalcon\Acl\Exception
550
     */
551
    protected function insertOrUpdateAccess($roleName, $resourceName, $accessName, $action)
552
    {
553
        $resourceName = $this->setAppByResource($resourceName);
554
555
        /**
556
         * Check if the access is valid in the resource unless wildcard.
557
         */
558
        if ($resourceName !== '*' && $accessName !== '*') {
559
            $resource = ResourcesDB::getByName($resourceName);
560
561
            if (!ResourcesAccesses::exist($resource, $accessName)) {
562
                throw new Exception(
563
                    "Access '{$accessName}' does not exist in resource '{$resourceName}' ({$resource->getId()}) in ACL"
564
                );
565
            }
566
        }
567
568
        /**
569
         * Update the access in access_list.
570
         */
571
572
        $role = RolesDB::getByName($roleName);
573
574
        if (!AccessListDB::exist($role, $resourceName, $accessName)) {
575
            $accessListDB = new AccessListDB();
576
            $accessListDB->roles_id = $role->getId();
577
            $accessListDB->roles_name = $roleName;
578
            $accessListDB->resources_name = $resourceName;
579
            $accessListDB->access_name = $accessName;
580
            $accessListDB->allowed = $action;
0 ignored issues
show
Documentation Bug introduced by
The property $allowed was declared of type boolean, but $action is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
581
            $accessListDB->apps_id = $this->getApp()->getId();
582
            $accessListDB->saveOrFail();
583
        } else {
584
            $accessListDB = accessListDB::getBy($role, $resourceName, $accessName);
585
            $accessListDB->allowed = $action;
586
            $accessListDB->updateOrFail();
587
        }
588
589
        /**
590
         * Update the access '*' in access_list.
591
         */
592
        if (!AccessListDB::exist($role, $resourceName, '*')) {
593
            $accessListDB = new AccessListDB();
594
            $accessListDB->roles_id = $role->getId();
595
            $accessListDB->roles_name = $roleName;
596
            $accessListDB->resources_name = $resourceName;
597
            $accessListDB->access_name = '*';
598
            $accessListDB->allowed = $this->_defaultAccess;
599
            $accessListDB->apps_id = $this->getApp()->getId();
600
            $accessListDB->saveOrFail();
601
        }
602
603
        return true;
604
    }
605
606
    /**
607
     * Inserts/Updates a permission in the access list.
608
     *
609
     * @param  string       $roleName
610
     * @param  string       $resourceName
611
     * @param  array|string $access
612
     * @param  integer      $action
613
     * @throws \Phalcon\Acl\Exception
614
     */
615
    protected function allowOrDeny($roleName, $resourceName, $access, $action)
616
    {
617
        if (!RolesDB::isRole($roleName)) {
618
            throw new Exception("Role '{$roleName}' does not exist in the list");
619
        }
620
        if (!is_array($access)) {
621
            $access = [$access];
622
        }
623
        foreach ($access as $accessName) {
624
            $this->insertOrUpdateAccess($roleName, $resourceName, $accessName, $action);
625
        }
626
627
        return true;
628
    }
629
}
630