Completed
Push — master ( 579af5...b29473 )
by Oleg
07:53
created

micro/filter/AccessFilter.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php /** AccessFilterMicro */
2
3
namespace Micro\filter;
4
5
/**
6
 * Class AccessFilter
7
 *
8
 * @author Oleg Lunegov <[email protected]>
9
 * @link https://github.com/lugnsk/micro
10
 * @copyright Copyright &copy; 2013 Oleg Lunegov
11
 * @license /LICENSE
12
 * @package micro
13
 * @subpackage filter
14
 * @version 1.0
15
 * @since 1.0
16
 */
17
class AccessFilter extends Filter
18
{
19
    /**
20
     * @inheritdoc
21
     */
22
    public function pre(array $params)
23
    {
24
        foreach ($params['rules'] AS $rule) {
25
            $res = $this->checkRule($rule);
26
27
            if ($res === true) {
28
                return true;
29 View Code Duplication
            } elseif ($res === false) {
30
                $this->result = [
31
                    'redirect' => !empty($rule['redirect']) ? $rule['redirect'] : null,
32
                    'message' => !empty($rule['message']) ? $rule['message'] : 'Access denied!'
33
                ];
34
35
                return false;
36
            } elseif ($res === null) {
37
                continue;
38
            }
39
        }
40
41
        return true;
42
    }
43
44
    /**
45
     * Check one rule
46
     *
47
     * @access protected
48
     *
49
     * @param array $rule rule definition
50
     *
51
     * @return bool|null
52
     */
53
    protected function checkRule(array $rule)
54
    {
55
        if (
56
            $this->matchAction($rule)
57
            && $this->matchUser($rule)
58
            && $this->matchRole($rule)
59
            && $this->matchIP($rule)
60
            && $this->matchVerb($rule)
61
        ) {
62
            return $rule['allow'];
63
        } else {
64
            return null;
65
        }
66
    }
67
68
    /**
69
     * Match action
70
     *
71
     * @access protected
72
     *
73
     * @param array $rule rule definition
74
     *
75
     * @return bool
76
     */
77
    protected function matchAction($rule)
78
    {
79
        if (empty($rule['actions'])) {
80
            return true;
81
        }
82
83
        if (is_array($rule['actions'])) {
84
            return in_array($this->action, $rule['actions'], true);
85
        }
86
87
        return $this->action === $rule['actions'];
88
    }
89
90
    /**
91
     * Match user
92
     *
93
     * @access protected
94
     * @global      Container
95
     *
96
     * @param array $rule rule definition
97
     *
98
     * @return bool
99
     */
100
    protected function matchUser($rule)
101
    {
102
        if (empty($rule['users'])) {
103
            return true;
104
        }
105
106
        if (!is_array($rule['users'])) {
107
            $rule['users'][] = $rule['users'];
108
        }
109
110
        foreach ($rule['users'] AS $u) {
111
            switch ($u) {
112
                case '*':
113
                    return true;
114
115
                case '?':
116
                    if ($this->container->user->isGuest()) {
0 ignored issues
show
Accessing user on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
117
                        return true;
118
                    }
119
                    break;
120
121
                case '@':
122
                    if (!$this->container->user->isGuest()) {
0 ignored issues
show
Accessing user on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
123
                        return true;
124
                    }
125
                    break;
126
127
                default:
128
                    if ($this->container->user->getID() === $u) {
0 ignored issues
show
Accessing user on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
129
                        return true;
130
                    }
131
            }
132
        }
133
134
        return false;
135
    }
136
137
    /**
138
     * Match role
139
     *
140
     * @access protected
141
     * @global      Container
142
     *
143
     * @param array $rule rule definition
144
     *
145
     * @return bool
146
     */
147 View Code Duplication
    protected function matchRole($rule)
148
    {
149
        if (empty($rule['roles'])) {
150
            return true;
151
        }
152
153
        if (!is_array($rule['roles'])) {
154
            $rule['roles'][] = $rule['roles'];
155
        }
156
157
        foreach ($rule['roles'] AS $role) {
158
            if ($this->container->user->check($role)) {
0 ignored issues
show
Accessing user on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
159
                return true;
160
            }
161
        }
162
163
        return false;
164
    }
165
166
    /**
167
     * Match IP
168
     *
169
     * @access protected
170
     * @global      Container
171
     *
172
     * @param array $rule rule definition
173
     *
174
     * @return bool
175
     */
176
    protected function matchIP($rule)
177
    {
178
        if (empty($rule['ips'])) {
179
            return true;
180
        }
181
182
        if (!is_array($rule['ips'])) {
183
            $rule['ips'][] = $rule['ips'];
184
        }
185
186
        $userIp = $this->container->request->getUserIP();
0 ignored issues
show
Accessing request on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
187
188
        foreach ($rule['ips'] AS $r) {
189
            if ($r === '*' || $r === $userIp || (($pos = strpos($r, '*')) !== false && !strncmp($userIp, $r, $pos))) {
190
                return true;
191
            }
192
        }
193
194
        return false;
195
    }
196
197
    /**
198
     * Match verbose
199
     *
200
     * @access protected
201
     * @global      Container
202
     *
203
     * @param array $rule rule definition
204
     *
205
     * @return bool
206
     */
207 View Code Duplication
    protected function matchVerb($rule)
208
    {
209
        if (empty($rule['verb'])) {
210
            return true;
211
        }
212
213
        if (!is_array($rule['verb'])) {
214
            $rule['verb'][] = $rule['verb'];
215
        }
216
217
        $verb = $this->container->request->getMethod();
0 ignored issues
show
Accessing request on the interface Micro\base\IContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
218
        foreach ($rule['verb'] AS $v) {
219
            if ($v === $verb) {
220
                return true;
221
            }
222
        }
223
224
        return false;
225
    }
226
227
    /**
228
     * @inheritdoc
229
     */
230
    public function post(array $params)
231
    {
232
        return $params['data'];
233
    }
234
}
235