Failed Conditions
Push — master ( cdc595...f2bb18 )
by Adrien
02:12
created

Acl::getCurrentRole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ecodev\Felix\Acl;
6
7
use Doctrine\Common\Util\ClassUtils;
8
use Ecodev\Felix\Model\CurrentUser;
9
use Ecodev\Felix\Model\Model;
10
11
class Acl extends \Laminas\Permissions\Acl\Acl
12
{
13
    /**
14
     * The message explaining the last denial
15
     *
16
     * @var null|string
17
     */
18
    private $message;
19
20
    /**
21
     * @var null|string
22
     */
23
    private $reason;
24
25 1
    protected function createModelResource(string $class): ModelResource
26
    {
27 1
        $resource = new ModelResource($class);
28 1
        $this->addResource($resource);
29
30 1
        return $resource;
31
    }
32
33
    /**
34
     * Return whether the current user is allowed to do something
35
     *
36
     * This should be the main method to do all ACL checks.
37
     *
38
     * @param Model $model
39
     * @param string $privilege
40
     *
41
     * @return bool
42
     */
43 1
    public function isCurrentUserAllowed(Model $model, string $privilege): bool
44
    {
45 1
        $resource = new ModelResource($this->getClass($model), $model);
46 1
        $role = $this->getCurrentRole();
47 1
        $this->reason = null;
48
49 1
        $isAllowed = $this->isAllowed($role, $resource, $privilege);
50
51 1
        $this->message = $this->buildMessage($resource, $privilege, $role, $isAllowed);
52
53 1
        return $isAllowed;
54
    }
55
56
    /**
57
     * Set the reason for rejection that will be shown to end-user
58
     *
59
     * This method always return false for usage convenience and should be used by all assertions,
60
     * instead of only return false themselves.
61
     *
62
     * @param string $reason
63
     *
64
     * @return false
65
     */
66 1
    public function reject(string $reason): bool
67
    {
68 1
        $this->reason = $reason;
69
70 1
        return false;
71
    }
72
73 1
    private function getClass(Model $resource): string
74
    {
75 1
        return ClassUtils::getRealClass(get_class($resource));
76
    }
77
78 1
    private function getCurrentRole(): string
79
    {
80 1
        $user = CurrentUser::get();
81 1
        if (!$user) {
82 1
            return 'anonymous';
83
        }
84
85 1
        return $user->getRole();
86
    }
87
88 1
    private function buildMessage(ModelResource $resource, ?string $privilege, string $role, bool $isAllowed): ?string
89
    {
90 1
        if ($isAllowed) {
91
            return null;
92
        }
93
94 1
        $resource = $resource->getName();
95
96 1
        $user = CurrentUser::get();
97 1
        $userName = $user ? 'User "' . $user->getName() . '"' : 'Non-logged user';
98 1
        $privilege = $privilege === null ? 'NULL' : $privilege;
99
100 1
        $message = "$userName with role $role is not allowed on resource \"$resource\" with privilege \"$privilege\"";
101
102 1
        if ($this->reason) {
103 1
            $message .= ' because ' . $this->reason;
104
        }
105
106 1
        return $message;
107
    }
108
109
    /**
110
     * Returns the message explaining the last denial, if any
111
     *
112
     * @return null|string
113
     */
114 1
    public function getLastDenialMessage(): ?string
115
    {
116 1
        return $this->message;
117
    }
118
}
119