Security::checkAcl()   C
last analyzed

Complexity

Conditions 17
Paths 124

Size

Total Lines 81
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 17
eloc 47
c 3
b 0
f 0
nc 124
nop 2
dl 0
loc 81
ccs 0
cts 47
cp 0
crap 306
rs 5.0166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Dispatcher;
13
14
use Phalcon\Cli\Dispatcher as CliDispatcher;
15
use Phalcon\Dispatcher\AbstractDispatcher;
16
use Phalcon\Events\Event;
17
use Phalcon\Dispatcher\Exception;
18
use Phalcon\Mvc\Dispatcher as MvcDispatcher;
19
use Zemit\Di\Injectable;
20
21
/**
22
 * This is the security plugin which controls that users only have access to the modules they're assigned to
23
 */
24
class Security extends Injectable
25
{
26
    /**
27
     * This action is executed before execute any action in the application
28
     * @throws Exception
29
     */
30
    public function beforeDispatchLoop(Event $event, AbstractDispatcher $dispatcher): bool
31
    {
32
        return $this->checkAcl($event, $dispatcher);
33
    }
34
    
35
    /**
36
     * Check if the current identity is allowed from the dispatcher
37
     * @throws Exception
38
     */
39
    public function checkAcl(Event $event, ?AbstractDispatcher $dispatcher = null): bool
40
    {
41
        $dispatcher ??= $this->dispatcher;
42
        assert($dispatcher instanceof AbstractDispatcher);
43
        
44
        $componentNames = ['components'];
45
        
46
        // get controller and action
47
        $module = $dispatcher->getModuleName();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $module is correct as $dispatcher->getModuleName() targeting Phalcon\Dispatcher\Abstr...atcher::getModuleName() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
48
        $namespace = $dispatcher->getNamespaceName();
49
        
50
        if ($dispatcher instanceof MvcDispatcher) {
51
            $controller = $dispatcher->getControllerName();
52
//            $controllerClass = $dispatcher->getControllerClass();
53
            $componentNames [] = 'controllers';
54
        }
55
        
56
        if ($dispatcher instanceof CliDispatcher) {
57
            $task = $dispatcher->getTaskName();
58
//            $taskSuffix = $dispatcher->getTaskSuffix();
59
            $componentNames [] = 'tasks';
60
        }
61
        
62
        $handler = $controller ?? $task ?? null;
63
        $handlerClass = $dispatcher->getHandlerClass();
64
//        $handlerSuffix = $dispatcher->getHandlerSuffix();
65
        $action = $dispatcher->getActionName();
66
//        $actionSuffix = $dispatcher->getActionSuffix();
67
        
68
        // Get ACL components (components + task, or components + controllers)
69
        $acl = $this->acl->get($componentNames);
70
        
71
        // Security not found
72
        if (!$acl->isComponent($handlerClass)) {
73
            $notFoundRoute = $this->config->pathToArray('router.notFound') ?? [];
74
            $dispatcher->forward($notFoundRoute);
75
            return false;
76
        }
77
        
78
        $allowed = false;
79
        $roles = $this->identity->getAclRoles();
80
        
81
        foreach ($roles as $role) {
82
            $allowed = $acl->isAllowed($role, $handlerClass, $action);
83
            if ($allowed) {
84
                break;
85
            }
86
        }
87
        
88
        $permissions = $this->config->pathToArray('permissions');
89
        if (empty($permissions)) {
90
            $allowed = true;
91
        }
92
        
93
        if (!$allowed) {
94
            if (count($roles) > 1) {
95
                $unauthorizedRoute = $this->config->pathToArray('router.unauthorized') ?? [];
96
                if ($unauthorizedRoute['namespace'] === $namespace &&
97
                    $unauthorizedRoute['module'] === $module &&
98
                    $unauthorizedRoute['controller'] === $handler &&
99
                    $unauthorizedRoute['action'] === $action
100
                ) {
101
                    return true;
102
                }
103
                $dispatcher->forward($unauthorizedRoute);
104
            }
105
            else {
106
                $forbiddenRoute = $this->config->pathToArray('router.forbidden') ?? [];
107
                if ($forbiddenRoute['namespace'] === $namespace &&
108
                    $forbiddenRoute['module'] === $module &&
109
                    $forbiddenRoute['controller'] === $handler &&
110
                    $forbiddenRoute['action'] === $action
111
                ) {
112
                    return true;
113
                }
114
                $dispatcher->forward($forbiddenRoute);
115
            }
116
            return false;
117
        }
118
        
119
        return true;
120
    }
121
}
122