Completed
Push — master ( 9be769...48f2d6 )
by Dominik
04:24
created

RoleAuthorization   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 102
c 0
b 0
f 0
wmc 13
lcom 1
cbo 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A isGranted() 0 7 1
A getOwningRoles() 0 11 2
A resolveRoleHierarchy() 0 16 4
A getNeededRoles() 0 4 2
A checkRoles() 0 10 3
1
<?php
2
3
namespace Chubbyphp\Security\Authorization;
4
5
use Chubbyphp\Model\ModelInterface;
6
use Chubbyphp\Security\UserInterface;
7
8
final class RoleAuthorization implements AuthorizationInterface
9
{
10
    /**
11
     * @var array
12
     */
13
    private $roleHierarchy;
14
15
    /**
16
     * @var array
17
     */
18
    private $cachedResolvedHierarchies;
19
20
    /**
21
     * @param array $roleHierarchy
22
     */
23
    public function __construct(array $roleHierarchy = [])
24
    {
25
        $this->roleHierarchy = $roleHierarchy;
26
    }
27
28
    /**
29
     * @param UserInterface       $user
30
     * @param mixed               $attributes
31
     * @param ModelInterface|null $model
32
     *
33
     * @return bool
34
     */
35
    public function isGranted(UserInterface $user, $attributes, ModelInterface $model = null): bool
36
    {
37
        $owningRoles = $this->getOwningRoles($user);
38
        $neededRoles = $this->getNeededRoles($attributes);
39
40
        return $this->checkRoles($owningRoles, $neededRoles);
41
    }
42
43
    /**
44
     * @param UserInterface $user
45
     *
46
     * @return array
47
     */
48
    private function getOwningRoles(UserInterface $user): array
49
    {
50
        $roles = $user->getRoles();
51
        $rolesHash = serialize($roles);
52
53
        if (!isset($this->cachedResolvedHierarchies[$rolesHash])) {
54
            $this->cachedResolvedHierarchies[$rolesHash] = $this->resolveRoleHierarchy($user->getRoles());
55
        }
56
57
        return $this->cachedResolvedHierarchies[$rolesHash];
58
    }
59
60
    /**
61
     * @param array $roles
62
     * @param array $alreadySolvedRoles
63
     *
64
     * @return array
65
     */
66
    private function resolveRoleHierarchy(array $roles, array $alreadySolvedRoles = []): array
67
    {
68
        foreach ($roles as $role) {
69
            if (isset($this->roleHierarchy[$role])) {
70
                if (in_array($role, $alreadySolvedRoles, true)) {
71
                    continue;
72
                }
73
74
                $alreadySolvedRoles[] = $role;
75
                $resolveRoles = $this->resolveRoleHierarchy($this->roleHierarchy[$role], $alreadySolvedRoles);
76
                $roles = array_merge($roles, $resolveRoles);
77
            }
78
        }
79
80
        return array_unique($roles);
81
    }
82
83
    /**
84
     * @param mixed $attributes
85
     *
86
     * @return array
87
     */
88
    private function getNeededRoles($attributes): array
89
    {
90
        return is_scalar($attributes) ? [$attributes] : $attributes;
91
    }
92
93
    /**
94
     * @param array $owningRoles
95
     * @param array $neededRoles
96
     *
97
     * @return bool
98
     */
99
    private function checkRoles(array $owningRoles, array $neededRoles): bool
100
    {
101
        foreach ($neededRoles as $neededRole) {
102
            if (!in_array($neededRole, $owningRoles, true)) {
103
                return false;
104
            }
105
        }
106
107
        return true;
108
    }
109
}
110