From edc2e4111a64c097b70007be5ac6db7a67d89c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=91cze=20Bence?= Date: Tue, 9 Jun 2020 02:01:41 +0200 Subject: [PATCH] MAPG-115 add login functionality --- public/index.php | 3 ++ public/static/css/mapguesser.css | 66 ++++++++++++++++++++++++++- public/static/js/login.js | 42 +++++++++++++++++ src/Cli/AddUserCommand.php | 3 +- src/Controller/LoginController.php | 73 ++++++++++++++++++++++++++++++ views/login.php | 17 +++++++ 6 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 public/static/js/login.js create mode 100644 src/Controller/LoginController.php create mode 100644 views/login.php diff --git a/public/index.php b/public/index.php index bc3ea01..d90278f 100644 --- a/public/index.php +++ b/public/index.php @@ -12,6 +12,9 @@ if (($pos = strpos($url, '?')) !== false) { $url = rawurldecode($url); Container::$routeCollection->get('index', '', [MapGuesser\Controller\HomeController::class, 'getIndex']); +Container::$routeCollection->get('login', 'login', [MapGuesser\Controller\LoginController::class, 'getLoginForm']); +Container::$routeCollection->post('login-action', 'login', [MapGuesser\Controller\LoginController::class, 'login']); +Container::$routeCollection->get('logout', 'logout', [MapGuesser\Controller\LoginController::class, 'logout']); Container::$routeCollection->get('maps', 'maps', [MapGuesser\Controller\MapsController::class, 'getMaps']); Container::$routeCollection->group('game', function (MapGuesser\Routing\RouteCollection $routeCollection) { $routeCollection->get('game', '{mapId}', [MapGuesser\Controller\GameController::class, 'getGame']); diff --git a/public/static/css/mapguesser.css b/public/static/css/mapguesser.css index d96bc8a..e95792f 100644 --- a/public/static/css/mapguesser.css +++ b/public/static/css/mapguesser.css @@ -17,7 +17,7 @@ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; } -p, h1, h2, button, a { +p, h1, h2, input, textarea, select, button, a { font-family: 'Roboto', sans-serif; } @@ -93,6 +93,10 @@ sub { margin-bottom: 10px; } +.right { + text-align: right; +} + svg.inline, img.inline { display: inline-block; width: 1em; @@ -158,6 +162,54 @@ button.red:hover, button.red:focus, a.button.red:hover, a.button.red:focus { background-color: #7f2929; } +input, select, textarea { + background-color: #f9fafb; + border: solid #c8d2e1 1px; + border-radius: 2px; + padding: 4px; + box-sizing: border-box; + font-size: 15px; + font-weight: 300; +} + +textarea { + font-size: 13px; + resize: none; +} + +input.big, select.big, textarea.big { + padding: 5px; + font-size: 18px; +} + +input.fullWidth, select.fullWidth, textarea.fullWidth { + display: block; + width: 100%; +} + +input:disabled, select:disabled, textarea:disabled { + background-color: #dfdfdf; + border: solid #dfdfdf 1px; + color: #000000; +} + +input:focus, select:focus, textarea:focus { + background-color: #ffffff; + border: solid #29457f 2px; + padding: 3px; + outline: none; +} + +input.big:focus, select.big:focus, textarea.big:focus { + padding: 4px; +} + +p.formError { + color: #7f2929; + font-weight: 500; + display: none; +} + div.header { background-color: #333333; height: 50px; @@ -200,6 +252,15 @@ div.buttonContainer>button { visibility: hidden; } +div.box { + width: 576px; + background-color: #eeeeee; + border-radius: 3px; + margin: 10px auto; + padding: 10px; + box-sizing: border-box; +} + @media screen and (max-width: 599px) { div.header.small h1 span { display: none; @@ -208,4 +269,7 @@ div.buttonContainer>button { padding: 0; width: 100%; } + div.box { + width: initial; + } } diff --git a/public/static/js/login.js b/public/static/js/login.js new file mode 100644 index 0000000..0297b14 --- /dev/null +++ b/public/static/js/login.js @@ -0,0 +1,42 @@ +(function () { + var form = document.getElementById('loginForm'); + + form.onsubmit = function (e) { + document.getElementById('loading').style.visibility = 'visible'; + + e.preventDefault(); + + var formData = new FormData(form); + + var xhr = new XMLHttpRequest(); + xhr.responseType = 'json'; + xhr.onload = function () { + document.getElementById('loading').style.visibility = 'hidden'; + + if (this.response.error) { + var errorText; + switch (this.response.error) { + case 'user_not_found': + errorText = 'No user found with the given email address.'; + break; + case 'password_not_match': + errorText = 'The given password is wrong.' + break; + } + + var loginFormError = document.getElementById('loginFormError'); + loginFormError.style.display = 'block'; + loginFormError.innerHTML = errorText; + + form.elements.email.select(); + + return; + } + + window.location.replace('/'); + }; + + xhr.open('POST', form.action, true); + xhr.send(formData); + }; +})(); diff --git a/src/Cli/AddUserCommand.php b/src/Cli/AddUserCommand.php index ce90058..45fb57d 100644 --- a/src/Cli/AddUserCommand.php +++ b/src/Cli/AddUserCommand.php @@ -22,9 +22,10 @@ class AddUserCommand extends Command { $user = new User([ 'email' => $input->getArgument('email'), - 'password' => $input->getArgument('password') ]); + $user->setPlainPassword($input->getArgument('password')); + if ($input->hasArgument('type')) { $user->setType($input->getArgument('type')); } diff --git a/src/Controller/LoginController.php b/src/Controller/LoginController.php new file mode 100644 index 0000000..5f124d4 --- /dev/null +++ b/src/Controller/LoginController.php @@ -0,0 +1,73 @@ +request = $request; + } + + public function getLoginForm() + { + $session = $this->request->session(); + + if ($session->get('user')) { + return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY); + } + + $data = []; + return new HtmlContent('login', $data); + } + + public function login(): IContent + { + $session = $this->request->session(); + + if ($session->get('user')) { + $data = ['success' => true]; + return new JsonContent($data); + } + + $select = new Select(\Container::$dbConnection, 'users'); + $select->columns(User::getFields()); + $select->where('email', '=', $this->request->post('email')); + + $userData = $select->execute()->fetch(IResultSet::FETCH_ASSOC); + + if ($userData === null) { + $data = ['error' => 'user_not_found']; + return new JsonContent($data); + } + + $user = new User($userData); + + if (!$user->checkPassword($this->request->post('password'))) { + $data = ['error' => 'password_not_match']; + return new JsonContent($data); + } + + $session->set('user', $user); + + $data = ['success' => true]; + return new JsonContent($data); + } + + public function logout(): IRedirect + { + $this->request->session()->delete('user'); + + return new Redirect([\Container::$routeCollection->getRoute('login'), []], IRedirect::TEMPORARY); + } +} diff --git a/views/login.php b/views/login.php new file mode 100644 index 0000000..565e7aa --- /dev/null +++ b/views/login.php @@ -0,0 +1,17 @@ + + +
+

Login

+
+
+ + +

+
+ +
+
+
+
+ + \ No newline at end of file