Failed Conditions
Pull Request — master (#243)
by Rafael
04:38
created

Manager::isRole()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
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;
8
use Phalcon\Db\AdapterInterface as DbAdapter;
9
use Phalcon\Acl\Exception;
10
use Phalcon\Acl\Resource;
11
use Phalcon\Acl;
12
use Phalcon\Acl\Role;
13
use Phalcon\Acl\RoleInterface;
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
0 ignored issues
show
Documentation introduced by
Should the return type not be Apps?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Should the return type not be Companies?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
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;
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
0 ignored issues
show
Documentation introduced by
Should the type for parameter $accessInherits not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
167
     * @return boolean
168
     * @throws \Phalcon\Acl\Exception
169
     */
170
    public function addRole($role, $scope = 0, $accessInherits = null) : bool
0 ignored issues
show
Coding Style introduced by
function addRole() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
171
    {
172
        if (is_string($role)) {
173
            $role = $this->setAppByRole($role);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $role. This often makes code more readable.
Loading history...
174
175
            $role = new Role($role, ucwords($role) . ' Role');
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $role. This often makes code more readable.
Loading history...
176
        }
177
178
        if (!$role instanceof RoleInterface) {
0 ignored issues
show
Bug introduced by
The class Phalcon\Acl\RoleInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
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
            $rolesDB->saveOrFail();
190
191
            $accessListDB = new AccessListDB();
192
            $accessListDB->roles_name = $role->getName();
193
            $accessListDB->roles_id = $rolesDB->getId();
194
            $accessListDB->resources_name = '*';
195
            $accessListDB->access_name = '*';
196
            $accessListDB->allowed = $this->_defaultAccess;
197
            $accessListDB->apps_id = $this->getApp()->getId();
198
            $accessListDB->saveOrFail();
199
        }
200
201
        if ($accessInherits) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $accessInherits of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
202
            return $this->addInherit($role->getName(), $accessInherits);
203
        }
204
205
        return true;
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     *
211
     * @param  string  $roleName
212
     * @return boolean
213
     */
214
    public function isRole($roleName) : bool
215
    {
216
        return RolesDB::isRole($roleName);
217
    }
218
219
    /**
220
     * {@inheritdoc}
221
     *
222
     * @param  string  $resourceName
223
     * @return boolean
224
     */
225
    public function isResource($resourceName) : bool
226
    {
227
        return ResourcesDB::isResource($resourceName);
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     *
233
     * @param  string $roleName
234
     * @param  string $roleToInherit
235
     * @throws \Phalcon\Acl\Exception
236
     */
237
    public function addInherit($roleName, $roleToInherit) : bool
0 ignored issues
show
Coding Style introduced by
function addInherit() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
238
    {
239
        return RolesDB::addInherit($roleName, $roleToInherit);
240
    }
241
242
    /**
243
     * Given a resource with a dot CRM.Leads , it will set the app.
244
     *
245
     * @param string $resource
246
     * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
247
     */
248
    protected function setAppByResource(string $resource) : string
249
    {
250
        //echeck if we have a dot , taht means we are sending the specific app to use
251
        if (strpos($resource, '.') !== false) {
252
            $appResource = explode('.', $resource);
253
            $resource = $appResource[1];
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $resource. This often makes code more readable.
Loading history...
254
            $appName = $appResource[0];
255
256
            //look for the app and set it
257
            if ($app = Apps::getACLApp($appName)) {
258
                $this->setApp($app);
259
            }
260
        }
261
262
        return $resource;
263
    }
264
265
    /**
266
     * Given a resource with a dot CRM.Leads , it will set the app.
267
     *
268
     * @param string $resource
0 ignored issues
show
Bug introduced by
There is no parameter named $resource. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
269
     * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
270
     */
271
    protected function setAppByRole(string $role) : string
272
    {
273
        //echeck if we have a dot , taht means we are sending the specific app to use
274
        if (strpos($role, '.') !== false) {
275
            $appRole = explode('.', $role);
276
            $role = $appRole[1];
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $role. This often makes code more readable.
Loading history...
277
            $appName = $appRole[0];
278
279
            //look for the app and set it
280
            if ($app = Apps::getACLApp($appName)) {
281
                $this->setApp($app);
282
            }
283
        }
284
285
        return $role;
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     * Example:
291
     * <code>
292
     * //Add a resource to the the list allowing access to an action
293
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), 'search');
294
     * $acl->addResource('customers', 'search');
295
     * //Add a resource  with an access list
296
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), ['create', 'search']);
297
     * $acl->addResource('customers', ['create', 'search']);
298
     * $acl->addResource('App.customers', ['create', 'search']);
299
     * </code>.
300
     *
301
     * @param  \Phalcon\Acl\Resource|string $resource
302
     * @param  array|string                 $accessList
0 ignored issues
show
Documentation introduced by
Should the type for parameter $accessList not be array|string|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
303
     * @return boolean
304
     */
305
    public function addResource($resource, $accessList = null) : bool
0 ignored issues
show
Coding Style introduced by
function addResource() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
306
    {
307
        if (!is_object($resource)) {
308
            //echeck if we have a dot , taht means we are sending the specific app to use
309
            $resource = $this->setAppByResource($resource);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $resource. This often makes code more readable.
Loading history...
310
311
            $resource = new Resource($resource);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $resource. This often makes code more readable.
Loading history...
312
        }
313
314
        if (!ResourcesDB::isResource($resource->getName())) {
315
            $resourceDB = new ResourcesDB();
316
            $resourceDB->name = $resource->getName();
317
            $resourceDB->description = $resource->getDescription();
318
            $resourceDB->apps_id = $this->getApp()->getId();
319
            $resourceDB->saveOrFail();
320
        }
321
322
        if ($accessList) {
323
            return $this->addResourceAccess($resource->getName(), $accessList);
324
        }
325
326
        return true;
327
    }
328
329
    /**
330
     * {@inheritdoc}
331
     *
332
     * @param  string       $resourceName
333
     * @param  array|string $accessList
334
     * @return boolean
335
     * @throws \Phalcon\Acl\Exception
336
     */
337
    public function addResourceAccess($resourceName, $accessList) : bool
0 ignored issues
show
Coding Style introduced by
function addResourceAccess() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
338
    {
339
        if (!ResourcesDB::isResource($resourceName)) {
340
            throw new Exception("Resource '{$resourceName}' does not exist in ACL");
341
        }
342
343
        $resource = ResourcesDB::getByName($resourceName);
344
345
        if (!is_array($accessList)) {
346
            $accessList = [$accessList];
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $accessList. This often makes code more readable.
Loading history...
347
        }
348
349
        foreach ($accessList as $accessName) {
350
            if (!ResourcesAccesses::exist($resource, $accessName)) {
351
                $resourceAccesses = new ResourcesAccesses();
352
                $resourceAccesses->beforeCreate(); //wtf?
353
                $resourceAccesses->resources_name = $resourceName;
354
                $resourceAccesses->access_name = $accessName;
355
                $resourceAccesses->apps_id = $this->getApp()->getId();
356
                $resourceAccesses->resources_id = $resource->getId();
357
                $resourceAccesses->saveOrFail();
358
            }
359
        }
360
        return true;
361
    }
362
363
    /**
364
     * {@inheritdoc}
365
     *
366
     * @return \Phalcon\Acl\Resource[]
0 ignored issues
show
Documentation introduced by
Should the return type not be Acl\ResourceInterface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
367
     */
368
    public function getResources() : \Phalcon\Acl\ResourceInterface
369
    {
370
        $resources = [];
371
372
        foreach (ResourcesDB::find() as $row) {
373
            $resources[] = new Resource($row->name, $row->description);
374
        }
375
        return $resources;
376
    }
377
378
    /**
379
     * {@inheritdoc}
380
     *
381
     * @return RoleInterface[]
0 ignored issues
show
Documentation introduced by
Should the return type not be RoleInterface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
382
     */
383
    public function getRoles() : \Phalcon\Acl\RoleInterface
384
    {
385
        $roles = [];
386
387
        foreach (RolesDB::find() as $row) {
388
            $roles[] = new Role($row->name, $row->description);
389
        }
390
        return $roles;
391
    }
392
393
    /**
394
     * {@inheritdoc}
395
     *
396
     * @param string       $resourceName
397
     * @param array|string $accessList
398
     */
399
    public function dropResourceAccess($resourceName, $accessList)
400
    {
401
        throw new BadMethodCallException('Not implemented yet.');
402
    }
403
404
    /**
405
     * {@inheritdoc}
406
     * You can use '*' as wildcard
407
     * Example:
408
     * <code>
409
     * //Allow access to guests to search on customers
410
     * $acl->allow('guests', 'customers', 'search');
411
     * //Allow access to guests to search or create on customers
412
     * $acl->allow('guests', 'customers', ['search', 'create']);
413
     * //Allow access to any role to browse on products
414
     * $acl->allow('*', 'products', 'browse');
415
     * //Allow access to any role to browse on any resource
416
     * $acl->allow('*', '*', 'browse');
417
     * </code>.
418
     *
419
     * @param string       $roleName
420
     * @param string       $resourceName
421
     * @param array|string $access
422
     * @param mixed $func
423
     */
424
    public function allow($roleName, $resourceName, $access, $func = null)
0 ignored issues
show
Coding Style introduced by
function allow() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
425
    {
426
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::ALLOW);
427
    }
428
429
    /**
430
     * {@inheritdoc}
431
     * You can use '*' as wildcard
432
     * Example:
433
     * <code>
434
     * //Deny access to guests to search on customers
435
     * $acl->deny('guests', 'customers', 'search');
436
     * //Deny access to guests to search or create on customers
437
     * $acl->deny('guests', 'customers', ['search', 'create']);
438
     * //Deny access to any role to browse on products
439
     * $acl->deny('*', 'products', 'browse');
440
     * //Deny access to any role to browse on any resource
441
     * $acl->deny('*', '*', 'browse');
442
     * </code>.
443
     *
444
     * @param  string       $roleName
445
     * @param  string       $resourceName
446
     * @param  array|string $access
447
     * @param  mixed $func
448
     * @return boolean
449
     */
450
    public function deny($roleName, $resourceName, $access, $func = null)
0 ignored issues
show
Coding Style introduced by
function deny() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
451
    {
452
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::DENY);
453
    }
454
455
    /**
456
     * {@inheritdoc}
457
     * Example:
458
     * <code>
459
     * //Does Andres have access to the customers resource to create?
460
     * $acl->isAllowed('Andres', 'Products', 'create');
461
     * //Do guests have access to any resource to edit?
462
     * $acl->isAllowed('guests', '*', 'edit');
463
     * </code>.
464
     *
465
     * @param string $role
466
     * @param string $resource
467
     * @param string $access
468
     * @param array  $parameters
0 ignored issues
show
Documentation introduced by
Should the type for parameter $parameters not be null|array? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
469
     * @return bool
470
     */
471
    public function isAllowed($role, $resource, $access, array $parameters = null) : bool
472
    {
473
        $role = $this->setAppByRole($role);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $role. This often makes code more readable.
Loading history...
474
        //resoure always overwrites the role app?
475
        $resource = $this->setAppByResource($resource);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $resource. This often makes code more readable.
Loading history...
476
        $roleObj = RolesDB::getByName($role);
477
478
        $sql = implode(' ', [
479
            'SELECT ' . $this->connection->escapeIdentifier('allowed') . ' FROM access_list AS a',
480
            // role_name in:
481
            'WHERE roles_id IN (',
482
            // given 'role'-parameter
483
            'SELECT roles_id ',
484
            // inherited role_names
485
            'UNION SELECT roles_inherit FROM roles_inherits WHERE roles_id = ?',
486
            // or 'any'
487
            "UNION SELECT '*'",
488
            ')',
489
            // resources_name should be given one or 'any'
490
            "AND resources_name IN (?, '*')",
491
            // access_name should be given one or 'any'
492
            //"AND access_name IN (?, '*')", you need to specify * , we are forcing to check always for permisions
493
            'AND access_name IN (?)',
494
            'AND apps_id = ? ',
495
            'AND roles_id = ? ',
496
            // order be the sum of bools for 'literals' before 'any'
497
            'ORDER BY ' . $this->connection->escapeIdentifier('allowed') . ' DESC',
498
            // get only one...
499
            'LIMIT 1'
500
        ]);
501
502
        // fetch one entry...
503
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, [$roleObj->getId(), $resource, $access, $this->getApp()->getId(), $roleObj->getId()]);
504
505
        if (is_array($allowed)) {
506
            return (bool) $allowed[0];
507
        }
508
509
        /**
510
         * Return the default access action.
511
         */
512
        return (bool) $this->_defaultAccess;
513
    }
514
515
    /**
516
     * Returns the default ACL access level for no arguments provided
517
     * in isAllowed action if there exists func for accessKey.
518
     *
519
     * @return int
520
     */
521
    public function getNoArgumentsDefaultAction() : int
522
    {
523
        return $this->noArgumentsDefaultAction;
524
    }
525
526
    /**
527
     * Sets the default access level for no arguments provided
528
     * in isAllowed action if there exists func for accessKey.
529
     *
530
     * @param int $defaultAccess Phalcon\Acl::ALLOW or Phalcon\Acl::DENY
531
     */
532
    public function setNoArgumentsDefaultAction($defaultAccess)
533
    {
534
        $this->noArgumentsDefaultAction = intval($defaultAccess);
535
    }
536
537
    /**
538
     * Inserts/Updates a permission in the access list.
539
     *
540
     * @param  string  $roleName
541
     * @param  string  $resourceName
542
     * @param  string  $accessName
543
     * @param  integer $action
544
     * @return boolean
545
     * @throws \Phalcon\Acl\Exception
546
     */
547
    protected function insertOrUpdateAccess($roleName, $resourceName, $accessName, $action)
0 ignored issues
show
Coding Style introduced by
function insertOrUpdateAccess() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
548
    {
549
        $resourceName = $this->setAppByResource($resourceName);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $resourceName. This often makes code more readable.
Loading history...
550
551
        /**
552
         * Check if the access is valid in the resource unless wildcard.
553
         */
554
        if ($resourceName !== '*' && $accessName !== '*') {
555
            $resource = ResourcesDB::getByName($resourceName);
556
557
            if (!ResourcesAccesses::exist($resource, $accessName)) {
558
                throw new Exception(
559
                    "Access '{$accessName}' does not exist in resource '{$resourceName}' ({$resource->getId()}) in ACL"
560
                );
561
            }
562
        }
563
564
        /**
565
         * Update the access in access_list.
566
         */
567
568
        $role = RolesDB::getByName($roleName);
569
570
        if (!AccessListDB::exist($role, $resourceName, $accessName)) {
571
            $accessListDB = new AccessListDB();
572
            $accessListDB->roles_id = $role->getId();
573
            $accessListDB->roles_name = $roleName;
574
            $accessListDB->resources_name = $resourceName;
575
            $accessListDB->access_name = $accessName;
576
            $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...
577
            $accessListDB->apps_id = $this->getApp()->getId();
578
            $accessListDB->saveOrFail();
579
        } else {
580
            $accessListDB = accessListDB::getBy($role, $resourceName, $accessName);
581
            $accessListDB->allowed = $action;
582
            $accessListDB->updateOrFail();
583
        }
584
585
        /**
586
         * Update the access '*' in access_list.
587
         */
588
        if (!AccessListDB::exist($role, $resourceName, '*')) {
589
            $accessListDB = new AccessListDB();
590
            $accessListDB->roles_id = $role->getId();
591
            $accessListDB->roles_name = $roleName;
592
            $accessListDB->resources_name = $resourceName;
593
            $accessListDB->access_name = '*';
594
            $accessListDB->allowed = $this->_defaultAccess;
595
            $accessListDB->apps_id = $this->getApp()->getId();
596
            $accessListDB->saveOrFail();
597
        }
598
599
        return true;
600
    }
601
602
    /**
603
     * Inserts/Updates a permission in the access list.
604
     *
605
     * @param  string       $roleName
606
     * @param  string       $resourceName
607
     * @param  array|string $access
608
     * @param  integer      $action
609
     * @throws \Phalcon\Acl\Exception
610
     */
611
    protected function allowOrDeny($roleName, $resourceName, $access, $action)
0 ignored issues
show
Coding Style introduced by
function allowOrDeny() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
612
    {
613
        if (!RolesDB::isRole($roleName)) {
614
            throw new Exception("Role '{$roleName}' does not exist in the list");
615
        }
616
        if (!is_array($access)) {
617
            $access = [$access];
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $access. This often makes code more readable.
Loading history...
618
        }
619
        foreach ($access as $accessName) {
620
            $this->insertOrUpdateAccess($roleName, $resourceName, $accessName, $action);
621
        }
622
623
        return true;
624
    }
625
}
626