Passed
Push — develop ( f31b27...ac6bc8 )
by Jens
03:16
created

CmsComponent::bricksRouting()   D

Complexity

Conditions 10
Paths 8

Size

Total Lines 34
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 29
nc 8
nop 2
dl 0
loc 34
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
18
19
		public $storage;
20
21
        const INVALID_CREDENTIALS_MESSAGE = 'Invalid username / password combination';
22
23
        const MAIN_NAV_CLASS = 'default';
24
25
		const PARAMETER_APPLICATION_COMPONENT = 'applicationComponent';
26
		const PARAMETER_APPLICATION_COMPONENTS = 'applicationComponents';
27
        const PARAMETER_BLACKLIST_IPS = 'blacklistIps';
28
        const PARAMETER_BODY = 'body';
29
        const PARAMETER_BRICK = 'brick';
30
        const PARAMETER_BRICKS = 'bricks';
31
        const PARAMETER_CMS_PREFIX = 'cmsPrefix';
32
		const PARAMETER_CONFIGURATION = 'configuration';
33
        const PARAMETER_DOCUMENT = 'document';
34
        const PARAMETER_DOCUMENTS = 'documents';
35
        const PARAMETER_DOCUMENT_TYPE = 'documentType';
36
        const PARAMETER_DOCUMENT_TYPES = 'documentTypes';
37
        const PARAMETER_ERROR_MESSAGE = 'errorMsg';
38
        const PARAMETER_FILES = 'files';
39
        const PARAMETER_FOLDER = 'folder';
40
        const PARAMETER_IMAGE = 'image';
41
        const PARAMETER_IMAGES = 'images';
42
        const PARAMETER_IMAGE_SET = 'imageSet';
43
        const PARAMETER_MAIN_NAV_CLASS = 'mainNavClass';
44
        const PARAMETER_MY_BRICK_SLUG = 'myBrickSlug';
45
        const PARAMETER_SITEMAP = 'sitemap';
46
        const PARAMETER_SITEMAP_ITEM = 'sitemapItem';
47
        const PARAMETER_SMALLEST_IMAGE = 'smallestImage';
48
        const PARAMETER_STATIC = 'static';
49
        const PARAMETER_USER = 'user';
50
        const PARAMETER_USERS = 'users';
51
        const PARAMETER_USER_RIGHTS = 'userRights';
52
        const PARAMETER_WHITELIST_IPS = 'whitelistIps';
53
54
        const POST_PARAMETER_COMPONENT = 'component';
55
        const POST_PARAMETER_PASSWORD = 'password';
56
        const POST_PARAMETER_SAVE = 'save';
57
        const POST_PARAMETER_TEMPLATE = 'template';
58
        const POST_PARAMETER_TITLE = 'title';
59
        const POST_PARAMETER_USERNAME = 'username';
60
61
        const GET_PARAMETER_PATH = 'path';
62
        const GET_PARAMETER_SLUG = 'slug';
63
64
        const FILES_PARAMETER_FILE = 'file';
65
66
        const SESSION_PARAMETER_CLOUD_CONTROL = 'cloudcontrol';
67
68
        const LOGIN_TEMPLATE_PATH = 'cms/login';
69
70
        const CONTENT_TYPE_APPLICATION_JSON = 'Content-type:application/json';
71
72
        public $subTemplate = null;
73
74
75
        /**
76
         * @param \library\storage\Storage $storage
77
         *
78
         * @return void
79
         */
80
        public function run(Storage $storage)
81
        {
82
            $this->parameters[self::PARAMETER_MAIN_NAV_CLASS] = self::MAIN_NAV_CLASS;
83
            $this->storage = $storage;
84
85
            $remoteAddress = $_SERVER['REMOTE_ADDR'];
86
            $this->checkWhiteList($remoteAddress);
87
            $this->checkBlackList($remoteAddress);
88
89
            $this->checkLogin();
90
91
            $this->parameters[self::PARAMETER_USER_RIGHTS] = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
92
93
            $this->routing();
94
        }
95
96
        /**
97
         * See if a user is logged or wants to log in and
98
         * takes appropriate actions.
99
         *
100
         * @throws \Exception
101
         */
102
        protected function checkLogin()
103
        {
104
            $request = $this->request;
105
106
            if (!isset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL])) {
107
                if (isset($request::$post[self::POST_PARAMETER_USERNAME], $request::$post[self::POST_PARAMETER_PASSWORD])) {
108
                    $user = $this->storage->getUserByUsername($request::$post[self::POST_PARAMETER_USERNAME]);
109
                    $crypt = new Crypt();
110
                    if (empty($user)) {
111
                        $crypt->encrypt($request::$post[self::POST_PARAMETER_PASSWORD], 16); // Buy time, to avoid brute forcing
112
                        $this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
113
                        $this->showLogin();
114
                    } else {
115
                        $salt = $user->salt;
116
                        $password = $user->password;
117
118
                        $passwordCorrect = $crypt->compare($request::$post[self::POST_PARAMETER_PASSWORD], $password, $salt);
119
120
                        if ($passwordCorrect) {
121
                            $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = $user;
122
                        } else {
123
                            $this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
124
                            $this->showLogin();
125
                        }
126
                    }
127
                } else {
128
                    $this->showLogin();
129
                }
130
            }
131
        }
132
133
        /**
134
         * Overrides normal behaviour and only renders the
135
         * login screen
136
         *
137
         * @throws \Exception
138
         */
139
        protected function showLogin()
140
        {
141
            $loginTemplatePath = self::LOGIN_TEMPLATE_PATH;
142
            $this->renderTemplate($loginTemplatePath);
143
            ob_end_flush();
144
            exit;
145
        }
146
147
        /**
148
         * As an exception, to keep the initial file structure simple
149
         * the cms implements it's own routing, apart from the regular sitemap functionality
150
         *
151
         * @throws \Exception
152
         */
153
        protected function routing()
154
        {
155
            $relativeCmsUri = $this->getRelativeCmsUri($this->request);
156
157
            $userRights = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
158
159
            if ($relativeCmsUri == '' || $relativeCmsUri == '/') {
160
                $this->subTemplate = 'cms/dashboard';
161
            }
162
163
            $this->logOffRouting($this->request, $relativeCmsUri);
164
165
            $this->apiRouting($relativeCmsUri);
166
167
            if (in_array(self::PARAMETER_DOCUMENTS, $userRights)) {
168
                new DocumentRouting($this->request, $relativeCmsUri, $this);
169
            }
170
171
            if (in_array(self::PARAMETER_SITEMAP, $userRights)) {
172
                new SitemapRouting($this->request, $relativeCmsUri, $this);
173
            }
174
175
            if (in_array(self::PARAMETER_IMAGES, $userRights)) {
176
                new ImagesRouting($this->request, $relativeCmsUri, $this);
177
            }
178
179
            if (in_array(self::PARAMETER_FILES, $userRights)) {
180
                new FilesRouting($this->request, $relativeCmsUri, $this);
181
            }
182
183
            if (in_array('configuration', $userRights)) {
184
                new ConfigurationRouting($this->request, $relativeCmsUri, $this);
185
            }
186
187
            if ($this->subTemplate !== null) {
188
                $this->parameters[self::PARAMETER_BODY] = $this->renderTemplate($this->subTemplate);
189
            }
190
        }
191
192
        /**
193
         * @param $remoteAddress
194
         * @throws \Exception
195
         */
196 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...
197
        {
198
            if (isset($this->parameters[self::PARAMETER_WHITELIST_IPS])) {
199
                $whitelistIps = explode(',', $this->parameters[self::PARAMETER_WHITELIST_IPS]);
200
                $whitelistIps = array_map("trim", $whitelistIps);
201
                if (!in_array($remoteAddress, $whitelistIps)) {
202
                    throw new \Exception('Ip address ' . $remoteAddress . ' is not on whitelist');
203
                }
204
            }
205
        }
206
207
        /**
208
         * @param $remoteAddress
209
         * @throws \Exception
210
         */
211 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...
212
        {
213
            if (isset($this->parameters[self::PARAMETER_BLACKLIST_IPS])) {
214
                $blacklistIps = explode(',', $this->parameters[self::PARAMETER_BLACKLIST_IPS]);
215
                $blacklistIps = array_map("trim", $blacklistIps);
216
                if (in_array($remoteAddress, $blacklistIps)) {
217
                    throw new \Exception('Ip address ' . $remoteAddress . ' is on blacklist');
218
                }
219
            }
220
        }
221
222
        /**
223
         * @param $request
224
         * @return mixed|string
225
         */
226
        private function getRelativeCmsUri($request)
227
        {
228
            // TODO Use regex match parameter instead of calculating relative uri
229
            $pos = strpos($request::$relativeUri, $this->parameters[self::PARAMETER_CMS_PREFIX]);
230
            $relativeCmsUri = '/';
231
            if ($pos !== false) {
232
                $relativeCmsUri = substr_replace($request::$relativeUri, '', $pos, strlen($this->parameters[self::PARAMETER_CMS_PREFIX]));
233
            }
234
            return $relativeCmsUri;
235
        }
236
237
        /**
238
         * @param $relativeCmsUri
239
         */
240
        private function apiRouting($relativeCmsUri)
241
        {
242
            if ($relativeCmsUri == '/images.json') {
243
                header(self::CONTENT_TYPE_APPLICATION_JSON);
244
                die(json_encode($this->storage->getImages()));
245
            } elseif ($relativeCmsUri == '/files.json') {
246
                header(self::CONTENT_TYPE_APPLICATION_JSON);
247
                die(json_encode($this->storage->getFiles()));
248
            } elseif ($relativeCmsUri == '/documents.json') {
249
                header(self::CONTENT_TYPE_APPLICATION_JSON);
250
                die(json_encode($this->storage->getDocuments()));
251
            }
252
        }
253
254
        private function logOffRouting($request, $relativeCmsUri)
255
        {
256
            if ($relativeCmsUri == '/log-off') {
257
                $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = null;
258
                unset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]);
259
                header('Location: ' . $request::$subfolders . $this->parameters[self::PARAMETER_CMS_PREFIX]);
260
                exit;
261
            }
262
        }
263
264
        public function setParameter($parameterName, $parameterValue)
265
        {
266
            $this->parameters[$parameterName] = $parameterValue;
267
        }
268
269
        public function getParameter($parameterName)
270
        {
271
            return $this->parameters[$parameterName];
272
        }
273
    }
274
}