CmsComponent   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 240
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 240
rs 10
c 0
b 0
f 0
wmc 28

16 Methods

Rating   Name   Duplication   Size   Complexity  
A setParameter() 0 3 1
A getParameter() 0 3 1
A isCmsLoggedIn() 0 3 1
A renderBody() 0 4 2
A getTemplateDir() 0 3 1
A checkLogin() 0 9 3
A run() 0 19 1
A checkWhiteList() 0 7 3
A getRelativeCmsUri() 0 11 2
A checkPassword() 0 14 2
A checkBlackList() 0 7 3
A checkLoginAttempt() 0 8 2
A invalidCredentials() 0 6 1
A showLogin() 0 6 1
A checkAutoUpdateSearchIndex() 0 6 3
A routing() 0 8 1
1
<?php
2
3
namespace CloudControl\Cms\components {
4
5
    use CloudControl\Cms\cc\Application;
6
    use CloudControl\Cms\cc\Request;
7
    use CloudControl\Cms\components\cms\BaseRouting;
8
    use CloudControl\Cms\components\cms\CmsConstants;
9
    use CloudControl\Cms\crypt\Crypt;
10
    use CloudControl\Cms\storage\Storage;
11
12
    class CmsComponent extends BaseComponent
13
    {
14
        /**
15
         * @var \CloudControl\Cms\storage\Storage
16
         */
17
        public $storage;
18
19
        public $subTemplate;
20
21
        public $autoUpdateSearchIndex = true;
22
23
24
        /**
25
         * @param Storage $storage
26
         *
27
         * @return void
28
         * @throws \Exception
29
         */
30
        public function run(Storage $storage)
31
        {
32
            $this->setParameter(CmsConstants::PARAMETER_MAIN_NAV_CLASS, CmsConstants::MAIN_NAV_CLASS);
33
            $this->storage = $storage;
34
35
            $remoteAddress = $_SERVER['REMOTE_ADDR'];
36
            $this->checkWhiteList($remoteAddress);
37
            $this->checkBlackList($remoteAddress);
38
39
            $this->checkAutoUpdateSearchIndex();
40
41
            $this->checkLogin();
42
43
            $this->setParameter(CmsConstants::PARAMETER_USER_RIGHTS,
44
                $_SESSION[CmsConstants::SESSION_PARAMETER_CLOUD_CONTROL]->rights);
45
46
            $this->routing();
47
48
            $this->renderBody();
49
        }
50
51
        /**
52
         * See if a user is logged or wants to log in and
53
         * takes appropriate actions.
54
         *
55
         * @throws \Exception
56
         */
57
        protected function checkLogin()
58
        {
59
            $request = $this->request;
60
61
            if (!isset($_SESSION[CmsConstants::SESSION_PARAMETER_CLOUD_CONTROL])) {
62
                if (isset($request::$post[CmsConstants::POST_PARAMETER_USERNAME], $request::$post[CmsConstants::POST_PARAMETER_PASSWORD])) {
63
                    $this->checkLoginAttempt($request);
64
                } else {
65
                    $this->showLogin();
66
                }
67
            }
68
        }
69
70
        /**
71
         * Overrides normal behaviour and only renders the
72
         * login screen
73
         *
74
         * @throws \Exception
75
         */
76
        protected function showLogin()
77
        {
78
            $loginTemplatePath = CmsConstants::LOGIN_TEMPLATE_PATH;
79
            $this->renderTemplate($loginTemplatePath);
80
            ob_end_flush();
81
            exit;
82
        }
83
84
        /**
85
         * As an exception, to keep the initial file structure simple
86
         * the cms implements it's own routing, apart from the regular sitemap functionality
87
         *
88
         * @throws \Exception
89
         */
90
        protected function routing()
91
        {
92
            $relativeCmsUri = $this->getRelativeCmsUri($this->request);
93
            $userRights = $_SESSION[CmsConstants::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
94
95
            $baseRouting = new BaseRouting($this->request, $relativeCmsUri, $this);
96
            $baseRouting->setUserRights($userRights);
97
            $baseRouting->route();
98
        }
99
100
        /**
101
         * @param $remoteAddress
102
         *
103
         * @throws \Exception
104
         */
105
        protected function checkWhiteList($remoteAddress)
106
        {
107
            if (isset($this->parameters[CmsConstants::PARAMETER_WHITELIST_IPS])) {
108
                $whitelistIps = explode(',', $this->parameters[CmsConstants::PARAMETER_WHITELIST_IPS]);
109
                $whitelistIps = array_map('trim', $whitelistIps);
110
                if (!in_array($remoteAddress, $whitelistIps, true)) {
111
                    throw new \RuntimeException('Ip address ' . $remoteAddress . ' is not on whitelist');
112
                }
113
            }
114
        }
115
116
        /**
117
         * @param $remoteAddress
118
         *
119
         * @throws \Exception
120
         */
121
        protected function checkBlackList($remoteAddress)
122
        {
123
            if (isset($this->parameters[CmsConstants::PARAMETER_BLACKLIST_IPS])) {
124
                $blacklistIps = explode(',', $this->parameters[CmsConstants::PARAMETER_BLACKLIST_IPS]);
125
                $blacklistIps = array_map('trim', $blacklistIps);
126
                if (in_array($remoteAddress, $blacklistIps, true)) {
127
                    throw new \RuntimeException('Ip address ' . $remoteAddress . ' is on blacklist');
128
                }
129
            }
130
        }
131
132
        /**
133
         * @param $request
134
         *
135
         * @return mixed|string
136
         */
137
        protected function getRelativeCmsUri($request)
138
        {
139
            // TODO Use regex match parameter instead of calculating relative uri
140
            $pos = strpos($request::$relativeUri, $this->parameters[CmsConstants::PARAMETER_CMS_PREFIX]);
141
            $relativeCmsUri = '/';
142
            if ($pos !== false) {
143
                $relativeCmsUri = substr_replace($request::$relativeUri, '', $pos,
144
                    strlen($this->parameters[CmsConstants::PARAMETER_CMS_PREFIX]));
145
            }
146
147
            return $relativeCmsUri;
148
        }
149
150
        /**
151
         * @param $parameterName
152
         * @param $parameterValue
153
         */
154
        public function setParameter($parameterName, $parameterValue)
155
        {
156
            $this->parameters[$parameterName] = $parameterValue;
157
        }
158
159
        /**
160
         * @param $parameterName
161
         * @return mixed
162
         */
163
        public function getParameter($parameterName)
164
        {
165
            return $this->parameters[$parameterName];
166
        }
167
168
        /**
169
         * @throws \Exception
170
         */
171
        protected function renderBody()
172
        {
173
            if ($this->subTemplate !== null) {
174
                $this->parameters[CmsConstants::PARAMETER_BODY] = $this->renderTemplate($this->subTemplate);
175
            }
176
        }
177
178
        /**
179
         * @param Crypt $crypt
180
         * @param Request $request
181
         * @throws \Exception
182
         */
183
        protected function invalidCredentials($crypt, $request)
184
        {
185
            $crypt->encrypt($request::$post[CmsConstants::POST_PARAMETER_PASSWORD],
186
                16); // Buy time, to avoid brute forcing
187
            $this->parameters[CmsConstants::PARAMETER_ERROR_MESSAGE] = CmsConstants::INVALID_CREDENTIALS_MESSAGE;
188
            $this->showLogin();
189
        }
190
191
        /**
192
         * @param $user
193
         * @param Crypt $crypt
194
         * @param Request $request
195
         * @throws \Exception
196
         */
197
        protected function checkPassword($user, $crypt, $request)
198
        {
199
            $salt = $user->salt;
200
            $password = $user->password;
201
202
            $passwordCorrect = $crypt->compare($request::$post[CmsConstants::POST_PARAMETER_PASSWORD], $password,
203
                $salt);
204
205
            if ($passwordCorrect) {
206
                $_SESSION[CmsConstants::SESSION_PARAMETER_CLOUD_CONTROL] = $user;
207
                $this->storage->getActivityLog()->add('logged in', 'user');
208
            } else {
209
                $this->parameters[CmsConstants::PARAMETER_ERROR_MESSAGE] = CmsConstants::INVALID_CREDENTIALS_MESSAGE;
210
                $this->showLogin();
211
            }
212
        }
213
214
        /**
215
         * @param $request
216
         * @throws \Exception
217
         */
218
        protected function checkLoginAttempt($request)
219
        {
220
            $user = $this->storage->getUsers()->getUserByUsername($request::$post[CmsConstants::POST_PARAMETER_USERNAME]);
221
            $crypt = new Crypt();
222
            if (empty($user)) {
223
                $this->invalidCredentials($crypt, $request);
224
            } else {
225
                $this->checkPassword($user, $crypt, $request);
226
            }
227
        }
228
229
        /**
230
         * @param $template
231
         * @param Application $application
232
         * @return string
233
         */
234
        protected function getTemplateDir($template, $application = null)
235
        {
236
            return __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template . '.php';
237
        }
238
239
        private function checkAutoUpdateSearchIndex()
240
        {
241
            if (isset($this->parameters[CmsConstants::PARAMETER_AUTO_UPDATE_SEARCH_INDEX])) {
242
                $param = $this->parameters[CmsConstants::PARAMETER_AUTO_UPDATE_SEARCH_INDEX];
243
                if ($param === 'false') {
244
                    $this->autoUpdateSearchIndex = false;
245
                }
246
            }
247
        }
248
249
        public static function isCmsLoggedIn()
250
        {
251
            return isset($_SESSION[CmsConstants::SESSION_PARAMETER_CLOUD_CONTROL]);
252
        }
253
254
    }
255
}