Passed
Push — master ( ff614d...6c840c )
by Anton
05:03 queued 02:24
created

GuardScope::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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