Enforcer::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Psecio\Invoke;
4
use \Psecio\Invoke\Match as Match;
5
use \Psecio\Invoke\Resource as Resource;
6
7
class Enforcer
8
{
9
	private $config = array();
10
	private $fail = false;
0 ignored issues
show
Unused Code introduced by
The property $fail is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
11
	private $error = 'There was an error!';
12
13
	private $options = array(
14
		'protected' => 'resource.isProtected',
15
		'groups' => 'user.hasGroup',
16
		'permissions' => 'user.hasPermission',
17
		'methods' => 'resource.hasMethod',
18
		'params' => 'route.hasParameters',
19
		'callback' => 'object.callback',
20
		'inherit' => 'internal.inherit'
21
	);
22
23
	private $matches = [];
24
25
	public function __construct($configPath)
26
	{
27
		$this->loadConfig($configPath);
28
	}
29
30
	/**
31
	 * Load the configuration from the given path
32
	 *
33
	 * @param string $configPath Path to YAML configuration file
34
	 * @return array Configuration data set
35
	 */
36
	public function loadConfig($configPath)
37
	{
38
		$yaml = new \Symfony\Component\Yaml\Parser();
39
	    $config = $yaml->parse(file_get_contents($configPath));
40
41
		if (is_array($config) && !empty($config)) {
42
			foreach ($config as $route => $setup) {
43
				$this->config[$route] = new RouteContainer($route, $setup);
44
			}
45
		}
46
47
	    return $this->config;
48
	}
49
50
	/**
51
	 * Return the current config
52
	 *
53
	 * @return array Current configuration values
54
	 */
55
	public function getConfig()
56
	{
57
		return $this->config;
58
	}
59
60
	/**
61
	 * Set the current configuration data
62
	 *
63
	 * @param array $config Configuration data
64
	 */
65
	public function setConfig(array $config)
66
	{
67
		$this->config = $config;
68
	}
69
70
	/**
71
	 * Get the current error message
72
	 *
73
	 * @return string Error message
74
	 */
75
	public function getError()
76
	{
77
		return $this->error;
78
	}
79
80
	/**
81
	 * Set the current error mesasge
82
	 *
83
	 * @param string $error Error message
84
	 */
85
	public function setError($error)
86
	{
87
		$this->error = $error;
88
	}
89
90
	/**
91
	 * Try to find a route match in the current config set
92
	 *
93
	 * @param string $uri URI to evaluate
94
	 * @param array $config Current route configuration
95
	 * @return \Psecio\Invoke\RouteContainer|null Route if found, null if not
96
	 */
97
	public function findRouteMatch($uri, array $config)
98
	{
99
		$route = null;
100
		foreach ($config as $matchUri => $routeInstance) {
101
			$match = Match::create('route.regex', ['route' => $matchUri]);
102
			if ($match->evaluate($uri) === true) {
0 ignored issues
show
Bug introduced by
The method evaluate() does not seem to exist on object<Psecio\Invoke\Match>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
103
				$routeInstance->setParams($match->getParams());
0 ignored issues
show
Bug introduced by
The method getParams() does not seem to exist on object<Psecio\Invoke\Match>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
104
				return $routeInstance;
105
			}
106
		}
107
		return $route;
108
	}
109
110
	public function addMatch(\Psecio\Invoke\RouteContainer $route)
111
	{
112
		$config = $route->getConfig();
113
114
		foreach ($config as $index => $option) {
115
			if ($this->isValidOption($index)) {
116
				$found = $this->options[$index];
117
118
				// make a match for this type
119
				$this->matches[] = Match::create($found, ['data' => $option]);
120
			}
121
		}
122
	}
123
124
	public function isValidOption($option)
125
	{
126
		return (isset($this->options[$option])) ? true : false;
127
	}
128
129
	/**
130
	 * Check to see if the request is authorized
131
	 * 	By default, fails closed
132
	 *
133
	 * @param \Psecio\Invoke\UserInterface $user User instance
134
	 * @param \Psecio\Invoke\Resource $resource Resource instance
135
	 * @param array $matches Additional matches to add manually for evaluation
136
	 * @return boolean Pass/fail of authorization
137
	 */
138
	public function isAuthorized(
139
		\Psecio\Invoke\UserInterface $user, \Psecio\Invoke\Resource $resource, array $matches = array()
0 ignored issues
show
Unused Code introduced by
The parameter $matches is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
140
	)
141
	{
142
		$data = new Data($user, $resource);
143
		$data->setEnforcer($this);
144
145
		$config = $this->config;
146
		$uri = $resource->getUri(true)['path'];
147
148
		// See if we have a route match at all
149
		$route = $this->findRouteMatch($uri, $config);
150
151
		// If we don't have a configuration for the route, allow
152
		// 	public resource
153
		if ($route === null) {
154
			return true;
155
		}
156
		$data->setRoute($route);
157
		$this->addMatch($route);
158
159
		do {
160
			$match = array_pop($this->matches);
161
			$result = $match->evaluate($data);
162
163
			if ($result === false) {
164
				$this->setError($match->getError());
165
				return false;
166
			}
167
		} while (!empty($this->matches));
168
169
		return true;
170
	}
171
172
	/**
173
	 * Get the match type of the given object instance
174
	 *
175
	 * @param object $match Match object instance
176
	 * @return string Match type
177
	 */
178
	public function getMatchType($match)
179
	{
180
		$ns = explode('\\', get_class($match));
181
		return strtolower($ns[3]);
182
	}
183
184
	/**
185
	 * Check to ensure the route exists in the current configuration
186
	 * 	One to one string match, not a regex match
187
	 *
188
	 * @param string $route Route to match
189
	 * @return boolean Match found/no match
190
	 */
191
	public function routeExists($route)
192
	{
193
		return array_key_exists($route, $this->config);
194
	}
195
196
	/**
197
	 * Evaluate if the endpoint has protection turned on
198
	 *
199
	 * @param \Psecio\RouteContainer $route Route instance
200
	 * @return boolean On/off status of protection
201
	 */
202
	public function isProtected($route)
203
	{
204
		$config = $route->getConfig();
205
		return (array_key_exists('protected', $config) && $config['protected'] === 'on');
206
	}
207
}