Completed
Push — master ( 1cdf8a...e14431 )
by Nikola
04:02
created

AccessVoter::supports()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 9
cts 9
cp 1
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 12
nc 3
nop 2
crap 6
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\RoleInterface;
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
     * AccessVoter constructor.
51
     *
52
     * @param array $roles
53
     *
54
     * @codeCoverageIgnore
55
     */
56
    public function __construct(array $roles = [])
57
    {
58
        $this->roles = array_merge([
59
            self::VIEW => [],
60
            self::CREATE => [],
61
            self::EDIT => [],
62
            self::DELETE => [],
63
        ], $roles);
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 3
    protected function supports($attribute, $subject)
70
    {
71 3
        $attribute = strtolower($attribute);
72
73 3
        if ($subject instanceof RateInterface && in_array($attribute, [ self::EDIT, self::DELETE, self::VIEW ], true)) {
74 2
            return true;
75
        }
76
77
        if (
78 3
            in_array($attribute, [ self::VIEW, self::CREATE], true)
79
            &&
80 3
            is_string($subject)
81
            &&
82 3
            class_exists($subject)
83
        ) {
84 2
            return (new \ReflectionClass($subject))->implementsInterface(RateInterface::class);
85
        }
86
87 1
        return false;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93 2
    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
94
    {
95 2
        $attribute = strtolower($attribute);
96
97 2
        return $this->hasAnyRole($token, $this->roles[$attribute]);
98
    }
99
100
    /**
101
     * Check if token has any of given roles.
102
     *
103
     * @param TokenInterface $token
104
     * @param array $roles
105
     *
106
     * @return bool
107
     */
108
    private function hasAnyRole(TokenInterface $token, array $roles)
109
    {
110 2
        $tokenRoles = array_filter(array_map(function(RoleInterface $role) {
111 2
            return $role->getRole() ?: false;
112 2
        }, $token->getRoles()));
113
114
115 2
        foreach ($tokenRoles as $tokenRole) {
116 2
            foreach ($roles as $role) {
117 2
                if (strtolower($tokenRole) === strtolower($role)) {
118 2
                    return true;
119
                }
120
            }
121
        }
122
123 1
        return false;
124
    }
125
}
126