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

AccessVoter   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 3
dl 0
loc 104
ccs 20
cts 20
cp 1
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
B supports() 0 20 6
A voteOnAttribute() 0 6 1
B hasAnyRole() 0 17 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\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