Passed
Push — master ( 86c3d2...1ebd3c )
by Gabor
07:26
created

Acl   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 6
dl 0
loc 115
ccs 0
cts 51
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A isAllowed() 0 16 3
A getUserPolicies() 0 5 1
A getUserGroupPolicies() 0 15 2
B checkPolicy() 0 21 7
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 7.1
6
 *
7
 * @copyright 2012 - 2017 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
declare(strict_types = 1);
13
14
namespace WebHemi\Acl;
15
16
use WebHemi\Adapter\Acl\AclAdapterInterface;
17
use WebHemi\Data\Coupler\UserGroupToPolicyCoupler;
18
use WebHemi\Data\Coupler\UserToGroupCoupler;
19
use WebHemi\Data\Coupler\UserToPolicyCoupler;
20
use WebHemi\Data\Entity\AccessManagement\PolicyEntity;
21
use WebHemi\Data\Entity\AccessManagement\ResourceEntity;
22
use WebHemi\Data\Entity\ApplicationEntity;
23
use WebHemi\Data\Entity\User\UserEntity;
24
25
/**
26
 * Class Acl
27
 */
28
final class Acl implements AclAdapterInterface
29
{
30
    /** @var UserToPolicyCoupler */
31
    private $userToPolicyCoupler;
32
    /** @var UserToGroupCoupler */
33
    private $userToGroupCoupler;
34
    /** @var UserGroupToPolicyCoupler */
35
    private $userGroupToPolicyCoupler;
36
37
    /**
38
     * Acl constructor.
39
     *
40
     * @param UserToPolicyCoupler $userToPolicyCoupler
41
     * @param UserToGroupCoupler $userToGroupCoupler
42
     * @param UserGroupToPolicyCoupler $userGroupToPolicyCoupler
43
     */
44
    public function __construct(
45
        UserToPolicyCoupler $userToPolicyCoupler,
46
        UserToGroupCoupler $userToGroupCoupler,
47
        UserGroupToPolicyCoupler $userGroupToPolicyCoupler
48
    ) {
49
        $this->userToPolicyCoupler = $userToPolicyCoupler;
50
        $this->userToGroupCoupler = $userToGroupCoupler;
51
        $this->userGroupToPolicyCoupler = $userGroupToPolicyCoupler;
52
    }
53
54
    /**
55
     * Checks if a User can access to a Resource in an Application
56
     *
57
     * @param UserEntity             $userEntity
58
     * @param ResourceEntity|null    $resourceEntity
59
     * @param ApplicationEntity|null $applicationEntity
60
     * @return bool
61
     */
62
    public function isAllowed(
63
        UserEntity $userEntity,
64
        ?ResourceEntity $resourceEntity = null,
65
        ?ApplicationEntity $applicationEntity = null
66
    ) : bool {
67
        // We assume the best case: the user has access
68
        $allowed = false;
69
70
        /** @var array<PolicyEntity> $policies */
71
        $policies = array_merge($this->getUserPolicies($userEntity), $this->getUserGroupPolicies($userEntity));
72
        foreach ($policies as $policyEntity) {
73
            $allowed = $allowed || $this->checkPolicy($policyEntity, $applicationEntity, $resourceEntity);
74
        }
75
76
        return $allowed;
77
    }
78
79
    /**
80
     * Gets the policies assigned to the user.
81
     *
82
     * @param UserEntity $userEntity
83
     * @return array<PolicyEntity>
84
     */
85
    private function getUserPolicies(UserEntity $userEntity) : array
86
    {
87
        /** @var array<PolicyEntity> $userPolicies */
88
        return $this->userToPolicyCoupler->getEntityDependencies($userEntity);
89
    }
90
91
    /**
92
     * Gets the policies assigned to the group in which the user is.
93
     *
94
     * @param UserEntity $userEntity
95
     * @return array<PolicyEntity>
96
     */
97
    private function getUserGroupPolicies(UserEntity $userEntity) : array
98
    {
99
        /** @var array<PolicyEntity> $userGroupPolicies */
100
        $userGroupPolicies = [];
101
        /** @var array<UserGroupEntity> $userGroups */
102
        $userGroups = $this->userToGroupCoupler->getEntityDependencies($userEntity);
103
104
        foreach ($userGroups as $userGroupEntity) {
105
            /** @var array<PolicyEntity> $groupPolicies */
106
            $groupPolicies = $this->userGroupToPolicyCoupler->getEntityDependencies($userGroupEntity);
107
            $userGroupPolicies = array_merge($userGroupPolicies, $groupPolicies);
108
        }
109
110
        return $userGroupPolicies;
111
    }
112
113
    /**
114
     * Check a concrete policy.
115
     *
116
     * @param PolicyEntity           $policyEntity
117
     * @param ApplicationEntity|null $applicationEntity
118
     * @param ResourceEntity|null    $resourceEntity
119
     * @return bool
120
     */
121
    private function checkPolicy(
122
        PolicyEntity $policyEntity,
123
        ?ApplicationEntity $applicationEntity = null,
124
        ?ResourceEntity $resourceEntity = null
125
    ) : bool {
126
        $policyApplicationId = $policyEntity->getApplicationId();
127
        $policyResourceId = $policyEntity->getResourceId();
128
        $applicationId = $applicationEntity ? $applicationEntity->getApplicationId() : null;
129
        $resourceId = $resourceEntity ? $resourceEntity->getResourceId() : null;
130
131
        // The user has access when:
132
        // - user/user's group has a policy that connected to the current application OR any application AND
133
        // - user/user's group has a policy that connected to the current resource OR any resource
134
        if ((is_null($policyApplicationId) || $policyApplicationId === $applicationId)
135
            && (is_null($policyResourceId) || $policyResourceId === $resourceId)
136
        ) {
137
            return $policyEntity->getAllowed();
138
        }
139
140
        return false;
141
    }
142
}
143