Add register and login of authentification actions #12
Merged
samuel.berion
merged 22 commits from connexion/bootstrap
into master
1 year ago
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Gateway\AuthGateway;
|
||||
use App\Http\HttpRequest;
|
||||
use App\Http\HttpResponse;
|
||||
use App\Http\ViewHttpResponse;
|
||||
use App\Model\AuthModel;
|
||||
use App\Validation\FieldValidationFail;
|
||||
use App\Validation\ValidationFail;
|
||||
use App\Validation\Validators;
|
||||
use Twig\Environment;
|
||||
|
||||
class AuthController {
|
||||
private AuthModel $model;
|
||||
|
||||
/**
|
||||
* @param AuthModel $model
|
||||
*/
|
||||
public function __construct(AuthModel $model) {
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function displayRegister(): HttpResponse {
|
||||
return ViewHttpResponse::twig("display_register.html.twig", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $viewName
|
||||
* @param ValidationFail[] $fails
|
||||
* @return HttpResponse
|
||||
*/
|
||||
private function displayBadFields(string $viewName, array $fails): HttpResponse {
|
||||
$bad_fields = [];
|
||||
foreach ($fails as $err) {
|
||||
if ($err instanceof FieldValidationFail) {
|
||||
$bad_fields[] = $err->getFieldName();
|
||||
}
|
||||
}
|
||||
return ViewHttpResponse::twig($viewName, ['bad_fields' => $bad_fields]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $request
|
||||
* @return HttpResponse
|
||||
*/
|
||||
public function confirmRegister(array $request): HttpResponse {
|
||||
$fails = [];
|
||||
$request = HttpRequest::from($request, $fails, [
|
||||
"username" => [Validators::name(), Validators::lenBetween(2, 32)],
|
||||
"password" => [Validators::lenBetween(6, 256)],
|
||||
"confirmpassword" => [Validators::lenBetween(6, 256)],
|
||||
"email" => [Validators::regex("/^\\S+@\\S+\\.\\S+$/"),Validators::lenBetween(5, 256)],
|
||||
]);
|
||||
if (!empty($fails)) {
|
||||
return $this->displayBadFields("display_register.html.twig", $fails);
|
||||
}
|
||||
$fails = $this->model->register($request['username'], $request["password"], $request['confirmpassword'], $request['email']);
|
||||
if (empty($fails)) {
|
||||
$results = $this->model->getUserFields($request['email']);
|
||||
return ViewHttpResponse::twig("display_auth_confirm.html.twig", ['username' => $results['username'], 'email' => $results['email']]);
|
||||
}
|
||||
return $this->displayBadFields("display_register.html.twig", $fails);
|
||||
}
|
||||
|
||||
|
||||
public function displayLogin(): HttpResponse {
|
||||
return ViewHttpResponse::twig("display_login.html.twig", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $request
|
||||
* @return HttpResponse
|
||||
*/
|
||||
public function confirmLogin(array $request): HttpResponse {
|
||||
$fails = [];
|
||||
$request = HttpRequest::from($request, $fails, [
|
||||
"password" => [Validators::lenBetween(6, 256)],
|
||||
"email" => [Validators::regex("/^\\S+@\\S+\\.\\S+$/"),Validators::lenBetween(5, 256)],
|
||||
]);
|
||||
if (!empty($fails)) {
|
||||
return $this->displayBadFields("display_login.html.twig", $fails);
|
||||
}
|
||||
|
||||
$fails = $this->model->login($request['email'], $request['password']);
|
||||
if (empty($fails)) {
|
||||
$results = $this->model->getUserFields($request['email']);
|
||||
return ViewHttpResponse::twig("display_auth_confirm.html.twig", ['username' => $results['username'], 'email' => $results['email']]);
|
||||
}
|
||||
return $this->displayBadFields("display_login.html.twig", $fails);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Gateway;
|
||||
|
||||
use App\Connexion;
|
||||
use PDO;
|
||||
|
||||
class AuthGateway {
|
||||
private Connexion $con;
|
||||
|
||||
/**
|
||||
* @param Connexion $con
|
||||
*/
|
||||
public function __construct(Connexion $con) {
|
||||
$this->con = $con;
|
||||
}
|
||||
|
||||
|
||||
public function mailExist(string $email): bool {
|
||||
return $this->getUserFields($email) != null;
|
||||
}
|
||||
|
||||
|
||||
public function insertAccount(string $username, string $hash, string $email): void {
|
||||
$this->con->exec("INSERT INTO AccountUser VALUES (:username,:hash,:email)", [':username' => [$username, PDO::PARAM_STR],':hash' => [$hash, PDO::PARAM_STR],':email' => [$email, PDO::PARAM_STR]]);
|
||||
}
|
||||
|
||||
public function getUserHash(string $email): string {
|
||||
$results = $this->con->fetch("SELECT hash FROM AccountUser WHERE email = :email", [':email' => [$email, PDO::PARAM_STR]]);
|
||||
return $results[0]['hash'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
* @return array<string,string>|null
|
||||
*/
|
||||
public function getUserFields(string $email): ?array {
|
||||
$results = $this->con->fetch("SELECT username,email FROM AccountUser WHERE email = :email", [':email' => [$email, PDO::PARAM_STR]]);
|
||||
$firstRow = $results[0] ?? null;
|
||||
return $firstRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Controller\AuthController;
|
||||
use App\Gateway\AuthGateway;
|
||||
use App\Validation\FieldValidationFail;
|
||||
use App\Validation\ValidationFail;
|
||||
|
||||
class AuthModel {
|
||||
private AuthGateway $gateway;
|
||||
/**
|
||||
* @param AuthGateway $gateway
|
||||
*/
|
||||
public function __construct(AuthGateway $gateway) {
|
||||
$this->gateway = $gateway;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $confirmPassword
|
||||
* @param string $email
|
||||
* @return ValidationFail[]
|
||||
*/
|
||||
public function register(string $username, string $password, string $confirmPassword, string $email): array {
|
||||
$errors = [];
|
||||
|
||||
if ($password != $confirmPassword) {
|
||||
$errors[] = new FieldValidationFail("confirmpassword", "password and password confirmation are not equals");
|
||||
}
|
||||
|
||||
if ($this->gateway->mailExist($email)) {
|
||||
$errors[] = new FieldValidationFail("email", "email already exist");
|
||||
}
|
||||
|
||||
if(empty($errors)) {
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$this->gateway->insertAccount($username, $hash, $email);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
* @return array<string,string>|null
|
||||
*/
|
||||
public function getUserFields(string $email): ?array {
|
||||
return $this->gateway->getUserFields($email);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $email
|
||||
* @param string $password
|
||||
* @return ValidationFail[] $errors
|
||||
*/
|
||||
public function login(string $email, string $password): array {
|
||||
$errors = [];
|
||||
|
||||
if (!$this->gateway->mailExist($email)) {
|
||||
$errors[] = new FieldValidationFail("email", "email doesnt exists");
|
||||
return $errors;
|
||||
}
|
||||
$hash = $this->gateway->getUserHash($email);
|
||||
|
||||
if (!password_verify($password, $hash)) {
|
||||
$errors[] = new FieldValidationFail("password", "invalid password");
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profil Utilisateur</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
background-color: #7FBFFF;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="user-profile">
|
||||
<h1>Votre profil</h1>
|
||||
<p><strong>Pseudo : </strong> {{ username }} </p>
|
||||
<p><strong>Email : {{ email }} </strong></p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,85 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Connexion</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
{% for err in bad_fields %}
|
||||
.form-group #{{ err }} {
|
||||
border-color: red;
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<center><h2>Se connecter</h2></center>
|
||||
<form action="login" method="post">
|
||||
<div class="form-group">
|
||||
<label for="email">Email :</label>
|
||||
<input type="text" id="email" name="email" required>
|
||||
<label for= "password">Mot de passe :</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="S'identifier">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,88 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>S'enregistrer</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
{% for err in bad_fields %}
|
||||
.form-group #{{ err }} {
|
||||
border-color: red;
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<center><h2>S'enregistrer</h2></center>
|
||||
<form action="register" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Nom d'utilisateur :</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
<label for= "password">Mot de passe :</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
<label for="confirmpassword">Confirmer le mot de passe :</label>
|
||||
<input type="password" id="confirmpassword" name="confirmpassword" required>
|
||||
|
||||
<label for="email">Email :</label>
|
||||
<input type="text" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Confirmer">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in new issue