Test Failed
Pull Request — master (#18)
by Maximo
07:25
created

Manager   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 616
Duplicated Lines 0 %

Test Coverage

Coverage 65.28%

Importance

Changes 0
Metric Value
eloc 176
dl 0
loc 616
ccs 126
cts 193
cp 0.6528
rs 4.08
c 0
b 0
f 0
wmc 59

23 Methods

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

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 Gewaer\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 Gewaer\Models\Companies;
15
use Gewaer\Models\Apps;
16
use Phalcon\Acl\Adapter;
17
use BadMethodCallException;
18
19
/**
20
 * Class Manager
21
 *
22
 * Manages Geweaer Multi tenant ACL lists in database
23
 *
24
 * @package Gewaer\Acl
25
 *
26
 * @property Users $userData
27
 * @property Request $request
28
 */
29
class Manager extends Adapter
30
{
31
    /**
32
     * @var DbAdapter
33
     */
34
    protected $connection;
35
36
    /**
37
     * Roles table
38
     * @var string
39
     */
40
    protected $roles;
41
42
    /**
43
     * Resources table
44
     * @var string
45
     */
46
    protected $resources;
47
48
    /**
49
     * Resources Accesses table
50
     * @var string
51
     */
52
    protected $resourcesAccesses;
53
54
    /**
55
     * Access List table
56
     * @var string
57
     */
58
    protected $accessList;
59
60
    /**
61
     * Roles Inherits table
62
     * @var string
63
     */
64
    protected $rolesInherits;
65
66
    /**
67
     * Default action for no arguments is allow
68
     * @var int
69
     */
70
    protected $noArgumentsDefaultAction = Acl::ALLOW;
71
72
    /**
73
     * Company Object
74
     *
75
     * @var Companies
76
     */
77
    protected $company;
78
79
    /**
80
     * App Objc
81
     *
82
     * @var Apps
83
     */
84
    protected $app;
85
86
    /**
87
     * Class constructor.
88
     *
89
     * @param  array $options Adapter config
90
     * @throws Exception
91
     */
92 13
    public function __construct(array $options)
93
    {
94 13
        if (!isset($options['db']) || !$options['db'] instanceof DbAdapter) {
95
            throw new Exception(
96
                'Parameter "db" is required and it must be an instance of Phalcon\Acl\AdapterInterface'
97
            );
98
        }
99
100 13
        $this->connection = $options['db'];
101
102 13
        foreach (['roles', 'resources', 'resourcesAccesses', 'accessList', 'rolesInherits'] as $table) {
103 13
            if (!isset($options[$table]) || empty($options[$table]) || !is_string($options[$table])) {
104
                throw new Exception("Parameter '{$table}' is required and it must be a non empty string");
105
            }
106
107 13
            $this->{$table} = $this->connection->escapeIdentifier($options[$table]);
108
        }
109 13
    }
110
111
    /**
112
     * Set current user Company
113
     *
114
     * @param Companies $company
115
     * @return void
116
     */
117
    public function setCompany(Companies $company): void
118
    {
119
        $this->company = $company;
120
    }
121
122
    /**
123
     * Set current user app
124
     *
125
     * @param Apps $app
126
     * @return void
127
     */
128 6
    public function setApp(Apps $app): void
129
    {
130 6
        $this->app = $app;
131 6
    }
132
133
    /**
134
     * Get the current App
135
     *
136
     * @return void
137
     */
138 5
    public function getApp(): Apps
139
    {
140 5
        if (!is_object($this->app)) {
141
            $this->app = new Apps();
142
            $this->app->id = 0;
143
            $this->app->name = 'Canvas';
144
        }
145
146 5
        return $this->app;
147
    }
148
149
    /**
150
     * Get the current App
151
     *
152
     * @return void
153
     */
154
    public function getCompany() : Companies
155
    {
156
        if (!is_object($this->company)) {
157
            $this->company = new Companies();
158
            $this->company->id = 0;
159
            $this->company->name = 'Canvas';
160
        }
161
162
        return $this->company;
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     *
168
     * Example:
169
     * <code>
170
     * $acl->addRole(new Phalcon\Acl\Role('administrator'), 'consultor');
171
     * $acl->addRole('administrator', 'consultor');
172
     * </code>
173
     *
174
     * @param  \Phalcon\Acl\Role|string $role
175
     * @param  int   $scope
176
     * @param  string                   $accessInherits
177
     * @return boolean
178
     * @throws \Phalcon\Acl\Exception
179
     */
180 2
    public function addRole($role, $scope = 0, $accessInherits = null): bool
181
    {
182 2
        if (is_string($role)) {
183 1
            $role = $this->setAppByRole($role);
184
185 1
            $role = new Role($role, ucwords($role) . ' Role');
186
        }
187 2
        if (!$role instanceof RoleInterface) {
1 ignored issue
show
introduced by
$role is always a sub-type of Phalcon\Acl\RoleInterface.
Loading history...
188
            throw new Exception('Role must be either an string or implement RoleInterface');
189
        }
190
191 2
        $exists = $this->connection->fetchOne(
192 2
            "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?",
193 2
            null,
194 2
            [$role->getName()]
1 ignored issue
show
Bug introduced by
array($role->getName()) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

194
            /** @scrutinizer ignore-type */ [$role->getName()]
Loading history...
195
        );
196
197 2
        if (!$exists[0]) {
198
            $this->connection->execute(
199
                "INSERT INTO {$this->roles} (name, description, company_id, apps_id, scope, created_at) VALUES (?, ?, ?, ?, ?, ?)",
200
                [$role->getName(), $role->getDescription(), $this->getCompany()->getId(), $this->getApp()->getId(), $scope, date('Y-m-d H:i:s')]
201
            );
202
            $this->connection->execute(
203
                "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id, created_at) VALUES (?, ?, ?, ?, ?, ?)",
204
                [$role->getName(), '*', '*', $this->_defaultAccess, $this->getApp()->getId(), date('Y-m-d H:i:s')]
205
            );
206
        }
207 2
        if ($accessInherits) {
208
            return $this->addInherit($role->getName(), $accessInherits);
209
        }
210 2
        return true;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     *
216
     * @param  string $roleName
217
     * @param  string $roleToInherit
218
     * @throws \Phalcon\Acl\Exception
219
     */
220
    public function addInherit($roleName, $roleToInherit): bool
221
    {
222
        $sql = "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?";
223
        $exists = $this->connection->fetchOne($sql, null, [$roleName]);
0 ignored issues
show
Bug introduced by
array($roleName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

223
        $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$roleName]);
Loading history...
224
        if (!$exists[0]) {
225
            throw new Exception("Role '{$roleName}' does not exist in the role list");
226
        }
227
        $exists = $this->connection->fetchOne(
228
            "SELECT COUNT(*) FROM {$this->rolesInherits} WHERE roles_name = ? AND roles_inherit = ?",
229
            null,
230
            [$roleName, $roleToInherit]
0 ignored issues
show
Bug introduced by
array($roleName, $roleToInherit) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

230
            /** @scrutinizer ignore-type */ [$roleName, $roleToInherit]
Loading history...
231
        );
232
        if (!$exists[0]) {
233
            $this->connection->execute(
234
                "INSERT INTO {$this->rolesInherits} VALUES (?, ?)",
235
                [$roleName, $roleToInherit]
236
            );
237
        }
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     *
243
     * @param  string  $roleName
244
     * @return boolean
245
     */
246 2
    public function isRole($roleName): bool
247
    {
248 2
        $exists = $this->connection->fetchOne(
249 2
            "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?",
250 2
            null,
251 2
            [$roleName]
0 ignored issues
show
Bug introduced by
array($roleName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

251
            /** @scrutinizer ignore-type */ [$roleName]
Loading history...
252
        );
253 2
        return (bool) $exists[0];
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     *
259
     * @param  string  $resourceName
260
     * @return boolean
261
     */
262 1
    public function isResource($resourceName): bool
263
    {
264 1
        $exists = $this->connection->fetchOne(
265 1
            "SELECT COUNT(*) FROM {$this->resources} WHERE name = ?",
266 1
            null,
267 1
            [$resourceName]
0 ignored issues
show
Bug introduced by
array($resourceName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

267
            /** @scrutinizer ignore-type */ [$resourceName]
Loading history...
268
        );
269 1
        return (bool) $exists[0];
270
    }
271
272
    /**
273
     * Given a resource with a dot CRM.Leads , it will set the app
274
     *
275
     * @param string $resource
276
     * @return void
277
     */
278 5
    protected function setAppByResource(string $resource): string
279
    {
280
        //echeck if we have a dot , taht means we are sending the specific app to use
281 5
        if (strpos($resource, '.') !== false) {
282 5
            $appResource = explode('.', $resource);
283 5
            $resource = $appResource[1];
284 5
            $appName = $appResource[0];
285
286
            //look for the app and set it
287 5
            if ($app = Apps::getACLApp($appName)) {
288 5
                $this->setApp($app);
289
            }
290
        }
291
292 5
        return $resource;
293
    }
294
295
    /**
296
     * Given a resource with a dot CRM.Leads , it will set the app
297
     *
298
     * @param string $resource
299
     * @return void
300
     */
301 3
    protected function setAppByRole(string $role) : string
302
    {
303
        //echeck if we have a dot , taht means we are sending the specific app to use
304 3
        if (strpos($role, '.') !== false) {
305 1
            $appRole = explode('.', $role);
306 1
            $role = $appRole[1];
307 1
            $appName = $appRole[0];
308
309
            //look for the app and set it
310 1
            if ($app = Apps::getACLApp($appName)) {
311 1
                $this->setApp($app);
312
            }
313
        }
314
315 3
        return $role;
316
    }
317
318
    /**
319
     * {@inheritdoc}
320
     * Example:
321
     * <code>
322
     * //Add a resource to the the list allowing access to an action
323
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), 'search');
324
     * $acl->addResource('customers', 'search');
325
     * //Add a resource  with an access list
326
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), ['create', 'search']);
327
     * $acl->addResource('customers', ['create', 'search']);
328
     * $acl->addResource('App.customers', ['create', 'search']);
329
     * </code>
330
     *
331
     * @param  \Phalcon\Acl\Resource|string $resource
332
     * @param  array|string                 $accessList
333
     * @return boolean
334
     */
335 1
    public function addResource($resource, $accessList = null): bool
336
    {
337 1
        if (!is_object($resource)) {
338
            //echeck if we have a dot , taht means we are sending the specific app to use
339 1
            $resource = $this->setAppByResource($resource);
340
341 1
            $resource = new Resource($resource);
342
        }
343
344 1
        $exists = $this->connection->fetchOne(
345 1
            "SELECT COUNT(*) FROM {$this->resources} WHERE name = ?",
346 1
            null,
347 1
            [$resource->getName()]
0 ignored issues
show
Bug introduced by
array($resource->getName()) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

347
            /** @scrutinizer ignore-type */ [$resource->getName()]
Loading history...
348
        );
349
350 1
        if (!$exists[0]) {
351 1
            $this->connection->execute(
352 1
                "INSERT INTO {$this->resources} (name, description, apps_id, created_at) VALUES (?, ?, ?, ?)",
353 1
                [$resource->getName(), $resource->getDescription(), $this->getApp()->getId(), date('Y-m-d H:i:s')]
354
            );
355
        }
356
357 1
        if ($accessList) {
358 1
            return $this->addResourceAccess($resource->getName(), $accessList);
359
        }
360
361
        return true;
362
    }
363
364
    /**
365
     * {@inheritdoc}
366
     *
367
     * @param  string       $resourceName
368
     * @param  array|string $accessList
369
     * @return boolean
370
     * @throws \Phalcon\Acl\Exception
371
     */
372 1
    public function addResourceAccess($resourceName, $accessList): bool
373
    {
374 1
        if (!$this->isResource($resourceName)) {
375
            throw new Exception("Resource '{$resourceName}' does not exist in ACL");
376
        }
377
378 1
        $sql = "SELECT COUNT(*) FROM {$this->resourcesAccesses} WHERE resources_name = ? AND access_name = ? AND apps_id = ?";
379 1
        if (!is_array($accessList)) {
380
            $accessList = [$accessList];
381
        }
382
383 1
        foreach ($accessList as $accessName) {
384 1
            $exists = $this->connection->fetchOne($sql, null, [$resourceName, $accessName, $this->getApp()->getId()]);
0 ignored issues
show
Bug introduced by
array($resourceName, $ac...his->getApp()->getId()) of type array<integer,integer|mixed|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

384
            $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$resourceName, $accessName, $this->getApp()->getId()]);
Loading history...
385 1
            if (!$exists[0]) {
386 1
                $this->connection->execute(
387 1
                    'INSERT INTO ' . $this->resourcesAccesses . ' (resources_name, access_name, apps_id, created_at) VALUES (?, ?, ?, ?)',
388 1
                    [$resourceName, $accessName, $this->getApp()->getId(), date('Y-m-d H:i:s')]
389
                );
390
            }
391
        }
392 1
        return true;
393
    }
394
395
    /**
396
     * {@inheritdoc}
397
     *
398
     * @return \Phalcon\Acl\Resource[]
399
     */
400
    public function getResources(): \Phalcon\Acl\ResourceInterface
401
    {
402
        $resources = [];
403
        $sql = "SELECT * FROM {$this->resources}";
404
        foreach ($this->connection->fetchAll($sql, Db::FETCH_ASSOC) as $row) {
405
            $resources[] = new Resource($row['name'], $row['description']);
406
        }
407
        return $resources;
408
    }
409
410
    /**
411
     * {@inheritdoc}
412
     *
413
     * @return RoleInterface[]
414
     */
415
    public function getRoles(): \Phalcon\Acl\RoleInterface
416
    {
417
        $roles = [];
418
        $sql = "SELECT * FROM {$this->roles}";
419
        foreach ($this->connection->fetchAll($sql, Db::FETCH_ASSOC) as $row) {
420
            $roles[] = new Role($row['name'], $row['description']);
421
        }
422
        return $roles;
423
    }
424
425
    /**
426
     * {@inheritdoc}
427
     *
428
     * @param string       $resourceName
429
     * @param array|string $accessList
430
     */
431
    public function dropResourceAccess($resourceName, $accessList)
432
    {
433
        throw new BadMethodCallException('Not implemented yet.');
434
    }
435
436
    /**
437
     * {@inheritdoc}
438
     * You can use '*' as wildcard
439
     * Example:
440
     * <code>
441
     * //Allow access to guests to search on customers
442
     * $acl->allow('guests', 'customers', 'search');
443
     * //Allow access to guests to search or create on customers
444
     * $acl->allow('guests', 'customers', ['search', 'create']);
445
     * //Allow access to any role to browse on products
446
     * $acl->allow('*', 'products', 'browse');
447
     * //Allow access to any role to browse on any resource
448
     * $acl->allow('*', '*', 'browse');
449
     * </code>
450
     *
451
     * @param string       $roleName
452
     * @param string       $resourceName
453
     * @param array|string $access
454
     * @param mixed $func
455
     */
456 1
    public function allow($roleName, $resourceName, $access, $func = null)
457
    {
458 1
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::ALLOW);
459
    }
460
461
    /**
462
     * {@inheritdoc}
463
     * You can use '*' as wildcard
464
     * Example:
465
     * <code>
466
     * //Deny access to guests to search on customers
467
     * $acl->deny('guests', 'customers', 'search');
468
     * //Deny access to guests to search or create on customers
469
     * $acl->deny('guests', 'customers', ['search', 'create']);
470
     * //Deny access to any role to browse on products
471
     * $acl->deny('*', 'products', 'browse');
472
     * //Deny access to any role to browse on any resource
473
     * $acl->deny('*', '*', 'browse');
474
     * </code>
475
     *
476
     * @param  string       $roleName
477
     * @param  string       $resourceName
478
     * @param  array|string $access
479
     * @param  mixed $func
480
     * @return boolean
481
     */
482 1
    public function deny($roleName, $resourceName, $access, $func = null)
483
    {
484 1
        return $this->allowOrDeny($roleName, $resourceName, $access, Acl::DENY);
485
    }
486
487
    /**
488
     * {@inheritdoc}
489
     * Example:
490
     * <code>
491
     * //Does Andres have access to the customers resource to create?
492
     * $acl->isAllowed('Andres', 'Products', 'create');
493
     * //Do guests have access to any resource to edit?
494
     * $acl->isAllowed('guests', '*', 'edit');
495
     * </code>
496
     *
497
     * @param string $role
498
     * @param string $resource
499
     * @param string $access
500
     * @param array  $parameters
501
     * @return bool
502
     */
503 4
    public function isAllowed($role, $resource, $access, array $parameters = null): bool
504
    {
505 4
        $role = $this->setAppByRole($role);
506
        //resoure always overwrites the role app?
507 2
        $resource = $this->setAppByResource($resource);
508
509 2
        $sql = implode(' ', [
510 2
            'SELECT ' . $this->connection->escapeIdentifier('allowed') . " FROM {$this->accessList} AS a",
511
            // role_name in:
512 2
            'WHERE roles_name IN (',
513
                // given 'role'-parameter
514 2
            'SELECT ? ',
515
                // inherited role_names
516 2
            "UNION SELECT roles_inherit FROM {$this->rolesInherits} WHERE roles_name = ?",
517
                // or 'any'
518 2
            "UNION SELECT '*'",
519 2
            ')',
520
            // resources_name should be given one or 'any'
521 2
            "AND resources_name IN (?, '*')",
522
            // access_name should be given one or 'any'
523
            //"AND access_name IN (?, '*')", you need to specify * , we are forcing to check always for permisions
524 2
            'AND access_name IN (?)',
525 2
            'AND apps_id = ? ',
526
            // order be the sum of bools for 'literals' before 'any'
527 2
            'ORDER BY ' . $this->connection->escapeIdentifier('allowed') . ' DESC',
528
            // get only one...
529 2
            'LIMIT 1'
530
        ]);
531
532
        // fetch one entry...
533 2
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, [$role, $role, $resource, $access, $this->getApp()->getId()]);
1 ignored issue
show
Bug introduced by
array($role, $role, $res...his->getApp()->getId()) of type array<integer,integer|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

533
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, /** @scrutinizer ignore-type */ [$role, $role, $resource, $access, $this->getApp()->getId()]);
Loading history...
534
535 2
        if (is_array($allowed)) {
1 ignored issue
show
introduced by
The condition is_array($allowed) is always true.
Loading history...
536 2
            return (bool) $allowed[0];
537
        }
538
539
        /**
540
         * Return the default access action
541
         */
542
        return (bool) $this->_defaultAccess;
543
    }
544
545
    /**
546
     * Returns the default ACL access level for no arguments provided
547
     * in isAllowed action if there exists func for accessKey
548
     *
549
     * @return int
550
     */
551
    public function getNoArgumentsDefaultAction(): int
552
    {
553
        return $this->noArgumentsDefaultAction;
554
    }
555
556
    /**
557
     * Sets the default access level for no arguments provided
558
     * in isAllowed action if there exists func for accessKey
559
     *
560
     * @param int $defaultAccess Phalcon\Acl::ALLOW or Phalcon\Acl::DENY
561
     */
562
    public function setNoArgumentsDefaultAction($defaultAccess)
563
    {
564
        $this->noArgumentsDefaultAction = intval($defaultAccess);
565
    }
566
567
    /**
568
     * Inserts/Updates a permission in the access list
569
     *
570
     * @param  string  $roleName
571
     * @param  string  $resourceName
572
     * @param  string  $accessName
573
     * @param  integer $action
574
     * @return boolean
575
     * @throws \Phalcon\Acl\Exception
576
     */
577 2
    protected function insertOrUpdateAccess($roleName, $resourceName, $accessName, $action)
578
    {
579 2
        $resourceName = $this->setAppByResource($resourceName);
580
581
        /**
582
         * Check if the access is valid in the resource unless wildcard
583
         */
584 2
        if ($resourceName !== '*' && $accessName !== '*') {
585 2
            $sql = "SELECT COUNT(*) FROM {$this->resourcesAccesses} WHERE resources_name = ? AND access_name = ? and apps_id  = ?";
586 2
            $exists = $this->connection->fetchOne($sql, null, [$resourceName, $accessName, $this->getApp()->getId()]);
1 ignored issue
show
Bug introduced by
array($resourceName, $ac...his->getApp()->getId()) of type array<integer,integer|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

586
            $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$resourceName, $accessName, $this->getApp()->getId()]);
Loading history...
587 2
            if (!$exists[0]) {
588
                throw new Exception(
589
                    "Access '{$accessName}' does not exist in resource '{$resourceName}' in ACL"
590
                );
591
            }
592
        }
593
        /**
594
         * Update the access in access_list
595
         */
596 2
        $sql = "SELECT COUNT(*) FROM {$this->accessList} "
597 2
            . ' WHERE roles_name = ? AND resources_name = ? AND access_name = ? AND apps_id = ?';
598 2
        $exists = $this->connection->fetchOne($sql, null, [$roleName, $resourceName, $accessName, $this->getApp()->getId()]);
1 ignored issue
show
Bug introduced by
array($roleName, $resour...his->getApp()->getId()) of type array<integer,integer|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

598
        $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$roleName, $resourceName, $accessName, $this->getApp()->getId()]);
Loading history...
599 2
        if (!$exists[0]) {
600 2
            $sql = "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id, created_at) VALUES (?, ?, ?, ?, ?, ?)";
601 2
            $params = [$roleName, $resourceName, $accessName, $action, $this->getApp()->getId(), date('Y-m-d H:i:s')];
602
        } else {
603
            $sql = "UPDATE {$this->accessList} SET allowed = ? " .
604
                'WHERE roles_name = ? AND resources_name = ? AND access_name = ? AND apps_id = ?';
605
            $params = [$action, $roleName, $resourceName, $accessName, $this->getApp()->getId()];
606
        }
607 2
        $this->connection->execute($sql, $params);
608
609
        /**
610
         * Update the access '*' in access_list
611
         */
612 2
        $sql = "SELECT COUNT(*) FROM {$this->accessList} " .
613 2
            'WHERE roles_name = ? AND resources_name = ? AND access_name = ? and apps_id = ?';
614 2
        $exists = $this->connection->fetchOne($sql, null, [$roleName, $resourceName, '*', $this->getApp()->getId()]);
615 2
        if (!$exists[0]) {
616 1
            $sql = "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id, created_at) VALUES (?, ?, ?, ?, ? , ?)";
617 1
            $this->connection->execute($sql, [$roleName, $resourceName, '*', $this->_defaultAccess, $this->getApp()->getId(), date('Y-m-d H:i:s')]);
618
        }
619
620 2
        return true;
621
    }
622
623
    /**
624
     * Inserts/Updates a permission in the access list
625
     *
626
     * @param  string       $roleName
627
     * @param  string       $resourceName
628
     * @param  array|string $access
629
     * @param  integer      $action
630
     * @throws \Phalcon\Acl\Exception
631
     */
632 2
    protected function allowOrDeny($roleName, $resourceName, $access, $action)
633
    {
634 2
        if (!$this->isRole($roleName)) {
635
            throw new Exception("Role '{$roleName}' does not exist in the list");
636
        }
637 2
        if (!is_array($access)) {
638
            $access = [$access];
639
        }
640 2
        foreach ($access as $accessName) {
641 2
            $this->insertOrUpdateAccess($roleName, $resourceName, $accessName, $action);
642
        }
643
644 2
        return true;
645
    }
646
}
647