1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <contact@terryl.in>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 * 
10
 * php version 7.1.0
11
 * 
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <contact@terryl.in>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20

21
declare(strict_types=1);
22

23
namespace Shieldon\Firewall\Panel;
24

25
use Psr\Http\Message\ResponseInterface;
26
use Shieldon\Firewall\Panel\BaseController;
27
use Shieldon\Firewall\Firewall\Captcha\CaptchaFactory;
28
use Shieldon\Firewall\Captcha\Foundation;
29
use Shieldon\Event\Event;
30
use function Shieldon\Firewall\__;
31
use function Shieldon\Firewall\get_request;
32
use function Shieldon\Firewall\get_response;
33
use function Shieldon\Firewall\get_session_instance;
34
use function Shieldon\Firewall\unset_superglobal;
35
use function password_verify;
36

37
/**
38
 * User
39
 */
40
class User extends BaseController
41
{
42
    /**
43
     *   Public methods       | Desctiotion
44
     *  ----------------------|---------------------------------------------
45
     *   login                | Display the login form.
46
     *   logout               | Remove the login status.
47
     *  ----------------------|---------------------------------------------
48
     */
49

50
    /**
51
     * Constructor.
52
     */
53 3
    public function __construct() 
54
    {
55 3
        parent::__construct();
56
    }
57

58
    /**
59
     * Login
60
     * 
61
     * @param string $mode login mode.
62
     *
63
     * @return ResponseInterface
64
     */
65 3
    public function login(): ResponseInterface
66
    {
67 3
        $this->applyCaptchaForms();
68

69 3
        $postParams = get_request()->getParsedBody();
70 3
        $login = false;
71 3
        $data = [];
72

73 3
        $data['error'] = '';
74 3
        $addonTitle = $this->markAsDemo;
75

76
        if (
77 3
            isset($postParams['s_user']) &&
78 3
            isset($postParams['s_pass'])
79
        ) {
80 3
            if ($this->mode === 'demo') {
81 3
                $loginResult = $this->userLoginAsDemo(
82 3
                    $postParams['s_user'],
83 3
                    $postParams['s_pass']
84
                );
85
            } else {
86 3
                $loginResult = $this->userLoginAsAdmin(
87 3
                    $postParams['s_user'],
88 3
                    $postParams['s_pass']
89
                );
90
            }
91

92 3
            $login = $loginResult['result'];
93 3
            $data['error'] = $loginResult['message'];
94
        }
95

96 3
        if ($login) {
97
            // This session variable is to mark current session as a logged user.
98 3
            get_session_instance()->set('shieldon_user_login', true);
99

100 3
            Event::doDispatch('user_login');
101

102
            // Redirect to overview page if logged in successfully.
103 3
            return get_response()->withHeader('Location', $this->url('home/overview'));
104
        }
105

106
        // Start to prompt a login form is not logged.
107 3
        if (!defined('SHIELDON_VIEW')) {
108 3
            define('SHIELDON_VIEW', true);
109
        }
110

111
        // `$ui` will be used in `css-default.php`. Do not remove it.
112
        $ui = [
113 3
            'background_image' => '',
114
            'bg_color'         => '#ffffff',
115
            'header_bg_color'  => '#212531',
116
            'header_color'     => '#ffffff',
117
            'shadow_opacity'   => '0.2',
118
        ];
119

120 3
        $data['csrf'] = $this->fieldCsrf();
121 3
        $data['form'] = get_request()->getUri()->getPath();
122 3
        $data['captchas'] = $this->captcha;
123

124 3
        $data['css'] = include $this->kernel::KERNEL_DIR . '/../../templates/frontend/css/default.php';
125

126 3
        unset($ui);
127

128 3
        $data['title'] = __('panel', 'title_login', 'Login') . $addonTitle;
129

130 3
        return $this->respond(
131 3
            $this->loadView('frontend/login', $data)
132
        );
133
    }
134

135
    /**
136
     * Logout
137
     *
138
     * @return ResponseInterface
139
     */
140 3
    public function logout(): ResponseInterface
141
    {
142 3
        $sessionLoginStatus = get_session_instance()->get('shieldon_user_login');
143 3
        $sessionPanelLang = get_session_instance()->get('shieldon_panel_lang');
144 3
        $response = get_response();
145

146 3
        if (isset($sessionLoginStatus)) {
147 3
            unset_superglobal('shieldon_user_login', 'session');
148
        }
149

150 3
        if (isset($sessionPanelLang)) {
151 3
            unset_superglobal('shieldon_panel_lang', 'session');
152
        }
153

154
        // @codeCoverageIgnoreStart
155
        if ($this->kernel->psr7) {
156
            unset_superglobal('_shieldon', 'cookie');
157
        } else {
158
            setcookie('_shieldon', '', time() - 3600, '/');
159
        }
160
        // // @codeCoverageIgnoreEnd
161

162
        return $response->withHeader('Location', $this->url('user/login'));
163
    }
164

165
    /**
166
     * Set the Captcha modules.
167
     *
168
     * @return void
169
     */
170
    protected function applyCaptchaForms(): void
171
    {
172
        $this->captcha[] = new Foundation();
173

174
        $captchaList = [
175
            'recaptcha',
176
            'image',
177
        ];
178

179
        foreach ($captchaList as $captcha) {
180
            $setting = $this->getConfig('captcha_modules.' . $captcha);
181

182
            if (is_array($setting)) {
183
                if (CaptchaFactory::check($setting)) {
184
                    $this->captcha[] = CaptchaFactory::getInstance($captcha, $setting);
185
                }
186
            }
187
            unset($setting);
188
        }
189
    }
190

191
    /**
192
     * Login as demonstration.
193
     *
194
     * @param string $username The username.
195
     * @param string $password The password.
196
     *
197
     * @return array
198
     */
199
    private function userLoginAsDemo($username, $password): array
200
    {
201
        $login = false;
202
        $errorMsg = '';
203

204
        if ($username === 'demo' && $password === 'demo') {
205
            $login = true;
206
        }
207

208
        $captcha = $this->checkCaptchaValidation($login, $errorMsg);
209
        $login = $captcha['result'];
210
        $errorMsg = $captcha['message'];
211

212
        return [
213
            'result' => $login,
214
            'message' => $errorMsg,
215
        ];
216
    }
217

218
    /**
219
     * Login as administration.
220
     *
221
     * @param string $username The username.
222
     * @param string $password The password.
223
     *
224
     * @return array
225
     */
226 3
    private function userLoginAsAdmin($username, $password): array
227
    {
228
        $admin = $this->getConfig('admin');
229

230
        $login = false;
231
        $errorMsg = '';
232

233
        if (
234
            // Default password, unencrypted.
235
            $admin['user'] === $username && 
236
            $admin['pass'] === $password
237
        ) {
238
            // @codeCoverageIgnoreStart
239
            $login = true;
240
            // @codeCoverageIgnoreEnd
241

242
        } elseif (
243
            // User has already changed password, encrypted.
244 3
            $admin['user'] === $username && 
245 3
            password_verify($password, $admin['pass'])
246
        ) {
247 3
            $login = true;
248

249
        } else {
250 3
            $errorMsg = __('panel', 'login_message_invalid_user_or_pass', 'Invalid username or password.');
251
        }
252

253 3
        $captcha = $this->checkCaptchaValidation($login, $errorMsg);
254 3
        $login = $captcha['result'];
255 3
        $errorMsg = $captcha['message'];
256

257
        return [
258 3
            'result' => $login,
259 3
            'message' => $errorMsg,
260
        ];
261
    }
262

263
    /**
264
     * Check Captcha.
265
     * 
266
     * @param bool   $login    The login status that will be overwritten.
267
     * @param string $errorMsg The error message.
268
     *
269
     * @return array
270
     */
271 3
    private function checkCaptchaValidation(bool $login, string $errorMsg): array
272
    {
273 3
        foreach ($this->captcha as $captcha) {
274 3
            if (!$captcha->response()) {
275 3
                $login = false;
276 3
                $errorMsg = __('panel', 'login_message_invalid_captcha', 'Invalid Captcha code.');
277
            }
278
        }
279

280
        return [
281 3
            'result' => $login,
282 3
            'message' => $errorMsg,
283
        ];
284
    }
285
}

Read our documentation on viewing source code .

Loading