Passed
Push — develop ( 92a637...7ee7eb )
by Jens
12:26
created

CmsComponent::imageRouting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 6
rs 9.4285
1
<?php
2
namespace library\components {
3
4
	use library\components\cms\ConfigurationRouting;
5
	use library\components\cms\DocumentRouting;
6
	use library\components\cms\FilesRouting;
7
	use library\components\cms\ImagesRouting;
8
	use library\components\cms\SitemapRouting;
9
	use library\crypt\Crypt;
10
	use library\storage\Storage;
11
12
	class CmsComponent extends BaseComponent
13
	{
14
		/*
15
		 * var \library\storage\Storage
16
		 */
17
		public $storage;
18
19
		const INVALID_CREDENTIALS_MESSAGE = 'Invalid username / password combination';
20
21
		const MAIN_NAV_CLASS = 'default';
22
23
		const PARAMETER_APPLICATION_COMPONENT = 'applicationComponent';
24
		const PARAMETER_APPLICATION_COMPONENTS = 'applicationComponents';
25
		const PARAMETER_BLACKLIST_IPS = 'blacklistIps';
26
		const PARAMETER_BODY = 'body';
27
		const PARAMETER_BRICK = 'brick';
28
		const PARAMETER_BRICKS = 'bricks';
29
		const PARAMETER_CMS_PREFIX = 'cmsPrefix';
30
		const PARAMETER_CONFIGURATION = 'configuration';
31
		const PARAMETER_DOCUMENT = 'document';
32
		const PARAMETER_DOCUMENTS = 'documents';
33
		const PARAMETER_DOCUMENT_TYPE = 'documentType';
34
		const PARAMETER_DOCUMENT_TYPES = 'documentTypes';
35
		const PARAMETER_ERROR_MESSAGE = 'errorMsg';
36
		const PARAMETER_FILES = 'files';
37
		const PARAMETER_FOLDER = 'folder';
38
		const PARAMETER_IMAGE = 'image';
39
		const PARAMETER_IMAGES = 'images';
40
		const PARAMETER_IMAGE_SET = 'imageSet';
41
		const PARAMETER_MAIN_NAV_CLASS = 'mainNavClass';
42
		const PARAMETER_MY_BRICK_SLUG = 'myBrickSlug';
43
		const PARAMETER_SITEMAP = 'sitemap';
44
		const PARAMETER_SITEMAP_ITEM = 'sitemapItem';
45
		const PARAMETER_SMALLEST_IMAGE = 'smallestImage';
46
		const PARAMETER_STATIC = 'static';
47
		const PARAMETER_USER = 'user';
48
		const PARAMETER_USERS = 'users';
49
		const PARAMETER_USER_RIGHTS = 'userRights';
50
		const PARAMETER_WHITELIST_IPS = 'whitelistIps';
51
52
		const POST_PARAMETER_COMPONENT = 'component';
53
		const POST_PARAMETER_PASSWORD = 'password';
54
		const POST_PARAMETER_SAVE = 'save';
55
		const POST_PARAMETER_TEMPLATE = 'template';
56
		const POST_PARAMETER_TITLE = 'title';
57
		const POST_PARAMETER_USERNAME = 'username';
58
59
		const GET_PARAMETER_PATH = 'path';
60
		const GET_PARAMETER_SLUG = 'slug';
61
62
		const FILES_PARAMETER_FILE = 'file';
63
64
		const SESSION_PARAMETER_CLOUD_CONTROL = 'cloudcontrol';
65
66
		const LOGIN_TEMPLATE_PATH = 'cms/login';
67
68
		const CONTENT_TYPE_APPLICATION_JSON = 'Content-type:application/json';
69
70
		public $subTemplate = null;
71
72
73
		/**
74
		 * @param \library\storage\Storage $storage
75
		 *
76
		 * @return void
77
		 */
78
		public function run(Storage $storage)
79
		{
80
			$this->parameters[self::PARAMETER_MAIN_NAV_CLASS] = self::MAIN_NAV_CLASS;
81
			$this->storage = $storage;
82
83
			$remoteAddress = $_SERVER['REMOTE_ADDR'];
84
			$this->checkWhiteList($remoteAddress);
85
			$this->checkBlackList($remoteAddress);
86
87
			$this->checkLogin();
88
89
			$this->parameters[self::PARAMETER_USER_RIGHTS] = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
90
91
			$this->routing();
92
		}
93
94
		/**
95
		 * See if a user is logged or wants to log in and
96
		 * takes appropriate actions.
97
		 *
98
		 * @throws \Exception
99
		 */
100
		protected function checkLogin()
101
		{
102
			$request = $this->request;
103
104
			if (!isset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL])) {
105
				if (isset($request::$post[self::POST_PARAMETER_USERNAME], $request::$post[self::POST_PARAMETER_PASSWORD])) {
106
					$this->checkLoginAttempt($request);
107
				} else {
108
					$this->showLogin();
109
				}
110
			}
111
		}
112
113
		/**
114
		 * Overrides normal behaviour and only renders the
115
		 * login screen
116
		 *
117
		 * @throws \Exception
118
		 */
119
		protected function showLogin()
120
		{
121
			$loginTemplatePath = self::LOGIN_TEMPLATE_PATH;
122
			$this->renderTemplate($loginTemplatePath);
123
			ob_end_flush();
124
			exit;
125
		}
126
127
		/**
128
		 * As an exception, to keep the initial file structure simple
129
		 * the cms implements it's own routing, apart from the regular sitemap functionality
130
		 *
131
		 * @throws \Exception
132
		 */
133
		protected function routing()
134
		{
135
			$relativeCmsUri = $this->getRelativeCmsUri($this->request);
136
137
			$userRights = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
138
139
			$this->dashboardRouting($relativeCmsUri);
140
			$this->logOffRouting($this->request, $relativeCmsUri);
141
			$this->apiRouting($relativeCmsUri);
142
			$this->documentRouting($userRights, $relativeCmsUri);
143
			$this->sitemapRouting($userRights, $relativeCmsUri);
144
			$this->imageRouting($userRights, $relativeCmsUri);
145
			$this->filesRouting($userRights, $relativeCmsUri);
146
			$this->configurationRouting($userRights, $relativeCmsUri);
147
148
			$this->renderBody();
149
		}
150
151
		/**
152
		 * @param $remoteAddress
153
		 *
154
		 * @throws \Exception
155
		 */
156 View Code Duplication
		private function checkWhiteList($remoteAddress)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
157
		{
158
			if (isset($this->parameters[self::PARAMETER_WHITELIST_IPS])) {
159
				$whitelistIps = explode(',', $this->parameters[self::PARAMETER_WHITELIST_IPS]);
160
				$whitelistIps = array_map("trim", $whitelistIps);
161
				if (!in_array($remoteAddress, $whitelistIps)) {
162
					throw new \Exception('Ip address ' . $remoteAddress . ' is not on whitelist');
163
				}
164
			}
165
		}
166
167
		/**
168
		 * @param $remoteAddress
169
		 *
170
		 * @throws \Exception
171
		 */
172 View Code Duplication
		private function checkBlackList($remoteAddress)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
173
		{
174
			if (isset($this->parameters[self::PARAMETER_BLACKLIST_IPS])) {
175
				$blacklistIps = explode(',', $this->parameters[self::PARAMETER_BLACKLIST_IPS]);
176
				$blacklistIps = array_map("trim", $blacklistIps);
177
				if (in_array($remoteAddress, $blacklistIps)) {
178
					throw new \Exception('Ip address ' . $remoteAddress . ' is on blacklist');
179
				}
180
			}
181
		}
182
183
		/**
184
		 * @param $request
185
		 *
186
		 * @return mixed|string
187
		 */
188
		private function getRelativeCmsUri($request)
189
		{
190
			// TODO Use regex match parameter instead of calculating relative uri
191
			$pos = strpos($request::$relativeUri, $this->parameters[self::PARAMETER_CMS_PREFIX]);
192
			$relativeCmsUri = '/';
193
			if ($pos !== false) {
194
				$relativeCmsUri = substr_replace($request::$relativeUri, '', $pos, strlen($this->parameters[self::PARAMETER_CMS_PREFIX]));
195
			}
196
197
			return $relativeCmsUri;
198
		}
199
200
		/**
201
		 * @param $relativeCmsUri
202
		 */
203
		private function apiRouting($relativeCmsUri)
204
		{
205
			if ($relativeCmsUri == '/images.json') {
206
				header(self::CONTENT_TYPE_APPLICATION_JSON);
207
				die(json_encode($this->storage->getImages()));
208
			} elseif ($relativeCmsUri == '/files.json') {
209
				header(self::CONTENT_TYPE_APPLICATION_JSON);
210
				die(json_encode($this->storage->getFiles()));
211
			} elseif ($relativeCmsUri == '/documents.json') {
212
				header(self::CONTENT_TYPE_APPLICATION_JSON);
213
				die(json_encode($this->storage->getDocuments()));
214
			}
215
		}
216
217
		private function logOffRouting($request, $relativeCmsUri)
218
		{
219
			if ($relativeCmsUri == '/log-off') {
220
				$_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = null;
221
				unset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]);
222
				header('Location: ' . $request::$subfolders . $this->parameters[self::PARAMETER_CMS_PREFIX]);
223
				exit;
224
			}
225
		}
226
227
		public function setParameter($parameterName, $parameterValue)
228
		{
229
			$this->parameters[$parameterName] = $parameterValue;
230
		}
231
232
		public function getParameter($parameterName)
233
		{
234
			return $this->parameters[$parameterName];
235
		}
236
237
		/**
238
		 * @param $relativeCmsUri
239
		 */
240
		protected function dashboardRouting($relativeCmsUri)
241
		{
242
			if ($relativeCmsUri == '' || $relativeCmsUri == '/') {
243
				$this->subTemplate = 'cms/dashboard';
244
			}
245
		}
246
247
		/**
248
		 * @param $userRights
249
		 * @param $relativeCmsUri
250
		 */
251
		protected function documentRouting($userRights, $relativeCmsUri)
252
		{
253
			if (in_array(self::PARAMETER_DOCUMENTS, $userRights)) {
254
				new DocumentRouting($this->request, $relativeCmsUri, $this);
255
			}
256
		}
257
258
		/**
259
		 * @param $userRights
260
		 * @param $relativeCmsUri
261
		 */
262
		protected function sitemapRouting($userRights, $relativeCmsUri)
263
		{
264
			if (in_array(self::PARAMETER_SITEMAP, $userRights)) {
265
				new SitemapRouting($this->request, $relativeCmsUri, $this);
266
			}
267
		}
268
269
		/**
270
		 * @param $userRights
271
		 * @param $relativeCmsUri
272
		 */
273
		protected function imageRouting($userRights, $relativeCmsUri)
274
		{
275
			if (in_array(self::PARAMETER_IMAGES, $userRights)) {
276
				new ImagesRouting($this->request, $relativeCmsUri, $this);
277
			}
278
		}
279
280
		/**
281
		 * @param $userRights
282
		 * @param $relativeCmsUri
283
		 */
284
		protected function filesRouting($userRights, $relativeCmsUri)
285
		{
286
			if (in_array(self::PARAMETER_FILES, $userRights)) {
287
				new FilesRouting($this->request, $relativeCmsUri, $this);
288
			}
289
		}
290
291
		/**
292
		 * @param $userRights
293
		 * @param $relativeCmsUri
294
		 */
295
		protected function configurationRouting($userRights, $relativeCmsUri)
296
		{
297
			if (in_array('configuration', $userRights)) {
298
				new ConfigurationRouting($this->request, $relativeCmsUri, $this);
299
			}
300
		}
301
302
		protected function renderBody()
303
		{
304
			if ($this->subTemplate !== null) {
305
				$this->parameters[self::PARAMETER_BODY] = $this->renderTemplate($this->subTemplate);
306
			}
307
		}
308
309
		/**
310
		 * @param $crypt
311
		 * @param $request
312
		 */
313
		protected function invalidCredentials($crypt, $request)
314
		{
315
			$crypt->encrypt($request::$post[self::POST_PARAMETER_PASSWORD], 16); // Buy time, to avoid brute forcing
316
			$this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
317
			$this->showLogin();
318
		}
319
320
		/**
321
		 * @param $user
322
		 * @param $crypt
323
		 * @param $request
324
		 */
325
		protected function checkPassword($user, $crypt, $request)
326
		{
327
			$salt = $user->salt;
328
			$password = $user->password;
329
330
			$passwordCorrect = $crypt->compare($request::$post[self::POST_PARAMETER_PASSWORD], $password, $salt);
331
332
			if ($passwordCorrect) {
333
				$_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = $user;
334
			} else {
335
				$this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
336
				$this->showLogin();
337
			}
338
		}
339
340
		/**
341
		 * @param $request
342
		 */
343
		protected function checkLoginAttempt($request)
344
		{
345
			$user = $this->storage->getUserByUsername($request::$post[self::POST_PARAMETER_USERNAME]);
346
			$crypt = new Crypt();
347
			if (empty($user)) {
348
				$this->invalidCredentials($crypt, $request);
349
			} else {
350
				$this->checkPassword($user, $crypt, $request);
351
			}
352
		}
353
	}
354
}