Test Failed
Push — master ( 6c568c...84fb84 )
by Maximo
19:10 queued 11:12
created

Manager   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 606
Duplicated Lines 0 %

Test Coverage

Coverage 1.66%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 165
c 1
b 0
f 0
dl 0
loc 606
ccs 3
cts 181
cp 0.0166
rs 5.04
wmc 57

23 Methods

Rating   Name   Duplication   Size   Complexity  
A setAppByResource() 0 15 3
A isResource() 0 3 1
B addRole() 0 41 7
A setNoArgumentsDefaultAction() 0 3 1
A getResources() 0 8 2
A isAllowed() 0 42 2
A allowOrDeny() 0 13 4
A addResourceAccess() 0 27 6
A addInherit() 0 3 1
B insertOrUpdateAccess() 0 59 8
A getNoArgumentsDefaultAction() 0 3 1
A setAppByRole() 0 15 3
A setApp() 0 3 1
A getApp() 0 7 2
A __construct() 0 3 1
A getCompany() 0 9 2
A dropResourceAccess() 0 3 1
A setCompany() 0 3 1
A addResource() 0 25 5
A deny() 0 3 1
A allow() 0 3 1
A getRoles() 0 8 2
A isRole() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Manager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Manager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Canvas\Acl;
6
7
use Phalcon\Db;
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;
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;
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
            $this->company = new Companies();
148
            $this->company->id = 1;
149
            $this->company->name = 'Canvas';
150
        }
151
152
        return $this->company;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->company returns the type Canvas\Models\Companies which is incompatible with the documented return type void.
Loading history...
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     *
158
     * Example:
159
     * <code>
160
     * $acl->addRole(new Phalcon\Acl\Role('administrator'), 'consultor');
161
     * $acl->addRole('administrator', 'consultor');
162
     * </code>
163
     *
164
     * @param  \Phalcon\Acl\Role|string $role
165
     * @param  int   $scope
166
     * @param  string                   $accessInherits
167
     * @return boolean
168
     * @throws \Phalcon\Acl\Exception
169
     */
170
    public function addRole($role, $scope = 0, $accessInherits = null) : bool
171
    {
172
        if (is_string($role)) {
173
            $role = $this->setAppByRole($role);
174
175
            $role = new Role($role, ucwords($role) . ' Role');
176
        }
177
178
        if (!$role instanceof RoleInterface) {
179
            throw new Exception('Role must be either an string or implement RoleInterface');
180
        }
181
182
        if (!RolesDB::exist($role)) {
183
            $rolesDB = new RolesDB();
184
            $rolesDB->name = $role->getName();
185
            $rolesDB->description = $role->getDescription() ?? $role->getName();
186
            $rolesDB->companies_id = $this->getCompany()->getId();
187
            $rolesDB->apps_id = $this->getApp()->getId();
188
            $rolesDB->scope = $scope;
189
            if (!$rolesDB->save()) {
190
                throw new ModelException((string)current($rolesDB->getMessages()));
191
            }
192
193
            $accessListDB = new AccessListDB();
194
            $accessListDB->roles_name = $role->getName();
195
            $accessListDB->roles_id = $rolesDB->getId();
196
            $accessListDB->resources_name = '*';
197
            $accessListDB->access_name = '*';
198
            $accessListDB->allowed = $this->_defaultAccess;
199
            $accessListDB->apps_id = $this->getApp()->getId();
200
201
            if (!$accessListDB->save()) {
202
                throw new ModelException((string)current($rolesDB->getMessages()));
203
            }
204
        }
205
206
        if ($accessInherits) {
207
            return $this->addInherit($role->getName(), $accessInherits);
208
        }
209
210
        return true;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     *
216
     * @param  string  $roleName
217
     * @return boolean
218
     */
219
    public function isRole($roleName) : bool
220
    {
221
        return RolesDB::isRole($roleName);
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     *
227
     * @param  string  $resourceName
228
     * @return boolean
229
     */
230
    public function isResource($resourceName) : bool
231
    {
232
        return ResourcesDB::isResource($resourceName);
233
    }
234
235
    /**
236
     * {@inheritdoc}
237
     *
238
     * @param  string $roleName
239
     * @param  string $roleToInherit
240
     * @throws \Phalcon\Acl\Exception
241
     */
242
    public function addInherit($roleName, $roleToInherit) : bool
243
    {
244
        return RolesDB::addInherit($roleName, $roleToInherit);
245
    }
246
247
    /**
248
     * Given a resource with a dot CRM.Leads , it will set the app
249
     *
250
     * @param string $resource
251
     * @return void
252
     */
253
    protected function setAppByResource(string $resource) : string
254
    {
255
        //echeck if we have a dot , taht means we are sending the specific app to use
256
        if (strpos($resource, '.') !== false) {
257
            $appResource = explode('.', $resource);
258
            $resource = $appResource[1];
259
            $appName = $appResource[0];
260
261
            //look for the app and set it
262
            if ($app = Apps::getACLApp($appName)) {
263
                $this->setApp($app);
264
            }
265
        }
266
267
        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...
268
    }
269
270
    /**
271
     * Given a resource with a dot CRM.Leads , it will set the app
272
     *
273
     * @param string $resource
274
     * @return void
275
     */
276
    protected function setAppByRole(string $role) : string
277
    {
278
        //echeck if we have a dot , taht means we are sending the specific app to use
279
        if (strpos($role, '.') !== false) {
280
            $appRole = explode('.', $role);
281
            $role = $appRole[1];
282
            $appName = $appRole[0];
283
284
            //look for the app and set it
285
            if ($app = Apps::getACLApp($appName)) {
286
                $this->setApp($app);
287
            }
288
        }
289
290
        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...
291
    }
292
293
    /**
294
     * {@inheritdoc}
295
     * Example:
296
     * <code>
297
     * //Add a resource to the the list allowing access to an action
298
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), 'search');
299
     * $acl->addResource('customers', 'search');
300
     * //Add a resource  with an access list
301
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), ['create', 'search']);
302
     * $acl->addResource('customers', ['create', 'search']);
303
     * $acl->addResource('App.customers', ['create', 'search']);
304
     * </code>
305
     *
306
     * @param  \Phalcon\Acl\Resource|string $resource
307
     * @param  array|string                 $accessList
308
     * @return boolean
309
     */
310
    public function addResource($resource, $accessList = null) : bool
311
    {
312
        if (!is_object($resource)) {
313
            //echeck if we have a dot , taht means we are sending the specific app to use
314
            $resource = $this->setAppByResource($resource);
315
316
            $resource = new Resource($resource);
317
        }
318
319
        if (!ResourcesDB::isResource($resource->getName())) {
320
            $resourceDB = new ResourcesDB();
321
            $resourceDB->name = $resource->getName();
322
            $resourceDB->description = $resource->getDescription();
323
            $resourceDB->apps_id = $this->getApp()->getId();
324
325
            if (!$resourceDB->save()) {
326
                throw new ModelException((string)current($resourceDB->getMessages()));
327
            }
328
        }
329
330
        if ($accessList) {
331
            return $this->addResourceAccess($resource->getName(), $accessList);
332
        }
333
334
        return true;
335
    }
336
337
    /**
338
     * {@inheritdoc}
339
     *
340
     * @param  string       $resourceName
341
     * @param  array|string $accessList
342
     * @return boolean
343
     * @throws \Phalcon\Acl\Exception
344
     */
345
    public function addResourceAccess($resourceName, $accessList) : bool
346
    {
347
        if (!ResourcesDB::isResource($resourceName)) {
348
            throw new Exception("Resource '{$resourceName}' does not exist in ACL");
349
        }
350
351
        $resource = ResourcesDB::getByName($resourceName);
352
353
        if (!is_array($accessList)) {
354
            $accessList = [$accessList];
355
        }
356
357
        foreach ($accessList as $accessName) {
358
            if (!ResourcesAccesses::exist($resource, $accessName)) {
359
                $resourceAccesses = new ResourcesAccesses();
360
                $resourceAccesses->beforeCreate(); //wtf?
361
                $resourceAccesses->resources_name = $resourceName;
362
                $resourceAccesses->access_name = $accessName;
363
                $resourceAccesses->apps_id = $this->getApp()->getId();
364
                $resourceAccesses->resources_id = $resource->getId();
365
366
                if (!$resourceAccesses->save()) {
367
                    throw new ModelException((string)current($resourceAccesses->getMessages()));
368
                }
369
            }
370
        }
371
        return true;
372
    }
373
374
    /**
375
     * {@inheritdoc}
376
     *
377
     * @return \Phalcon\Acl\Resource[]
378
     */
379
    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...
380
    {
381
        $resources = [];
382
383
        foreach (ResourcesDB::find() as $row) {
384
            $resources[] = new Resource($row->name, $row->description);
385
        }
386
        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...
387
    }
388
389
    /**
390
     * {@inheritdoc}
391
     *
392
     * @return RoleInterface[]
393
     */
394
    public function getRoles() : \Phalcon\Acl\RoleInterface
395
    {
396
        $roles = [];
397
398
        foreach (RolesDB::find() as $row) {
399
            $roles[] = new Role($row->name, $row->description);
400
        }
401
        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...
402
    }
403
404
    /**
405
     * {@inheritdoc}
406
     *
407
     * @param string       $resourceName
408
     * @param array|string $accessList
409
     */
410
    public function dropResourceAccess($resourceName, $accessList)
411
    {
412
        throw new BadMethodCallException('Not implemented yet.');
413
    }
414
415
    /**
416
     * {@inheritdoc}
417
     * You can use '*' as wildcard
418
     * Example:
419
     * <code>
420
     * //Allow access to guests to search on customers
421
     * $acl->allow('guests', 'customers', 'search');
422
     * //Allow access to guests to search or create on customers
423
     * $acl->allow('guests', 'customers', ['search', 'create']);
424
     * //Allow access to any role to browse on products
425
     * $acl->allow('*', 'products', 'browse');
426
     * //Allow access to any role to browse on any resource
427
     * $acl->allow('*', '*', 'browse');
428
     * </code>
429
     *
430
     * @param string       $roleName
431
     * @param string       $resourceName
432
     * @param array|string $access
433
     * @param mixed $func
434
     */
435
    public function allow($roleName, $resourceName, $access, $func = null)
436
    {
437
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::ALLOW);
438
    }
439
440
    /**
441
     * {@inheritdoc}
442
     * You can use '*' as wildcard
443
     * Example:
444
     * <code>
445
     * //Deny access to guests to search on customers
446
     * $acl->deny('guests', 'customers', 'search');
447
     * //Deny access to guests to search or create on customers
448
     * $acl->deny('guests', 'customers', ['search', 'create']);
449
     * //Deny access to any role to browse on products
450
     * $acl->deny('*', 'products', 'browse');
451
     * //Deny access to any role to browse on any resource
452
     * $acl->deny('*', '*', 'browse');
453
     * </code>
454
     *
455
     * @param  string       $roleName
456
     * @param  string       $resourceName
457
     * @param  array|string $access
458
     * @param  mixed $func
459
     * @return boolean
460
     */
461
    public function deny($roleName, $resourceName, $access, $func = null)
462
    {
463
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::DENY);
464
    }
465
466
    /**
467
     * {@inheritdoc}
468
     * Example:
469
     * <code>
470
     * //Does Andres have access to the customers resource to create?
471
     * $acl->isAllowed('Andres', 'Products', 'create');
472
     * //Do guests have access to any resource to edit?
473
     * $acl->isAllowed('guests', '*', 'edit');
474
     * </code>
475
     *
476
     * @param string $role
477
     * @param string $resource
478
     * @param string $access
479
     * @param array  $parameters
480
     * @return bool
481
     */
482
    public function isAllowed($role, $resource, $access, array $parameters = null) : bool
483
    {
484
        $role = $this->setAppByRole($role);
485
        //resoure always overwrites the role app?
486
        $resource = $this->setAppByResource($resource);
487
        $roleObj = RolesDB::getByName($role);
488
489
        $sql = implode(' ', [
490
            'SELECT ' . $this->connection->escapeIdentifier('allowed') . ' FROM access_list AS a',
491
            // role_name in:
492
            'WHERE roles_id IN (',
493
                // given 'role'-parameter
494
            'SELECT roles_id ',
495
                // inherited role_names
496
            'UNION SELECT roles_inherit FROM roles_inherits WHERE roles_id = ?',
497
                // or 'any'
498
            "UNION SELECT '*'",
499
            ')',
500
            // resources_name should be given one or 'any'
501
            "AND resources_name IN (?, '*')",
502
            // access_name should be given one or 'any'
503
            //"AND access_name IN (?, '*')", you need to specify * , we are forcing to check always for permisions
504
            'AND access_name IN (?)',
505
            'AND apps_id = ? ',
506
            'AND roles_id = ? ',
507
            // order be the sum of bools for 'literals' before 'any'
508
            'ORDER BY ' . $this->connection->escapeIdentifier('allowed') . ' DESC',
509
            // get only one...
510
            'LIMIT 1'
511
        ]);
512
513
        // fetch one entry...
514
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, [$roleObj->getId(), $resource, $access, $this->getApp()->getId(), $roleObj->getId()]);
515
516
        if (is_array($allowed)) {
517
            return (bool) $allowed[0];
518
        }
519
520
        /**
521
         * Return the default access action
522
         */
523
        return (bool) $this->_defaultAccess;
524
    }
525
526
    /**
527
     * Returns the default ACL access level for no arguments provided
528
     * in isAllowed action if there exists func for accessKey
529
     *
530
     * @return int
531
     */
532
    public function getNoArgumentsDefaultAction() : int
533
    {
534
        return $this->noArgumentsDefaultAction;
535
    }
536
537
    /**
538
     * Sets the default access level for no arguments provided
539
     * in isAllowed action if there exists func for accessKey
540
     *
541
     * @param int $defaultAccess Phalcon\Acl::ALLOW or Phalcon\Acl::DENY
542
     */
543
    public function setNoArgumentsDefaultAction($defaultAccess)
544
    {
545
        $this->noArgumentsDefaultAction = intval($defaultAccess);
546
    }
547
548
    /**
549
     * Inserts/Updates a permission in the access list
550
     *
551
     * @param  string  $roleName
552
     * @param  string  $resourceName
553
     * @param  string  $accessName
554
     * @param  integer $action
555
     * @return boolean
556
     * @throws \Phalcon\Acl\Exception
557
     */
558
    protected function insertOrUpdateAccess($roleName, $resourceName, $accessName, $action)
559
    {
560
        $resourceName = $this->setAppByResource($resourceName);
561
562
        /**
563
         * Check if the access is valid in the resource unless wildcard
564
         */
565
        if ($resourceName !== '*' && $accessName !== '*') {
566
            $resource = ResourcesDB::getByName($resourceName);
567
568
            if (!ResourcesAccesses::exist($resource, $accessName)) {
569
                throw new Exception(
570
                    "Access '{$accessName}' does not exist in resource '{$resourceName}' ({$resource->getId()}) in ACL"
571
                );
572
            }
573
        }
574
575
        /**
576
         * Update the access in access_list
577
         */
578
579
        $role = RolesDB::getByName($roleName);
580
581
        if (!AccessListDB::exist($role, $resourceName, $accessName)) {
582
            $accessListDB = new AccessListDB();
583
            $accessListDB->roles_id = $role->getId();
584
            $accessListDB->roles_name = $roleName;
585
            $accessListDB->resources_name = $resourceName;
586
            $accessListDB->access_name = $accessName;
587
            $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...
588
            $accessListDB->apps_id = $this->getApp()->getId();
589
590
            if (!$accessListDB->save()) {
591
                throw new ModelException((string)current($accessListDB->getMessages()));
592
            }
593
        } else {
594
            $accessListDB = accessListDB::getBy($role, $resourceName, $accessName);
595
            $accessListDB->allowed = $action;
596
            $accessListDB->update();
597
        }
598
599
        /**
600
         * Update the access '*' in access_list
601
         */
602
        if (!AccessListDB::exist($role, $resourceName, '*')) {
603
            $accessListDB = new AccessListDB();
604
            $accessListDB->roles_id = $role->getId();
605
            $accessListDB->roles_name = $roleName;
606
            $accessListDB->resources_name = $resourceName;
607
            $accessListDB->access_name = '*';
608
            $accessListDB->allowed = $this->_defaultAccess;
609
            $accessListDB->apps_id = $this->getApp()->getId();
610
611
            if (!$accessListDB->save()) {
612
                throw new ModelException((string)current($accessListDB->getMessages()));
613
            }
614
        }
615
616
        return true;
617
    }
618
619
    /**
620
     * Inserts/Updates a permission in the access list
621
     *
622
     * @param  string       $roleName
623
     * @param  string       $resourceName
624
     * @param  array|string $access
625
     * @param  integer      $action
626
     * @throws \Phalcon\Acl\Exception
627
     */
628
    protected function allowOrDeny($roleName, $resourceName, $access, $action)
629
    {
630
        if (!RolesDB::isRole($roleName)) {
631
            throw new Exception("Role '{$roleName}' does not exist in the list");
632
        }
633
        if (!is_array($access)) {
634
            $access = [$access];
635
        }
636
        foreach ($access as $accessName) {
637
            $this->insertOrUpdateAccess($roleName, $resourceName, $accessName, $action);
638
        }
639
640
        return true;
641
    }
642
}
643