Completed
Branch feature/pre-split (f4dde1)
by Anton
03:26
created

Guard::allows()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Security;
9
10
use Spiral\Core\Component;
11
use Spiral\Security\Exceptions\GuardException;
12
13
/**
14
 * Checks permissions using given actor.
15
 */
16
class Guard extends Component implements GuardInterface
17
{
18
    /**
19
     * @var PermissionsInterface
20
     */
21
    private $permissions = null;
22
23
    /**
24
     * @var ActorInterface|null
25
     */
26
    private $actor = null;
27
28
    /**
29
     * Session specific roles.
30
     *
31
     * @var array
32
     */
33
    private $roles = [];
34
35
    /**
36
     * @param PermissionsInterface $permissions
37
     * @param ActorInterface       $actor
38
     * @param array                $roles Session specific roles.
39
     */
40
    public function __construct(
41
        PermissionsInterface $permissions,
42
        ActorInterface $actor = null,
43
        array $roles = []
44
    ) {
45
        $this->roles = $roles;
46
        $this->actor = $actor;
47
        $this->permissions = $permissions;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function allows(string $permission, array $context = []): bool
54
    {
55
        foreach ($this->getRoles() as $role) {
56
            if (!$this->permissions->hasRole($role)) {
57
                continue;
58
            }
59
60
            $rule = $this->permissions->getRule($role, $permission);
61
62
            //Checking our rule
63
            return $rule->allows($this->getActor(), $permission, $context);
64
        }
65
66
        return false;
67
    }
68
69
    /**
70
     * Currently active actor/session roles.
71
     *
72
     * @return array
73
     *
74
     * @throws GuardException
75
     */
76
    public function getRoles(): array
77
    {
78
        return array_merge($this->roles, $this->getActor()->getRoles());
79
    }
80
81
    /**
82
     * Create instance of guard with session specific roles (existed roles will be droppped).
83
     *
84
     * @param array $roles
85
     *
86
     * @return self
87
     */
88
    public function withRoles(array $roles): Guard
89
    {
90
        $guard = clone $this;
91
        $guard->roles = $roles;
92
93
        return $guard;
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     *
99
     * @throws GuardException
100
     */
101
    public function getActor(): ActorInterface
102
    {
103
        if (empty($this->actor)) {
104
            throw new GuardException("Unable to get Guard Actor, no value set");
105
        }
106
107
        return $this->actor;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function withActor(ActorInterface $actor): GuardInterface
114
    {
115
        $guard = clone $this;
116
        $guard->actor = $actor;
117
118
        return $guard;
119
    }
120
}