Completed
Push — master ( 723cc3...ac603f )
by Arnold
07:30
created

ByGroup::getRoles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 5
cts 5
cp 1
rs 9.4285
nc 2
cc 2
eloc 5
nop 0
crap 2
1
<?php
2
3
namespace Jasny\Authz;
4
5
use Jasny\Authz\User;
6
7
/**
8
 * Authorize by access group.
9
 * Can be used for ACL (Access Control List).
10
 * 
11
 * <code>
12
 *   class Auth extends Jasny\Auth
13
 *   {
14
 *     use Jasny\Authz\ByGroup;
15
 *
16
 *     protected function getGroupStructure()
17
 *     {
18
 *       return [
19
 *         'user' => [],
20
 *         'accountant' => ['user'],
21
 *         'moderator' => ['user'],
22
 *         'developer' => ['user'],
23
 *         'admin' => ['moderator', 'developer']
24
 *       ];
25
 *     }
26
 *   }
27
 * </code>
28
 */
29
trait ByGroup
30
{
31
    /**
32
     * Get the authenticated user
33
     * 
34
     * @return User
35
     */
36
    abstract public function user();
37
    
38
    /**
39
     * Get the groups and the groups it supersedes.
40
     * 
41
     * @return array
42
     */
43
    abstract protected function getGroupStructure();
44
    
45
    
46
    /**
47
     * Get group and all groups it supersedes (recursively).
48
     *  
49
     * @param string|array $group  Single group or array of groups
50
     * @return array
51
     */
52 5
    protected function expandGroup($group)
53
    {
54 5
        $groups = (array)$group;
55 5
        $structure = $this->getGroupStructure();
56
57 5
        $expanded = [];
58
        
59 5
        foreach ($groups as $group) {
60 5
            if (!isset($structure[$group])) {
61 1
                continue;
62
            }
63
            
64 5
            $expanded[] = $group;
65 5
            $expanded = array_merge($expanded, $this->expandGroup((array)$structure[$group]));
66 5
        }
67
        
68 5
        return array_unique($expanded);
69
    }
70
    
71
    
72
    /**
73
     * Get all auth roles
74
     *  
75
     * @return array
76
     */
77 9
    public function getRoles()
78
    {
79 9
        $structure = $this->getGroupStructure();
80
        
81 9
        if (!is_array($structure)) {
82 1
            throw new \UnexpectedValueException("Group structure should be an array");
83
        }
84
        
85 8
        return array_keys($structure);
86
    }
87
    
88
    /**
89
     * Check if the current user is logged in and has specified role.
90
     * 
91
     * <code>
92
     *   if (!$auth->is('manager')) {
93
     *     http_response_code(403); // Forbidden
94
     *     echo "You are not allowed to view this page";
95
     *     exit();
96
     *   }
97
     * </code>
98
     * 
99
     * @param string $group
100
     * @return boolean
101
     */
102 7
    public function is($group)
103
    {
104 7 View Code Duplication
        if (!in_array($group, $this->getRoles())) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105 1
            trigger_error("Unknown role '$group'", E_USER_NOTICE);
106 1
            return false;
107
        }
108
        
109 6
        $user = $this->user();
110
        
111 6
        if (!isset($user)) {
112 1
            return false;
113
        }
114
        
115 5
        $userGroups = $this->expandGroup($user->getRole());
116
        
117 5
        return in_array($group, $userGroups);
118
    }
119
}
120