Failed Conditions
Push — master ( d88873...27ba7d )
by Adrien
11:39 queued 08:54
created

Acl::createModelResource()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
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 1
    public function isCurrentUserAllowed(Model $model, string $privilege): bool
39
    {
40 1
        $resource = new ModelResource($this->getClass($model), $model);
41 1
        $role = $this->getCurrentRole();
42 1
        $this->reason = null;
43
44 1
        $isAllowed = $this->isAllowed($role, $resource, $privilege);
45
46 1
        $this->message = $this->buildMessage($resource, $privilege, $role, $isAllowed);
47
48 1
        return $isAllowed;
49
    }
50
51
    /**
52
     * Set the reason for rejection that will be shown to end-user
53
     *
54
     * This method always return false for usage convenience and should be used by all assertions,
55
     * instead of only return false themselves.
56
     *
57
     * @return false
58
     */
59 1
    public function reject(string $reason): bool
60
    {
61 1
        $this->reason = $reason;
62
63 1
        return false;
64
    }
65
66 1
    private function getClass(Model $resource): string
67
    {
68 1
        return ClassUtils::getRealClass(get_class($resource));
69
    }
70
71 1
    private function getCurrentRole(): string
72
    {
73 1
        $user = CurrentUser::get();
74 1
        if (!$user) {
75 1
            return 'anonymous';
76
        }
77
78 1
        return $user->getRole();
79
    }
80
81 1
    private function buildMessage(ModelResource $resource, ?string $privilege, string $role, bool $isAllowed): ?string
82
    {
83 1
        if ($isAllowed) {
84
            return null;
85
        }
86
87 1
        $resource = $resource->getName();
88
89 1
        $user = CurrentUser::get();
90 1
        $userName = $user ? 'User "' . $user->getLogin() . '"' : 'Non-logged user';
91 1
        $privilege = $privilege === null ? 'NULL' : $privilege;
92
93 1
        $message = "$userName with role $role is not allowed on resource \"$resource\" with privilege \"$privilege\"";
94
95 1
        if ($this->reason) {
96 1
            $message .= ' because ' . $this->reason;
97
        }
98
99 1
        return $message;
100
    }
101
102
    /**
103
     * Returns the message explaining the last denial, if any
104
     */
105 1
    public function getLastDenialMessage(): ?string
106
    {
107 1
        return $this->message;
108
    }
109
}
110