Passed
Push — master ( 6a4ae5...6131aa )
by Jean-Christophe
07:36
created

RestServer::addAllowedOrigin()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Ubiquity\controllers\rest;
4
5
use Ubiquity\controllers\Startup;
6
use Ubiquity\cache\ClassUtils;
7
use Ubiquity\cache\CacheManager;
8
use Ubiquity\exceptions\RestException;
9
use Ubiquity\log\Logger;
10
use Ubiquity\utils\http\URequest;
11
12
/**
13
 * Rest server base class.
14
 * Ubiquity\controllers\rest$RestServer
15
 * This class is part of Ubiquity
16
 *
17
 * @author jcheron <[email protected]>
18
 * @version 1.0.6
19
 *
20
 */
21
class RestServer {
22
	/**
23
	 *
24
	 * @var array
25
	 */
26
	protected $config;
27
	protected $headers;
28
	protected $tokensFolder;
29
	protected $tokenLength;
30
	protected $tokenDuration;
31
	protected $tokensCacheKey = "_apiTokens";
32
	protected $allowedOrigins;
33
34
	/**
35
	 *
36
	 * @var ApiTokens
37
	 */
38
	protected $apiTokens;
39
40 14
	public function __construct(&$config, $headers = null) {
41 14
		$this->config = $config;
42 14
		$this->headers = [ 'Access-Control-Allow-Origin' => '*','Access-Control-Allow-Credentials' => 'true','Access-Control-Max-Age' => '86400','Access-Control-Allow-Methods' => 'GET, POST, OPTIONS, PUT, DELETE, PATCH, HEAD','Content-Type' => 'application/json; charset=utf8' ];
43 14
		if (is_array ( $headers )) {
44
			$this->headers = array_merge ( $this->headers, $headers );
45
		}
46 14
	}
47
48
	/**
49
	 * Establishes the connection with the server, returns an added token in the Authorization header of the request
50
	 *
51
	 * @return array
52
	 */
53 1
	public function connect() {
54 1
		if (! isset ( $this->apiTokens )) {
55 1
			$this->apiTokens = $this->_loadApiTokens ();
56
		}
57 1
		$token = $this->apiTokens->addToken ();
58 1
		$this->_addHeaderToken ( $token );
59 1
		return [ "access_token" => $token,"token_type" => "Bearer","expires_in" => $this->apiTokens->getDuration () ];
60
	}
61
62
	/**
63
	 * Check if token is valid
64
	 *
65
	 * @return boolean
66
	 */
67 1
	public function isValid() {
68 1
		$this->apiTokens = $this->_loadApiTokens ();
69 1
		$key = $this->_getHeaderToken ();
70
		if ($this->apiTokens->isExpired ( $key )) {
71
			return false;
72
		} else {
73
			$this->_addHeaderToken ( $key );
74
			return true;
75
		}
76
	}
77
78 1
	public function _getHeaderToken() {
79 1
		$authHeader = $this->_getHeader ( "Authorization" );
80 1
		if ($authHeader !== false) {
81
			$headerDatas = explode ( " ", $authHeader, 2 );
82
			if (sizeof ( $headerDatas ) === 2) {
83
				list ( $type, $data ) = $headerDatas;
84
				if (\strcasecmp ( $type, "Bearer" ) == 0) {
85
					return $data;
86
				} else {
87
					throw new RestException ( "Bearer is required in authorization header." );
88
				}
89
			} else {
90
				throw new RestException ( "The header Authorization is required in http headers." );
91
			}
92
		} else {
93 1
			throw new RestException ( "The header Authorization is required in http headers." );
94
		}
95
	}
96
97 9
	public function finalizeTokens() {
98 9
		if (isset ( $this->apiTokens )) {
99 1
			$this->apiTokens->removeExpireds ();
100 1
			$this->apiTokens->storeToCache ();
101
		}
102 9
	}
103
104 1
	public function _getHeader($header) {
105 1
		$headers = getallheaders ();
106 1
		if (isset ( $headers [$header] )) {
107
			return $headers [$header];
108
		}
109 1
		return false;
110
	}
111
112 1
	public function _addHeaderToken($token) {
113 1
		$this->_header ( "Authorization", "Bearer " . $token, true );
114 1
	}
115
116 2
	public function _loadApiTokens() {
117 2
		return $this->getApiTokens ()->getFromCache ( CacheManager::getAbsoluteCacheDirectory () . \DS, $this->tokensCacheKey );
118
	}
119
120 2
	protected function getApiTokens() {
121 2
		if (! isset ( $this->apiTokens )) {
122 2
			$this->apiTokens = $this->newApiTokens ();
123
		}
124 2
		return $this->apiTokens;
125
	}
126
127
	/**
128
	 * To override for defining another ApiToken type
129
	 *
130
	 * @return ApiTokens
131
	 */
132 2
	protected function newApiTokens() {
133 2
		return new ApiTokens ( $this->tokenLength, $this->tokenDuration );
134
	}
135
136 14
	protected function getAllowedOrigin() {
137 14
		$http_origin = URequest::getOrigin ();
138 14
		if (is_array ( $this->allowedOrigins )) {
139
			if (array_search ( $http_origin, $this->allowedOrigins ) !== false) {
140
				return $http_origin;
141
			}
142
			return 'null';
143
		}
144 14
		return '*';
145
	}
146
147 14
	protected function setAccessControlAllowOriginHeader() {
148 14
		$origin = $this->getAllowedOrigin ();
149 14
		unset ( $this->headers ['Access-Control-Allow-Origin'] );
150 14
		\header ( 'Access-Control-Allow-Origin: ' . $origin, true );
151 14
	}
152
153 14
	protected function addOtherHeaders() {
154 14
		foreach ( $this->headers as $k => $v ) {
155 14
			$this->_header ( $k, $v );
156
		}
157 14
	}
158
159
	/**
160
	 *
161
	 * @param string $headerField
162
	 * @param string $value
163
	 * @param boolean $replace
164
	 */
165 14
	public function _header($headerField, $value = null, $replace = null) {
166 14
		if (! isset ( $value )) {
167 14
			if (isset ( $this->headers [$headerField] )) {
168 14
				$value = $this->headers [$headerField];
169 14
				unset ( $this->headers [$headerField] );
170
			} else
171 14
				return;
172
		}
173 14
		\header ( trim ( $headerField ) . ": " . trim ( $value ), $replace );
174 14
	}
175
176
	/**
177
	 *
178
	 * @param string $contentType default application/json
179
	 * @param string $charset default utf8
180
	 */
181 14
	public function _setContentType($contentType = null, $charset = null) {
182 14
		$value = $contentType;
183 14
		if (isset ( $charset ))
184
			$value .= "; charset=" . $charset;
185 14
		$this->_header ( "Content-type", $value );
186 14
	}
187
188 14
	public function cors() {
189 14
		$this->setAccessControlAllowOriginHeader ();
190 14
		$this->_header ( 'Access-Control-Allow-Credentials' );
191 14
		$this->_header ( 'Access-Control-Max-Age' );
192 14
		if ($_SERVER ['REQUEST_METHOD'] == 'OPTIONS') {
193
			if (isset ( $_SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] ))
194
				$this->_header ( 'Access-Control-Allow-Methods' );
195
196
			if (isset ( $_SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] )) {
197
				$this->_header ( 'Access-Control-Allow-Headers', $_SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] );
198
			} else {
199
				$this->_header ( 'Access-Control-Allow-Headers', '*' );
200
			}
201
			Logger::info ( "Rest", "cors exit normally", "Cors" );
202
		}
203 14
		$this->addOtherHeaders ();
204 14
	}
205
206 1
	public static function getRestNamespace() {
207 1
		$config = Startup::getConfig ();
208 1
		$controllerNS = $config ["mvcNS"] ["controllers"];
209 1
		$restNS = "";
210 1
		if (isset ( $config ["mvcNS"] ["rest"] )) {
211 1
			$restNS = $config ["mvcNS"] ["rest"];
212
		}
213 1
		return ClassUtils::getNamespaceFromParts ( [ $controllerNS,$restNS ] );
214
	}
215
216
	/**
217
	 * Adds an unique allowed origin for access control.
218
	 *
219
	 * @param string $address
220
	 */
221
	public function setAllowedOrigin($address = '*') {
222
		if ($address !== '*') {
223
			$this->allowedOrigins = [ $address ];
224
		} else {
225
			$this->allowedOrigins = [ ];
226
		}
227
	}
228
229
	/**
230
	 * Sets the allowed origins for access control.
231
	 *
232
	 * @param array $addresses
233
	 */
234
	public function setAllowedOrigins($addresses) {
235
		$this->allowedOrigins = $addresses;
236
	}
237
238
	/**
239
	 * Adds an allowed origin for access control.
240
	 *
241
	 * @param string $address
242
	 */
243
	public function addAllowedOrigin($address) {
244
		$this->allowedOrigins = [ $address ];
245
	}
246
247
	/**
248
	 *
249
	 * @param int $tokenLength
250
	 */
251
	public function setTokenLength($tokenLength) {
252
		$this->tokenLength = $tokenLength;
253
	}
254
255
	/**
256
	 *
257
	 * @param mixed $tokenDuration
258
	 */
259
	public function setTokenDuration($tokenDuration) {
260
		$this->tokenDuration = $tokenDuration;
261
	}
262
}
263