AccessVoter::hasAnyRole()   B
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 3
cts 3
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 4
nop 2
crap 5
1
<?php
2
/*
3
 * This file is part of the Exchange Rate Bundle, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\Bundle\ExchangeRate\Security;
11
12
use RunOpenCode\ExchangeRate\Contract\RateInterface;
13
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
14
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
15
use Symfony\Component\Security\Core\Role\Role;
16
17
/**
18
 * Class AccessVoter
19
 *
20
 * @package RunOpenCode\Bundle\ExchangeRate\Security
21
 */
22
class AccessVoter extends Voter
23
{
24
    /**
25
     * View action for exchange rate
26
     */
27
    const VIEW = 'view';
28
29
    /**
30
     * Create new exchange rate action
31
     */
32
    const CREATE = 'create';
33
34
    /**
35
     * Edit exchange rate action
36
     */
37
    const EDIT = 'edit';
38
39
    /**
40
     * Delete exchange rate action
41
     */
42
    const DELETE = 'delete';
43
44
    /**
45
     * @var array
46
     */
47
    protected $roles;
48
49
    /**
50
     * @var boolean
51
     */
52
    protected $enabled;
53
54
    /**
55
     * AccessVoter constructor.
56
     *
57
     * @param array $roles
58
     *
59
     * @codeCoverageIgnore
60
     */
61
    public function __construct(array $roles = [], $enabled = true)
62
    {
63
        $this->roles = array_merge([
64
            self::VIEW => [],
65
            self::CREATE => [],
66
            self::EDIT => [],
67
            self::DELETE => [],
68
        ], $roles);
69
70
        $this->enabled = $enabled;
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76 22
    protected function supports($attribute, $subject)
77
    {
78 22
        $attribute = strtolower($attribute);
79
80 22
        if ($subject instanceof RateInterface && in_array($attribute, [ self::EDIT, self::DELETE, self::VIEW ], true)) {
81 15
            return true;
82
        }
83
84
        if (
85 19
            in_array($attribute, [ self::VIEW, self::CREATE], true)
86
            &&
87 19
            is_string($subject)
88
        ) {
89 18
            return (new \ReflectionClass($subject))->implementsInterface(RateInterface::class);
90
        }
91
92 1
        return false;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 21
    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
99
    {
100 21
        if (!$this->enabled) {
101 1
            return true;
102
        }
103
104 20
        $attribute = strtolower($attribute);
105
106 20
        return $this->hasAnyRole($token, $this->roles[$attribute]);
107
    }
108
109
    /**
110
     * Check if token has any of given roles.
111
     *
112
     * @param TokenInterface $token
113
     * @param array $roles
114
     *
115
     * @return bool
116
     */
117
    private function hasAnyRole(TokenInterface $token, array $roles)
118
    {
119 20
        $tokenRoles = array_filter(array_map(function(Role $role) {
120 20
            return $role->getRole() ?: false;
121 20
        }, $token->getRoles()));
122
123
        foreach ($tokenRoles as $tokenRole) {
124
            foreach ($roles as $role) {
125
                if (strtolower($tokenRole) === strtolower($role)) {
126
                    return true;
127
                }
128
            }
129
        }
130
131
        return false;
132
    }
133
}
134