MAPG-115 add login functionality

This commit is contained in:
Bence Pőcze 2020-06-09 02:01:41 +02:00
parent d93a758cd2
commit edc2e4111a
6 changed files with 202 additions and 2 deletions

View File

@ -12,6 +12,9 @@ if (($pos = strpos($url, '?')) !== false) {
$url = rawurldecode($url); $url = rawurldecode($url);
Container::$routeCollection->get('index', '', [MapGuesser\Controller\HomeController::class, 'getIndex']); 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->get('maps', 'maps', [MapGuesser\Controller\MapsController::class, 'getMaps']);
Container::$routeCollection->group('game', function (MapGuesser\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('game', function (MapGuesser\Routing\RouteCollection $routeCollection) {
$routeCollection->get('game', '{mapId}', [MapGuesser\Controller\GameController::class, 'getGame']); $routeCollection->get('game', '{mapId}', [MapGuesser\Controller\GameController::class, 'getGame']);

View File

@ -17,7 +17,7 @@ button::-moz-focus-inner, input::-moz-focus-inner {
border: 0; border: 0;
} }
p, h1, h2, button, a { p, h1, h2, input, textarea, select, button, a {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
} }
@ -93,6 +93,10 @@ sub {
margin-bottom: 10px; margin-bottom: 10px;
} }
.right {
text-align: right;
}
svg.inline, img.inline { svg.inline, img.inline {
display: inline-block; display: inline-block;
width: 1em; width: 1em;
@ -158,6 +162,54 @@ button.red:hover, button.red:focus, a.button.red:hover, a.button.red:focus {
background-color: #7f2929; 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 { div.header {
background-color: #333333; background-color: #333333;
height: 50px; height: 50px;
@ -200,6 +252,15 @@ div.buttonContainer>button {
visibility: hidden; 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) { @media screen and (max-width: 599px) {
div.header.small h1 span { div.header.small h1 span {
display: none; display: none;
@ -208,4 +269,7 @@ div.buttonContainer>button {
padding: 0; padding: 0;
width: 100%; width: 100%;
} }
div.box {
width: initial;
}
} }

42
public/static/js/login.js Normal file
View File

@ -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);
};
})();

View File

@ -22,9 +22,10 @@ class AddUserCommand extends Command
{ {
$user = new User([ $user = new User([
'email' => $input->getArgument('email'), 'email' => $input->getArgument('email'),
'password' => $input->getArgument('password')
]); ]);
$user->setPlainPassword($input->getArgument('password'));
if ($input->hasArgument('type')) { if ($input->hasArgument('type')) {
$user->setType($input->getArgument('type')); $user->setType($input->getArgument('type'));
} }

View File

@ -0,0 +1,73 @@
<?php namespace MapGuesser\Controller;
use MapGuesser\Database\Query\Select;
use MapGuesser\Interfaces\Database\IResultSet;
use MapGuesser\Interfaces\Request\IRequest;
use MapGuesser\Interfaces\Response\IContent;
use MapGuesser\Interfaces\Response\IRedirect;
use MapGuesser\Model\User;
use MapGuesser\Response\HtmlContent;
use MapGuesser\Response\JsonContent;
use MapGuesser\Response\Redirect;
class LoginController
{
private IRequest $request;
public function __construct(IRequest $request)
{
$this->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);
}
}

17
views/login.php Normal file
View File

@ -0,0 +1,17 @@
<?php require ROOT . '/views/templates/main_header.php'; ?>
<?php require ROOT . '/views/templates/header.php'; ?>
<div class="main">
<h2>Login</h2>
<div class="box">
<form id="loginForm" action="/login" method="post">
<input class="big fullWidth" type="email" name="email" placeholder="Email address" autofocus>
<input class="big fullWidth marginTop" type="password" name="password" placeholder="Password">
<p id="loginFormError" class="formError marginTop"></p>
<div class="right marginTop">
<button type="submit">Login</button>
</div>
</form>
</div>
</div>
<script src="/static/js/login.js"></script>
<?php require ROOT . '/views/templates/main_footer.php'; ?>