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

Guard::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 3
rs 9.6666
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 ActorInterface|null
20
     */
21
    private $actor = null;
22
23
    /**
24
     * Session specific roles.
25
     *
26
     * @var array
27
     */
28
    private $roles = [];
29
30
    /**
31
     * @var PermissionsInterface
32
     */
33
    private $permissions = null;
34
35
    /**
36
     * @param array                $roles Session specific roles.
37
     * @param ActorInterface       $actor
38
     * @param PermissionsInterface $permissions
39
     */
40
    public function __construct(
41
        array $roles = [],
42
        ActorInterface $actor = null,
43
        PermissionsInterface $permissions
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
            if ($rule === self::ALLOW) {
62
                return true;
63
            }
64
65
            if ($rule instanceof RuleInterface) {
66
                if ($rule->allows($this->actor, $permission, $context)) {
0 ignored issues
show
Bug introduced by
It seems like $this->actor can be null; however, allows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
67
                    return true;
68
                }
69
            }
70
        }
71
72
        return false;
73
    }
74
75
    /**
76
     * Currently active actor/session roles.
77
     *
78
     * @return array
79
     *
80
     * @throws GuardException
81
     */
82
    public function getRoles(): array
83
    {
84
        return array_merge($this->roles, $this->actor->getRoles());
85
    }
86
87
    /**
88
     * Create instance of guard with session specific roles (existed roles will be droppped).
89
     *
90
     * @param array $roles
91
     *
92
     * @return self
93
     */
94
    public function withRoles(array $roles): Guard
95
    {
96
        $guard = clone $this;
97
        $guard->roles = $roles;
98
99
        return $guard;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     *
105
     * @throws GuardException
106
     */
107
    public function getActor(): ActorInterface
108
    {
109
        if (empty($this->actor)) {
110
            throw new GuardException("Unable to get Guard Actor, no value set");
111
        }
112
113
        return $this->actor;
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
}