summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-08-11 06:25:39 +0200
committerpolo <ordipolo@gmx.fr>2025-08-11 06:25:39 +0200
commitd7468fc363b5d028db84373d4abfa6d7d19bacb9 (patch)
tree0235e6c7520bb16b939f3e753ccd45c94bfaef28
parent90673ef19133e037cf401773f4262ba3d7d050bf (diff)
downloadcms-d7468fc363b5d028db84373d4abfa6d7d19bacb9.zip
nouveau routeur! et contrôleurs et vues pour la connexion et la gestion du compte, début d'utilisation de Request et Responsemain
-rw-r--r--composer.json3
-rw-r--r--public/assets/user_full.svg22
-rw-r--r--public/assets/user_hollow.svg18
-rw-r--r--public/css/body.css52
-rw-r--r--public/css/form.css14
-rw-r--r--public/index.php65
-rw-r--r--src/Security.php11
-rw-r--r--src/controller/ArticleController.php4
-rw-r--r--src/controller/UserController.php360
-rw-r--r--src/controller/ViewController.php39
-rw-r--r--src/controller/password.php328
-rw-r--r--src/installation.php12
-rw-r--r--src/model/entities/Image.php2
-rw-r--r--src/model/entities/User.php5
-rw-r--r--src/router.php (renamed from src/request_router.php)128
-rw-r--r--src/view/FooterBuilder.php8
-rw-r--r--src/view/LoginBuilder.php41
-rw-r--r--src/view/MainBuilder.php2
-rw-r--r--src/view/UserEditBuilder.php58
-rw-r--r--src/view/ViewBuilder.php18
-rw-r--r--src/view/password.php155
-rw-r--r--src/view/templates/login.php28
-rw-r--r--src/view/templates/user_create.php52
-rw-r--r--src/view/templates/user_edit.php62
24 files changed, 865 insertions, 622 deletions
diff --git a/composer.json b/composer.json
index 12c7202..3ebe29c 100644
--- a/composer.json
+++ b/composer.json
@@ -9,7 +9,8 @@
9 "htmlawed/htmlawed": "^1.2", 9 "htmlawed/htmlawed": "^1.2",
10 "tinymce/tinymce": "^7.7", 10 "tinymce/tinymce": "^7.7",
11 "tweeb/tinymce-i18n": "^2.0", 11 "tweeb/tinymce-i18n": "^2.0",
12 "phpmailer/phpmailer": "^6.10" 12 "phpmailer/phpmailer": "^6.10",
13 "symfony/http-foundation": "^7.3"
13 }, 14 },
14 "scripts": { 15 "scripts": {
15 "post-install-cmd": [ 16 "post-install-cmd": [
diff --git a/public/assets/user_full.svg b/public/assets/user_full.svg
new file mode 100644
index 0000000..b211c67
--- /dev/null
+++ b/public/assets/user_full.svg
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Written by Treer (gitlab.com/Treer) -->
3<svg
4 version="1.1"
5 xmlns="http://www.w3.org/2000/svg"
6 xmlns:xlink="http://www.w3.org/1999/xlink"
7 width="600"
8 height="600"
9 fill="white">
10
11 <title>Abstract user icon</title>
12
13 <defs>
14 <clipPath id="circular-border">
15 <circle cx="300" cy="300" r="250" />
16 </clipPath>
17 </defs>
18
19 <circle cx="300" cy="300" r="280" fill="black" />
20 <circle cx="300" cy="230" r="100" />
21 <circle cx="300" cy="550" r="190" clip-path="url(#circular-border)" />
22</svg> \ No newline at end of file
diff --git a/public/assets/user_hollow.svg b/public/assets/user_hollow.svg
new file mode 100644
index 0000000..ca26d18
--- /dev/null
+++ b/public/assets/user_hollow.svg
@@ -0,0 +1,18 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Written by Treer (gitlab.com/Treer) -->
3<svg
4 version="1.1"
5 xmlns="http://www.w3.org/2000/svg"
6 xmlns:xlink="http://www.w3.org/1999/xlink"
7 width="600"
8 height="600"
9 stroke="black"
10 stroke-width="30"
11 fill="none">
12
13 <title>Abstract user icon</title>
14
15 <circle cx="300" cy="300" r="265" />
16 <circle cx="300" cy="230" r="115" />
17 <path d="M106.81863443903,481.4 a205,205 1 0,1 386.36273112194,0" stroke-linecap="butt" />
18</svg> \ No newline at end of file
diff --git a/public/css/body.css b/public/css/body.css
index a03510f..274627c 100644
--- a/public/css/body.css
+++ b/public/css/body.css
@@ -55,6 +55,13 @@ section > h3
55 margin: 0; 55 margin: 0;
56 text-align: center; 56 text-align: center;
57} 57}
58.login_form
59{
60 background-color: white;
61 margin: 15px;
62 padding: 15px;
63}
64
58.grid_columns 65.grid_columns
59{ 66{
60 display: grid; 67 display: grid;
@@ -181,7 +188,7 @@ button .action_icon:hover
181 display: flex; 188 display: flex;
182 justify-content: end; 189 justify-content: end;
183} 190}
184section button 191section button, section input[type=submit]
185{ 192{
186 color: #ff1d04; 193 color: #ff1d04;
187 font-size: medium; 194 font-size: medium;
@@ -189,7 +196,7 @@ section button
189 background-color: white; 196 background-color: white;
190 border: lightgrey 2px outset; /* rend identiques les boutons firefox et chromium */ 197 border: lightgrey 2px outset; /* rend identiques les boutons firefox et chromium */
191} 198}
192section button:hover 199section button:hover, section input[type=submit]:hover
193{ 200{
194 background-color: yellow; 201 background-color: yellow;
195 border-radius: 4px; 202 border-radius: 4px;
@@ -199,4 +206,45 @@ section button:hover
199article a:hover 206article a:hover
200{ 207{
201 cursor: pointer; 208 cursor: pointer;
209}
210
211.user_edit_header
212{
213 /*display: flex;
214 justify-content: space-evenly;
215 align-items: center;*/
216 display: grid;
217 grid-template-columns: repeat(3, 1fr);
218 text-align: center;
219 padding: 15px;
220}
221.user_icon
222{
223 height: 36px;
224}
225.user_edit_flex
226{
227 /*display: flex;
228 flex-wrap: wrap;
229 justify-content: space-between;*/
230 display: grid;
231 grid-template-columns: repeat(2, 1fr);
232}
233@media screen and (max-width: 900px)
234{
235 .user_edit_flex
236 {
237 display: block;
238 }
239}
240@media screen and (max-width: 500px)
241{
242 .empty_column
243 {
244 display: none;
245 }
246 .user_edit_header
247 {
248 grid-template-columns: repeat(2, 1fr);
249 }
202} \ No newline at end of file 250} \ No newline at end of file
diff --git a/public/css/form.css b/public/css/form.css
index 84c73ac..5bfa768 100644
--- a/public/css/form.css
+++ b/public/css/form.css
@@ -14,20 +14,6 @@
14.form .full_width_column{ 14.form .full_width_column{
15 grid-column: 1 / span 2; 15 grid-column: 1 / span 2;
16} 16}
17.form_inputs input[type=submit]
18{
19 color: #ff1d04;
20 font-size: medium;
21 border-radius: 4px;
22 background-color: white;
23 border: lightgrey 2px outset;
24}
25.form_inputs input[type=submit]:hover
26{
27 background-color: yellow;
28 border-radius: 4px;
29 cursor: pointer;
30}
31 17
32.no_recipient_warning{ 18.no_recipient_warning{
33 color: red; 19 color: red;
diff --git a/public/index.php b/public/index.php
index b7eeeae..89bb203 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,10 +1,24 @@
1<?php 1<?php
2// public/index/php 2// public/index/php
3 3
4/* plan d'action pour symfonyfier le site
51/ intégrer les classes Request et Response sans changer modifier les liens
62/ méthodes HTTP: GET, HEAD, POST, PUT, PATCH, DELETE, etc, pour un pré-routage (légères modifications des liens)
73/ passer à des chemins modernes "ciblant des ressources" genre /chemin/de/la/page
8 le mode modification de page doit thérioquement être appelé comme ça: /chemin/de/la/page/modif_page
9 apparemment, le from=nom_page pour les formulaires ne se fait pas...
104/ utiliser le routeur de symfony: nécéssite que tous les contrôleurs soient des classes avec un namespace
115/ http-foundation possède aussi une classe Session. intéressant!
12*/
13
4declare(strict_types=1); 14declare(strict_types=1);
5 15
16use Symfony\Component\HttpFoundation\Request;
17//use Symfony\Component\HttpFoundation\Session\Session;
18
6 19
7/* -- partie 1: prétraitement -- */ 20/* -- partie 1: prétraitement --
21code à exécuter pour toutes requêtes */
8 22
9// une nouvelle classe? taper: composer dump-autoload -o 23// une nouvelle classe? taper: composer dump-autoload -o
10require "../vendor/autoload.php"; 24require "../vendor/autoload.php";
@@ -12,6 +26,11 @@ require "../vendor/autoload.php";
12// configuration possible par l'utilisateur 26// configuration possible par l'utilisateur
13Config::load('../config/config.ini'); 27Config::load('../config/config.ini');
14 28
29// générateur de liens
30URL::setProtocol(Config::$protocol); // utile si port autre que 80 ou 443
31URL::setPort(Config::$port);
32URL::setHost($_SERVER['HTTP_HOST'] . Config::$index_path);
33
15// les messages d'erreur de déploiement qu'on aime 34// les messages d'erreur de déploiement qu'on aime
16require('../src/installation.php'); 35require('../src/installation.php');
17phpDependancies(); 36phpDependancies();
@@ -20,13 +39,10 @@ phpDependancies();
20// $entityManager 39// $entityManager
21require '../src/model/doctrine-bootstrap.php'; // isDevMode est sur "true", DSN à adapter 40require '../src/model/doctrine-bootstrap.php'; // isDevMode est sur "true", DSN à adapter
22 41
23// générateur de liens 42$request = Request::createFromGlobals();
24URL::setProtocol(Config::$protocol); // utile si port autre que 80 ou 443
25URL::setPort(Config::$port);
26URL::setHost($_SERVER['HTTP_HOST'] . Config::$index_path);
27 43
28// session 44// session
29//require('controller/Session.php'); 45// (symfony/http-foundation pourrait nous aider avec les sessions)
30ini_set('session.cookie_samesite', 'Strict'); 46ini_set('session.cookie_samesite', 'Strict');
31ini_set('session.cookie_httponly', 'On'); 47ini_set('session.cookie_httponly', 'On');
32ini_set('session.use_strict_mode', 'On'); 48ini_set('session.use_strict_mode', 'On');
@@ -38,39 +54,8 @@ if($_SESSION['admin'] === false || empty($_SESSION['user'])){ // OUT !!
38 $_SESSION['admin'] = false; 54 $_SESSION['admin'] = false;
39} 55}
40 56
41// login, mot de passe et captcha
42require '../src/controller/password.php';
43existUsers($entityManager); // si la table user est vide, on en crée un
44
45
46/* -- partie 2: contrôleurs -- */
47
48// navigation avec des GET
49define('CURRENT_PAGE', !empty($_GET['page']) ? htmlspecialchars($_GET['page']) : 'accueil');
50$id = '';
51if(!empty($_GET['id']))
52{
53 $id = htmlspecialchars($_GET['id']); // nettoyage qui n'abime pas les id du genre "n16"
54}
55
56/* -- routeur des données de formulaires et requêtes AJAX -- */
57require '../src/request_router.php';
58
59
60/* -- affichage d'une page -- */
61// mode modification d'une page activé
62if($_SESSION['admin'] && isset($_GET['page']) && isset($_GET['action']) && $_GET['action'] === 'modif_page'
63 && $_GET['page'] !== 'connexion' && $_GET['page'] !== 'article' && $_GET['page'] !== 'nouvelle_page' && $_GET['page'] !== 'menu_chemins')
64{
65 // les contrôles de la 2è ligne devraient utiliser un tableau
66 MainBuilder::$modif_mode = true;
67}
68 57
69// contrôleur accédant au modèle 58/* -- partie 2: routage et contrôleurs -- */
70$director = new Director($entityManager, true);
71$director->makeRootNode($id);
72$node = $director->getNode();
73 59
74// contrôleur principal des vues 60define('CURRENT_PAGE', htmlspecialchars($request->query->get('page') ?? 'accueil'));
75$view_builder = new ViewBuilder($node); 61require '../src/router.php'; \ No newline at end of file
76echo $view_builder->render(); // et voilà! \ No newline at end of file
diff --git a/src/Security.php b/src/Security.php
index b2042fd..c825994 100644
--- a/src/Security.php
+++ b/src/Security.php
@@ -19,8 +19,8 @@ class Security
19 // faire qu'un certain élément puisse n'avoir que certains attributs, regarder la doc 19 // faire qu'un certain élément puisse n'avoir que certains attributs, regarder la doc
20 private static $specHtmLawed = ''; 20 private static $specHtmLawed = '';
21 21
22 // ATTENTION, n'applique pas htmlspecialchars() !! 22 // obtenir du HTML non dangereur sans appliquer htmlspecialchars
23 public static function secureString(string $chaine): string 23 public static function secureHTML(string $chaine): string
24 { 24 {
25 return trim(htmLawed($chaine, self::$configHtmLawed, self::$specHtmLawed)); 25 return trim(htmLawed($chaine, self::$configHtmLawed, self::$specHtmLawed));
26 } 26 }
@@ -80,13 +80,6 @@ class Security
80 } 80 }
81} 81}
82 82
83// erreurs à la création des mots de passe
84function removeSpacesTabsCRLF(string $chaine): string
85{
86 $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !!
87 return(str_replace($cibles, '', $chaine));
88}
89
90// lien sans http:// 83// lien sans http://
91function fixLinks($data) 84function fixLinks($data)
92{ 85{
diff --git a/src/controller/ArticleController.php b/src/controller/ArticleController.php
index e3e4edb..3b39335 100644
--- a/src/controller/ArticleController.php
+++ b/src/controller/ArticleController.php
@@ -19,12 +19,12 @@ class ArticleController
19 // cas d'une nouvelle "news" 19 // cas d'une nouvelle "news"
20 if(is_array($json['content'])){ 20 if(is_array($json['content'])){
21 foreach($json['content'] as $one_input){ 21 foreach($json['content'] as $one_input){
22 $one_input = Security::secureString($one_input); 22 $one_input = Security::secureHTML($one_input);
23 } 23 }
24 $content = $json['content']; 24 $content = $json['content'];
25 } 25 }
26 else{ 26 else{
27 $content = Security::secureString($json['content']); 27 $content = Security::secureHTML($json['content']);
28 } 28 }
29 29
30 // nouvel article 30 // nouvel article
diff --git a/src/controller/UserController.php b/src/controller/UserController.php
new file mode 100644
index 0000000..50e8bf7
--- /dev/null
+++ b/src/controller/UserController.php
@@ -0,0 +1,360 @@
1<?php
2// src/controller/PasswordController.php
3//
4// test mot de passe et captcha
5
6declare(strict_types=1);
7
8use Doctrine\ORM\EntityManager;
9use App\Entity\User;
10use App\Entity\Log;
11
12class UserController
13{
14 static public function existUsers(EntityManager $entityManager): bool
15 {
16 // optimiser ça si possible, on veut juste savoir si la table est vide ou non
17 $users = $entityManager->getRepository(User::class)->findAll();
18
19 if(count($users) === 0) // table vide
20 {
21 $_SESSION['user'] = '';
22 $_SESSION['admin'] = false;
23
24 return false;
25 }
26 else{
27 return true;
28 }
29 }
30
31 static public function createUser(EntityManager $entityManager)
32 {
33 // test mauvais paramètres
34 if(!isset($_POST['login']) || empty($_POST['login'])
35 || !isset($_POST['password']) || empty($_POST['password'])
36 || !isset($_POST['password_confirmation']) || empty($_POST['password_confirmation'])
37 || !isset($_POST['create_user_hidden']) || !empty($_POST['create_user_hidden']))
38 {
39 header('Location: ' . new URL);
40 die;
41 }
42
43 unset($_SESSION['user']);
44
45 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
46 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
47 unset($_SESSION['captcha']);
48
49 $error = '';
50 if($captcha_try == 0)
51 {
52 $error = 'error_non_valid_captcha';
53 }
54 elseif($captcha_solution == 0) // ne peut pas arriver, si?
55 {
56 $error = 'captcha_server_error';
57 }
58 elseif($captcha_try != $captcha_solution) // le test!
59 {
60 $error = 'bad_solution_captcha';
61 }
62 elseif($_POST['password'] !== $_POST['password_confirmation'])
63 {
64 $error = 'different_passwords';
65 }
66 else
67 {
68 $login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['login']));
69 $password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['password']));
70
71 // self::removeSpacesTabsCRLF prévient la validation par erreur d'une chaine "vide"
72
73 // conformité
74 if(!empty($password) && !empty($login)
75 && $password === $_POST['password'] && $login === $_POST['login'])
76 {
77 // enregistrement et redirection
78 $password = password_hash($password, PASSWORD_DEFAULT);
79 $user = new App\Entity\User($login, $password);
80 $entityManager->persist($user);
81 $entityManager->flush();
82
83 header('Location: ' . new URL);
84 die;
85 }
86 else{
87 $error = 'forbidden_characters';
88 }
89 }
90
91 $url = empty($error) ? new URL : new URL(['error' => $error]);
92 header('Location: ' . $url);
93 die;
94 }
95
96 static public function connect(EntityManager $entityManager): void
97 {
98 if($_SESSION['admin']) // déjà connecté?
99 {
100 header('Location: ' . new URL);
101 die;
102 }
103
104 $_SESSION['user'] = '';
105 $_SESSION['admin'] = false;
106
107 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
108 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
109 unset($_SESSION['captcha']);
110
111 $error = '';
112 if($captcha_try == 0)
113 {
114 $error = 'error_non_valid_captcha';
115 }
116 elseif($captcha_solution == 0) // pas censé se produire
117 {
118 $error = 'captcha_server_error';
119 }
120 elseif($captcha_try != $captcha_solution) // le test!
121 {
122 $error = 'bad_solution_captcha';
123 }
124 elseif(!isset($_POST['login']) || empty($_POST['login'])
125 || !isset($_POST['password']) || empty($_POST['password']))
126 {
127 $error = 'bad_login_or_password';
128 }
129 else // c'est OK
130 {
131 $login = trim($_POST['login']);
132 $password = trim($_POST['password']);
133 $user = self::getUser($login, $entityManager);
134
135 // enregistrement et redirection
136 if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword()))
137 {
138 $log = new Log(true);
139 $entityManager->persist($log);
140 $entityManager->flush();
141
142 // protection fixation de session, si l'attaquant crée un cookie de session, il est remplacé
143 session_regenerate_id(true);
144
145 $_SESSION['user'] = $login;
146 $_SESSION['admin'] = true;
147
148 $url = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []);
149 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
150 header('Location: ' . $url);
151 die;
152 }
153 else
154 {
155 $log = new Log(false);
156 $entityManager->persist($log);
157 $entityManager->flush();
158 $error = 'bad_login_or_password';
159 }
160 }
161
162 // tous les cas sauf connexion réussie
163 sleep(1); // défense basique à la force brute
164 $url = new URL(isset($_GET['from']) ? ['page' => 'connexion', 'from' => $_GET['from']] : []);
165 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
166 !empty($error) ? $url->addParams(['error' => $error]) : '';
167 header('Location: ' . $url);
168 die;
169 }
170
171 static public function disconnect(): void
172 {
173 // nettoyage complet
174 $_SESSION = []; // mémoire vive
175 session_destroy(); // fichier côté serveur
176 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
177
178 // retour même page
179 $url = new URL;
180 isset($_GET['from']) ? $url->addParams(['page' => $_GET['from']]) : '';
181 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
182 header('Location: ' . $url);
183 die;
184 }
185
186 static public function updateUsername(EntityManager $entityManager): void
187 {
188 if(!$_SESSION['admin']) // superflux, fait dans le routeur
189 {
190 self::disconnect();
191 }
192
193 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
194 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
195 unset($_SESSION['captcha']);
196
197 $url = new URL(['page' => 'user_edit']);
198 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
199
200 $error = '';
201 if(!isset($_POST['old_login']) || empty($_POST['old_login'])
202 || !isset($_POST['password']) || empty($_POST['password'])
203 || !isset($_POST['new_login']) || empty($_POST['new_login'])
204 || !isset($_POST['modify_username_hidden']) || !empty($_POST['modify_username_hidden']))
205 {
206 $error = 'bad_login_or_password';
207 }
208 elseif($captcha_try != $captcha_solution) // le test!
209 {
210 $error = 'bad_solution_captcha';
211 }
212 else
213 {
214 // sécurisation de la saisie
215 $old_login = $_POST['old_login'];
216 $password = $_POST['password'];
217 $new_login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_login']));
218 // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide
219
220 // tests de conformité
221 if($old_login !== $_POST['old_login'] || $password !== $_POST['password'] || $new_login !== $_POST['new_login'])
222 {
223 $error = 'forbidden_characters';
224 }
225 elseif($old_login !== $_SESSION['user']){
226 $error = 'bad_login_or_password';
227 }
228 elseif($old_login === $new_login){
229 $error = 'same_username_as_before';
230 }
231 else
232 {
233 $user = self::getUser($old_login, $entityManager);
234
235 if(password_verify($password, $user->getPassword()))
236 {
237 $user->setLogin($new_login);
238 $entityManager->flush();
239 $_SESSION['user'] = $new_login;
240
241 $url->addParams(['success_login' => 'new_login']);
242 $error = '';
243 }
244 else
245 {
246 $error = 'bad_login_or_password';
247 }
248 }
249 }
250
251 if(!empty($error)){
252 sleep(1);
253 $url->addParams(['error_login' => $error]);
254 }
255
256 header('Location: ' . $url);
257 die;
258 }
259
260 static public function updatePassword(EntityManager $entityManager): void
261 {
262 if(!$_SESSION['admin']) // superflux, fait dans le routeur
263 {
264 self::disconnect();
265 }
266
267 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
268 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
269 unset($_SESSION['captcha']);
270
271 $url = new URL(['page' => 'user_edit']);
272 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
273
274 $error = '';
275 if(!isset($_POST['login']) || empty($_POST['login'])
276 || !isset($_POST['old_password']) || empty($_POST['old_password'])
277 || !isset($_POST['new_password']) || empty($_POST['new_password'])
278 || !isset($_POST['modify_password_hidden']) || !empty($_POST['modify_password_hidden']))
279 {
280 $error = 'bad_login_or_password';
281 }
282 elseif($captcha_try != $captcha_solution) // le test!
283 {
284 $error = 'bad_solution_captcha';
285 }
286 else
287 {
288 // sécurisation de la saisie
289 $login = $_POST['login'];
290 $old_password = $_POST['old_password'];
291 $new_password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_password']));
292 // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide
293
294 // tests de conformité
295 if($login !== $_POST['login'] || $old_password !== $_POST['old_password'] || $new_password !== $_POST['new_password'])
296 {
297 $error = 'forbidden_characters';
298 }
299 elseif($login !== $_SESSION['user']){
300 $error = 'bad_login_or_password';
301 }
302 elseif($old_password === $new_password){
303 $error = 'same_password_as_before';
304 }
305 else
306 {
307 $user = self::getUser($login, $entityManager);
308
309 if(password_verify($old_password, $user->getPassword()))
310 {
311 $new_password = password_hash($new_password, PASSWORD_DEFAULT);
312 $user->setPassword($new_password);
313 $entityManager->flush();
314
315 $url->addParams(['success_password' => 'new_password']);
316 $error = '';
317 }
318 else
319 {
320 $error = 'bad_login_or_password';
321 }
322 }
323 }
324
325 if(!empty($error)){
326 sleep(1);
327 $url->addParams(['error_password' => $error]);
328 }
329
330 header('Location: ' . $url);
331 die;
332 }
333
334 static private function getUser(string $login, EntityManager $entityManager): ?User
335 {
336 $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]);
337
338 if(count($users) === 0)
339 {
340 $_SESSION['user'] = '';
341 $_SESSION['admin'] = false;
342 }
343
344 foreach($users as $user)
345 {
346 if($user->getLogin() === $login)
347 {
348 return $user;
349 }
350 }
351 return null;
352 }
353
354 // erreurs à la création des mots de passe
355 static private function removeSpacesTabsCRLF(string $chaine): string
356 {
357 $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !!
358 return(str_replace($cibles, '', $chaine));
359 }
360} \ No newline at end of file
diff --git a/src/controller/ViewController.php b/src/controller/ViewController.php
new file mode 100644
index 0000000..69955c6
--- /dev/null
+++ b/src/controller/ViewController.php
@@ -0,0 +1,39 @@
1<?php
2// src/view/ViewController.php
3//
4// génère le HTML avec des Builder
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9use Doctrine\ORM\EntityManager;
10use Symfony\Component\HttpFoundation\Request;
11use Symfony\Component\HttpFoundation\Response;
12
13class ViewController extends AbstractBuilder
14{
15 static public Node $root_node;
16
17 public function __construct(){}
18
19 public function buildView(Request $request, EntityManager $entityManager): Response
20 {
21 // accès au modèle
22 $director = new Director($entityManager, true);
23 $director->makeRootNode(htmlspecialchars($request->query->get('id') ?? ''));
24 self::$root_node = $director->getNode();
25
26 // mode modification d'une page activé
27 if($_SESSION['admin'] && $request->query->has('page')
28 && $request->query->has('action') && $request->query->get('action') === 'modif_page'
29 && $request->query->get('page') !== 'connexion' && $request->query->get('page') !== 'article' && $request->query->get('page') !== 'nouvelle_page' && $request->query->get('page') !== 'menu_chemins'){
30 // les contrôles de la 2è ligne devraient utiliser un tableau
31 MainBuilder::$modif_mode = true;
32 }
33
34 // construction de la page
35 $this->useChildrenBuilder(self::$root_node);
36
37 return new Response($this->html, 200);
38 }
39} \ No newline at end of file
diff --git a/src/controller/password.php b/src/controller/password.php
deleted file mode 100644
index 3d003da..0000000
--- a/src/controller/password.php
+++ /dev/null
@@ -1,328 +0,0 @@
1<?php
2// src/controller/password.php
3//
4// test mot de passe et captcha
5
6declare(strict_types=1);
7
8use Doctrine\ORM\EntityManager;
9use App\Entity\User;
10use App\Entity\Log;
11
12// exécutée dans installation.php à l'ouverture de chaque page
13function existUsers(EntityManager $entityManager)
14{
15 // lecture
16 $users = $entityManager->getRepository(User::class)->findAll();
17
18 // cas particulier table vide
19 if(count($users) === 0)
20 {
21 $_GET = [];
22 $_SESSION['user'] = '';
23 $_SESSION['admin'] = false;
24
25 // création d'un utilisateur, puis rechargement de la page
26 createPassword($entityManager);
27 }
28}
29
30
31function createPassword(EntityManager $entityManager)
32{
33 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie
34
35 unset($_SESSION['user']);
36
37 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
38 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
39
40 // II - traitement
41 $error = '';
42 if(!isset($_POST['captcha'])) // page création d'un compte rechargée
43 {
44 //$error = '';
45 }
46 elseif($captcha_try == 0)
47 {
48 $error = 'error_non_valid_captcha';
49 }
50 elseif($captcha_solution == 0)
51 {
52 //$error = '';
53 }
54 elseif($captcha_try != $captcha_solution) // le test!
55 {
56 $error = 'bad_solution_captcha';
57 }
58 elseif(!isset($_POST['password']) || empty($_POST['password'])
59 || (!isset($_POST['login']) || empty($_POST['login'])))
60 {
61 $error = 'bad_login_or_password';
62 }
63 else
64 {
65 $login = Security::secureString($_POST['login']);
66 $password = Security::secureString($_POST['password']);
67
68 // -> prévenir la validation par erreur d'une chaine "vide"
69 $login = removeSpacesTabsCRLF($login);
70 $password = removeSpacesTabsCRLF($password);
71
72 // conformité
73 if(isset($password) && isset($login)
74 && $password == $_POST['password'] && $login == $_POST['login'])
75 {
76 unset($_SESSION['captcha']);
77
78 // enregistrement et redirection
79 $password = password_hash($password, PASSWORD_DEFAULT);
80 $user = new App\Entity\User($login, $password);
81 $entityManager->persist($user);
82 $entityManager->flush();
83
84 header('Location: ' . new URL);
85 exit();
86 }
87 else
88 {
89 $error = 'bad_login_or_password';
90
91 // compteur dans la session et blocage de compte
92 }
93 }
94
95 // inséré dans $captchaHtml puis dans $formulaireNouveauMDP
96 $captcha = new Captcha;
97 // enregistrement de la réponse du captcha pour vérification
98 $_SESSION['captcha'] = $captcha->getSolution();
99
100
101 // I - affichage
102 $title = 'Bienvenue nageur bigouden';
103 $subHeading = 'Veuillez choisir les codes que vous utiliserez pour gérer le site.';
104
105 // même vue que la fonction changerMotDePasse()
106 require('../src/view/password.php');
107
108 echo($header);
109 if($error != '')
110 {
111 sleep(1);
112 echo($error_messages[$error]);
113 }
114 echo($formulaireNouveauMDP);
115 echo($error_messages['forbidden_characters']);
116 echo($footer);
117 die;
118}
119
120
121function connect(LoginBuilder $builder, EntityManager $entityManager)
122{
123 // déjà connecté
124 if($_SESSION['admin'])
125 {
126 header('Location: ' . new URL);
127 die;
128 }
129
130 // II - traitement
131 $_SESSION['user'] = '';
132 $_SESSION['admin'] = false;
133
134 $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0;
135 $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0;
136
137 $error = '';
138 if(!isset($_POST['captcha'])) // page rechargée
139 {
140 //$error = '';
141 }
142 elseif($captcha_try == 0)
143 {
144 $error = 'error_non_valid_captcha';
145 }
146 elseif($captcha_solution == 0)
147 {
148 //$error = '';
149 }
150 elseif($captcha_try != $captcha_solution) // le test!
151 {
152 $error = 'bad_solution_captcha';
153 }
154 elseif(!isset($_POST['login']) || empty($_POST['login'])
155 || !isset($_POST['password']) || empty($_POST['password']))
156 {
157 $error = 'bad_login_or_password';
158 }
159 else // c'est OK
160 {
161 $login = Security::secureString($_POST['login']);
162 $password = Security::secureString($_POST['password']);
163 $user = getUser($login, $entityManager);
164
165 // enregistrement et redirection
166 if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword()))
167 {
168 $log = new Log(true);
169 $entityManager->persist($log);
170 $entityManager->flush();
171
172 session_regenerate_id(true); // protection fixation de session, si l'attaquant a créé un cookie de session (attaque XSS), il est remplacé
173 //unset($_SESSION['captcha']);
174 $_SESSION['user'] = $login;
175 $_SESSION['admin'] = true;
176 $link = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []);
177 isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
178 header('Location: ' . $link);
179 die;
180 }
181 else
182 {
183 $log = new Log(false);
184 $entityManager->persist($log);
185 $entityManager->flush();
186 $error = 'bad_login_or_password';
187 }
188 }
189
190 // inséré dans $captchaHtml puis dans $formulaireNouveauMDP
191 $captcha = new Captcha;
192 // enregistrement de la réponse du captcha pour vérification
193 $_SESSION['captcha'] = $captcha->getSolution(); // int
194
195 // I - affichage
196 $title = "Connexion";
197 $subHeading = "Veuillez saisir votre identifiant (e-mail) et votre mot de passe.";
198
199 require('../src/view/password.php');
200
201 //$builder->addHTML($header);
202 if($error != '')
203 {
204 sleep(1);
205 $builder->addHTML($error_messages[$error]);
206 }
207 $builder->addHTML($formulaireConnexion);
208 //$builder->addHTML($warning_messages['message_cookie']);
209 $builder->addHTML($warning_messages['private_browsing']);
210 $builder->addHTML($footer);
211
212 //die;
213}
214
215
216function changePassword(EntityManager $entityManager): void
217{
218 // fonction exécutée à priori deux fois d'affilée: affichage puis traitement de la saisie
219
220 // II - traitement
221 $error = '';
222 $success = false;
223 if(empty($_POST)) // première fois ou page rechargée
224 {
225 //
226 }
227 elseif(!isset($_POST['login']) || empty($_POST['login'])
228 || !isset($_POST['old_password']) || empty($_POST['old_password'])
229 || !isset($_POST['new_password']) || empty($_POST['new_password'])
230 || !isset($_POST['modify_password_hidden']) || !empty($_POST['modify_password_hidden']))
231 {
232 $error = 'bad_login_or_password';
233 }
234 else
235 {
236 // sécurisation de la saisie
237 $new_password = Security::secureString($_POST['new_password']);
238 $login = Security::secureString($_POST['login']);
239 $old_password = Security::secureString($_POST['old_password']);
240
241 // éviter d'enregistrer une chaîne vide
242 $new_password = removeSpacesTabsCRLF($new_password);
243
244 // tests de conformité
245 if($login != $_POST['login'] || $old_password != $_POST['old_password'] || $new_password != $_POST['new_password'])
246 {
247 $error = 'forbidden_characters';
248 }
249 elseif($login !== $_SESSION['user']){
250 $error = 'bad_login_or_password';
251 }
252 else
253 {
254 $user = getUser($login, $entityManager);
255
256 if(password_verify($old_password, $user->getPassword()))
257 {
258 // enregistrement et redirection
259 $new_password = password_hash($new_password, PASSWORD_DEFAULT);
260 $user->setPassword($new_password);
261 $entityManager->flush();
262 $success = true;
263 }
264 else
265 {
266 $error = 'bad_login_or_password';
267 }
268 }
269 }
270
271
272 // I - affichage
273 $title = "Nouveau mot de passe";
274 $subHeading = "Veuillez vous identifier à nouveau puis saisir votre nouveau mot de passe.";
275
276 require('../src/view/password.php');
277
278 echo($header);
279 if($error != '')
280 {
281 sleep(1); // sécurité TRÈS insuffisante à la force brute
282 echo($error_messages[$error]);
283 }
284 elseif($success)
285 {
286 $success = false;
287 echo($alertJSNewPassword);
288 //header("Location: " . new URL(['page' => $_GET['from']])); // choisir "location" entre PHP et JS
289 die;
290 }
291 echo($formulaireModifMDP);
292 echo($footer);
293 die;
294}
295
296
297function getUser(string $login, EntityManager $entityManager): ?User
298{
299 $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]);
300
301 if(count($users) === 0)
302 {
303 $_SESSION['user'] = '';
304 $_SESSION['admin'] = false;
305 }
306
307 foreach($users as $user)
308 {
309 if($user->getLogin() === $login)
310 {
311 return $user;
312 }
313 }
314 return null;
315}
316
317
318function disconnect()
319{
320 // nettoyage complet
321 $_SESSION = []; // mémoire vive
322 session_destroy(); // fichier côté serveur
323 setcookie('PHPSESSID', '', time() - 4200, '/'); // cookie de session
324 $link = new URL(['page' => $_GET['page']]);
325 isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
326 header('Location: ' . $link);
327 die;
328} \ No newline at end of file
diff --git a/src/installation.php b/src/installation.php
index 295c583..eaf2181 100644
--- a/src/installation.php
+++ b/src/installation.php
@@ -92,7 +92,8 @@ function makeStartPage(EntityManager $entityManager){
92 // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent 92 // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent
93 $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL); 93 $accueil = new Page('Accueil', 'accueil', true, true, false, 1, NULL);
94 $article = new Page('Article', 'article', true, false, false, NULL, NULL); 94 $article = new Page('Article', 'article', true, false, false, NULL, NULL);
95 $connection = new Page('Connexion', 'connexion', true, false, false, NULL, NULL); 95 $connection = new Page('Connexion', 'connection', true, false, false, NULL, NULL);
96 $my_account = new Page('Mon compte', 'user_edit', true, false, false, NULL, NULL);
96 $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL); 97 $menu_paths = new Page("Menu et chemins", 'menu_chemins', true, false, false, NULL, NULL);
97 //$edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); // pas de page "Modification de la page" 98 //$edit_page = new Page("Modification d'une page", 'modif_page', true, false, false, NULL, NULL); // pas de page "Modification de la page"
98 $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL); 99 $new_page = new Page('Nouvelle page', 'nouvelle_page', true, false, false, NULL, NULL);
@@ -108,6 +109,8 @@ function makeStartPage(EntityManager $entityManager){
108 $breadcrumb = new Node('breadcrumb', NULL, [], 2, $header, NULL, NULL); 109 $breadcrumb = new Node('breadcrumb', NULL, [], 2, $header, NULL, NULL);
109 $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $connection, NULL); 110 $head_login = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $connection, NULL);
110 $login = new Node('login', NULL, [], 1, $main, $connection, NULL); 111 $login = new Node('login', NULL, [], 1, $main, $connection, NULL);
112 $head_my_account = new Node('head', NULL, ["stop" => true, 'css_array' => ['body', 'head', 'nav'], 'js_array' => ['main']], 1, NULL, $my_account, NULL);
113 $user_edit = new Node('user_edit', NULL, [], 1, $main, $my_account, NULL);
111 $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL); 114 $head_edit_menu = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'menu', 'foot'], 'js_array' => ['main', 'menu']], 1, NULL, $menu_paths, NULL);
112 $bloc_edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL); 115 $bloc_edit_menu = new Node('menu', NULL, [], 1, $main, $menu_paths, NULL);
113 $head_new_page = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'new_page', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL); 116 $head_new_page = new Node('head', NULL, ['css_array' => ['body', 'head', 'nav', 'new_page', 'foot'], 'js_array' => ['main', 'new_page']], 1, NULL, $new_page, NULL);
@@ -123,8 +126,9 @@ function makeStartPage(EntityManager $entityManager){
123 126
124 /* -- table node_data -- */ 127 /* -- table node_data -- */
125 // paramètres: data, node, images 128 // paramètres: data, node, images
126 $head_accueil_data = new NodeData(["description" => "page d'accueil"], $head_accueil, new ArrayCollection([$favicon])); 129 $head_accueil_data = new NodeData(["description" => "Page d'accueil"], $head_accueil, new ArrayCollection([$favicon]));
127 $head_login_data = new NodeData(["description" => "Connexion"], $head_login, new ArrayCollection([$favicon])); 130 $head_login_data = new NodeData(["description" => "Connexion"], $head_login, new ArrayCollection([$favicon]));
131 $head_my_account_data = new NodeData(["description" => "Mon compte"], $head_my_account, new ArrayCollection([$favicon]));
128 $head_article_data = new NodeData(["description" => ""], $head_article, new ArrayCollection([$favicon])); 132 $head_article_data = new NodeData(["description" => ""], $head_article, new ArrayCollection([$favicon]));
129 $head_edit_menu_data = new NodeData(["description" => "Menu et chemins"], $head_edit_menu, new ArrayCollection([$favicon])); 133 $head_edit_menu_data = new NodeData(["description" => "Menu et chemins"], $head_edit_menu, new ArrayCollection([$favicon]));
130 $head_new_page_data = new NodeData(["description" => "Nouvelle page"], $head_new_page, new ArrayCollection([$favicon])); 134 $head_new_page_data = new NodeData(["description" => "Nouvelle page"], $head_new_page, new ArrayCollection([$favicon]));
@@ -137,6 +141,7 @@ function makeStartPage(EntityManager $entityManager){
137 $entityManager->persist($accueil); 141 $entityManager->persist($accueil);
138 $entityManager->persist($article); 142 $entityManager->persist($article);
139 $entityManager->persist($connection); 143 $entityManager->persist($connection);
144 $entityManager->persist($my_account);
140 $entityManager->persist($menu_paths); 145 $entityManager->persist($menu_paths);
141 //$entityManager->persist($edit_page); // pas de page "Modification de la page" 146 //$entityManager->persist($edit_page); // pas de page "Modification de la page"
142 $entityManager->persist($new_page); 147 $entityManager->persist($new_page);
@@ -150,6 +155,8 @@ function makeStartPage(EntityManager $entityManager){
150 $entityManager->persist($breadcrumb); 155 $entityManager->persist($breadcrumb);
151 $entityManager->persist($head_login); 156 $entityManager->persist($head_login);
152 $entityManager->persist($login); 157 $entityManager->persist($login);
158 $entityManager->persist($head_my_account);
159 $entityManager->persist($user_edit);
153 $entityManager->persist($head_article); 160 $entityManager->persist($head_article);
154 $entityManager->persist($head_edit_menu); 161 $entityManager->persist($head_edit_menu);
155 $entityManager->persist($bloc_edit_menu); 162 $entityManager->persist($bloc_edit_menu);
@@ -168,6 +175,7 @@ function makeStartPage(EntityManager $entityManager){
168 $entityManager->persist($header_data); 175 $entityManager->persist($header_data);
169 $entityManager->persist($footer_data); 176 $entityManager->persist($footer_data);
170 $entityManager->persist($head_login_data); 177 $entityManager->persist($head_login_data);
178 $entityManager->persist($head_my_account_data);
171 $entityManager->persist($head_article_data); 179 $entityManager->persist($head_article_data);
172 $entityManager->persist($head_edit_menu_data); 180 $entityManager->persist($head_edit_menu_data);
173 $entityManager->persist($head_new_page_data); 181 $entityManager->persist($head_new_page_data);
diff --git a/src/model/entities/Image.php b/src/model/entities/Image.php
index 181c137..302a27f 100644
--- a/src/model/entities/Image.php
+++ b/src/model/entities/Image.php
@@ -74,7 +74,7 @@ class Image
74 } 74 }
75 75
76 76
77 // pour ViewBuilder? 77 // pour ViewBuilderController?
78 /*public function displayImage($imageId): void 78 /*public function displayImage($imageId): void
79 { 79 {
80 //$imageId = 1; // Exemple d'ID d'image 80 //$imageId = 1; // Exemple d'ID d'image
diff --git a/src/model/entities/User.php b/src/model/entities/User.php
index 4b1dcb8..26802e2 100644
--- a/src/model/entities/User.php
+++ b/src/model/entities/User.php
@@ -35,11 +35,14 @@ class User
35 { 35 {
36 return $this->login; 36 return $this->login;
37 } 37 }
38 public function setLogin(string $login): void
39 {
40 $this->login = $login;
41 }
38 public function getPassword(): string 42 public function getPassword(): string
39 { 43 {
40 return $this->password; 44 return $this->password;
41 } 45 }
42
43 public function setPassword(string $password): void 46 public function setPassword(string $password): void
44 { 47 {
45 $this->password = $password; 48 $this->password = $password;
diff --git a/src/request_router.php b/src/router.php
index 0b31755..19fe1c1 100644
--- a/src/request_router.php
+++ b/src/router.php
@@ -1,30 +1,59 @@
1<?php 1<?php
2// src/request_router.php 2// src/router.php
3// 3//
4// routage des requêtes des formulaires et AJAX 4/* fonctionnement du routeur
5// n'utilisent que des POST à l'exception d'un GET par fullcalendar 5=> 1er test, méthode http: GET, POST ou autre chose
6// les contrôleurs des formulaires sont appelés ici, 6=> 2ème test, type de contenu (méthode POST uniquement):
7// ceux des requêtes AJAX sont derrière d'autres routeurs 7"application/x-www-form-urlencoded" = formulaire
8"application/json" = requête AJAX avec fetch()
9"multipart/form-data" = upload d'image par tinymce
10$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' requête AJAX xhs, non utilisée
11=> 3ème test, comme le 2ème test mais uniquement si $_SESSION['admin'] est vrai
12*/
8 13
9declare(strict_types=1); 14declare(strict_types=1);
10 15
11 16
12/* appel des contrôleurs dans password.php */ 17if($_SERVER['REQUEST_METHOD'] === 'GET'){
13if(isset($_GET['action']) && $_GET['action'] === 'deconnexion') 18 // table "user" vide
14{ 19 if(!UserController::existUsers($entityManager)){
15 disconnect($entityManager); 20 require '../src/view/templates/user_create.php';
16} 21 die;
17elseif(isset($_GET['action']) && $_GET['action'] === 'modif_mdp') 22 }
18{ 23
19 changePassword($entityManager); 24 // bouton déconnexion
25 if($request->query->has('action') && $request->query->get('action') === 'deconnection')
26 {
27 UserController::disconnect($entityManager);
28 }
29
30 // données du calendrier
31 // création du calendrier et changement de dates affichées (boutons flèches mais pas changement de vue)
32 if($_SERVER['REQUEST_METHOD'] === 'GET' && $request->query->has('action') && $request->query->get('action') === 'get_events'
33 && $request->query->has('start') && $request->query->has('end') && empty($_POST))
34 {
35 CalendarController::getData($entityManager);
36 }
37
38 if($_SESSION['admin'] === true){
39 // ...
40 }
41
42 // construction d'une page
43 $response = new ViewController()->buildView($request, $entityManager);
20} 44}
21 45
22 46
23// presque tout est ici 47elseif($_SERVER['REQUEST_METHOD'] === 'POST'){
24if($_SERVER['REQUEST_METHOD'] === 'POST'){
25 /* -- contrôleurs appellables par tout le monde -- */ 48 /* -- contrôleurs appellables par tout le monde -- */
49
50 // table "user" vide
51 if(!UserController::existUsers($entityManager))
52 {
53 UserController::createUser($entityManager);
54 }
26 55
27 // POST "ajax" avec fetch (application/json) 56 // requêtes JSON avec fetch()
28 if($_SERVER['CONTENT_TYPE'] === 'application/json') 57 if($_SERVER['CONTENT_TYPE'] === 'application/json')
29 { 58 {
30 $data = file_get_contents('php://input'); 59 $data = file_get_contents('php://input');
@@ -39,13 +68,20 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
39 } 68 }
40 } 69 }
41 70
42 // POST "form" 71 // envoi formulaire HTML
43 // ... 72 elseif($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'){
73 // tentative de connexion
74 if($request->query->has('action') && $request->query->get('action') === 'connection'){
75 //$response =
76 UserController::connect($entityManager);
77 }
78 }
44 79
45 80
46 if($_SESSION['admin'] === true) 81 if($_SESSION['admin'] === true)
47 { 82 {
48 /* -- requêtes AJAX -- */ 83 /* -- requêtes AJAX -- */
84
49 // requêtes JSON avec fetch() 85 // requêtes JSON avec fetch()
50 if($_SERVER['CONTENT_TYPE'] === 'application/json') 86 if($_SERVER['CONTENT_TYPE'] === 'application/json')
51 { 87 {
@@ -122,15 +158,15 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
122 } 158 }
123 159
124 // partie "blocs" 160 // partie "blocs"
125 elseif(isset($_GET['bloc_edit'])) 161 elseif($request->query->has('bloc_edit'))
126 { 162 {
127 // renommage d'un bloc 163 // renommage d'un bloc
128 if($_GET['bloc_edit'] === 'rename_page_bloc') 164 if($request->query->get('bloc_edit') === 'rename_page_bloc')
129 { 165 {
130 PageManagementController::renameBloc($entityManager, $json); 166 PageManagementController::renameBloc($entityManager, $json);
131 } 167 }
132 // inversion des positions de deux blocs 168 // inversion des positions de deux blocs
133 elseif($_GET['bloc_edit'] === 'switch_blocs_positions') 169 elseif($request->query->get('bloc_edit') === 'switch_blocs_positions')
134 { 170 {
135 PageManagementController::SwitchBlocsPositions($entityManager, $json); 171 PageManagementController::SwitchBlocsPositions($entityManager, $json);
136 } 172 }
@@ -138,22 +174,22 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
138 174
139 /* -- upload d'image dans tinymce par copier-coller -- */ 175 /* -- upload d'image dans tinymce par copier-coller -- */
140 // collage de HTML contenant une ou plusieurs balises <img> 176 // collage de HTML contenant une ou plusieurs balises <img>
141 if(isset($_GET['action']) && $_GET['action'] == 'upload_image_html'){ 177 if($request->query->has('action') && $request->query->get('action') == 'upload_image_html'){
142 ImageUploadController::uploadImageHtml(); 178 ImageUploadController::uploadImageHtml();
143 } 179 }
144 // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML 180 // collage d'une image (code base64 dans le presse-papier) non encapsulée dans du HTML
145 elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_base64'){ 181 elseif($request->query->has('action') && $request->query->get('action') == 'upload_image_base64'){
146 ImageUploadController::uploadImageBase64(); 182 ImageUploadController::uploadImageBase64();
147 } 183 }
148 184
149 /* -- requêtes spécifiques au calendrier -- */ 185 /* -- requêtes spécifiques au calendrier -- */
150 if($_GET['action'] === 'new_event'){ 186 if($request->query->get('action') === 'new_event'){
151 CalendarController::newEvent($json, $entityManager); 187 CalendarController::newEvent($json, $entityManager);
152 } 188 }
153 elseif($_GET['action'] === 'update_event'){ 189 elseif($request->query->get('action') === 'update_event'){
154 CalendarController::updateEvent($json, $entityManager); 190 CalendarController::updateEvent($json, $entityManager);
155 } 191 }
156 elseif($_GET['action'] === 'remove_event'){ 192 elseif($request->query->get('action') === 'remove_event'){
157 CalendarController::removeEvent($json, $entityManager); 193 CalendarController::removeEvent($json, $entityManager);
158 } 194 }
159 else{ 195 else{
@@ -163,7 +199,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
163 } 199 }
164 200
165 // upload d'image dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur) 201 // upload d'image dans tinymce avec le plugin (bouton "insérer une image" de l'éditeur)
166 elseif(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && isset($_GET['action']) && $_GET['action'] === 'upload_image') 202 elseif(strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false && $request->query->has('action') && $request->query->get('action') === 'upload_image')
167 { 203 {
168 ImageUploadController::imageUploadTinyMce(); 204 ImageUploadController::imageUploadTinyMce();
169 } 205 }
@@ -175,7 +211,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
175 die; 211 die;
176 } 212 }
177 213
178 /* -- envoi d'un formulaire HTML -- */ 214 /* -- envoi formulaire HTML -- */
179 elseif($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded') 215 elseif($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded')
180 { 216 {
181 /* -- nouvelle page -- */ 217 /* -- nouvelle page -- */
@@ -230,6 +266,17 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
230 MenuAndPathsController::deleteUrlMenuEntry($entityManager); 266 MenuAndPathsController::deleteUrlMenuEntry($entityManager);
231 } 267 }
232 268
269
270 /* -- page Mon compte -- */
271 elseif($request->query->has('action') && $request->query->get('action') === 'update_username')
272 {
273 UserController::updateUsername($entityManager);
274 }
275 elseif($request->query->has('action') && $request->query->get('action') === 'update_password')
276 {
277 UserController::updatePassword($entityManager);
278 }
279
233 // redirection page d'accueil 280 // redirection page d'accueil
234 else{ 281 else{
235 header("Location: " . new URL(['error' => 'paramètres inconnus'])); 282 header("Location: " . new URL(['error' => 'paramètres inconnus']));
@@ -237,20 +284,19 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){
237 } 284 }
238 } 285 }
239 } 286 }
287
288 // rien ne match
289 header("Location: " . new URL);
290 die;
240} 291}
241 292
242// cas particulier d'un GET ajax non-admin par fullcalendar
243elseif($_SERVER['REQUEST_METHOD'] === 'GET'){
244 /* -- non-admin -- */
245 // chargement des évènements à la création du calendrier
246 // et au changement de dates affichées (boutons flèches mais pas changement de vue)
247 if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'get_events'
248 && isset($_GET['start']) && isset($_GET['end']) && empty($_POST))
249 {
250 CalendarController::getData($entityManager);
251 }
252 293
253 if($_SESSION['admin'] === true){ 294else{
254 // ... 295 header("Location: " . new URL(['error' => 'tu fais quoi là mec?']));
255 } 296 die;
297}
298
299// enlever le test isset à terme
300if(isset($response)){
301 $response->send();
256} \ No newline at end of file 302} \ No newline at end of file
diff --git a/src/view/FooterBuilder.php b/src/view/FooterBuilder.php
index 14f9cd7..8a519f8 100644
--- a/src/view/FooterBuilder.php
+++ b/src/view/FooterBuilder.php
@@ -28,7 +28,7 @@ class FooterBuilder extends AbstractBuilder
28 if($_SESSION['admin']) 28 if($_SESSION['admin'])
29 { 29 {
30 $empty_admin_zone = 'empty_admin_zone'; 30 $empty_admin_zone = 'empty_admin_zone';
31 $link_edit_page = new URL(['page' => CURRENT_PAGE]); 31 $link_edit_page = CURRENT_PAGE === 'article' ? new URL(['page' => 'accueil']) : new URL(['page' => CURRENT_PAGE]);
32 if(MainBuilder::$modif_mode){ 32 if(MainBuilder::$modif_mode){
33 $mode = 'modification de page'; 33 $mode = 'modification de page';
34 $div_admin = 'logged_in modif_mode'; 34 $div_admin = 'logged_in modif_mode';
@@ -43,10 +43,10 @@ class FooterBuilder extends AbstractBuilder
43 $link_new_page = new URL(['page' => 'nouvelle_page']); 43 $link_new_page = new URL(['page' => 'nouvelle_page']);
44 $link_change_paths = new URL(['page' => 'menu_chemins']); 44 $link_change_paths = new URL(['page' => 'menu_chemins']);
45 45
46 $link_change_password = new URL(['from' => CURRENT_PAGE, 'action' => 'modif_mdp']); 46 $link_change_password = new URL(['page' => 'user_edit', 'from' => CURRENT_PAGE]);
47 isset($_GET['id']) ? $link_change_password->addParams(['id' => $_GET['id']]) : ''; 47 isset($_GET['id']) ? $link_change_password->addParams(['id' => $_GET['id']]) : '';
48 48
49 $link_logout = new URL(['page' => CURRENT_PAGE, 'action' => 'deconnexion']); 49 $link_logout = new URL(['action' => 'deconnection', 'from' => CURRENT_PAGE]);
50 isset($_GET['id']) ? $link_logout->addParams(['id' => $_GET['id']]) : ''; 50 isset($_GET['id']) ? $link_logout->addParams(['id' => $_GET['id']]) : '';
51 51
52 $zone_admin = '<div class="admin_buttons_zone"> 52 $zone_admin = '<div class="admin_buttons_zone">
@@ -54,7 +54,7 @@ class FooterBuilder extends AbstractBuilder
54 '<div><a href="' . $link_new_page . '"><button>Nouvelle page</button></a></div>' . "\n" . 54 '<div><a href="' . $link_new_page . '"><button>Nouvelle page</button></a></div>' . "\n" .
55 '<div><a href="' . $link_edit_page . '"><button>' . $link_edit_label . '</button></a></div>' . "\n" . 55 '<div><a href="' . $link_edit_page . '"><button>' . $link_edit_label . '</button></a></div>' . "\n" .
56 '<div><a href="' . $link_change_paths . '"><button>Menu et chemins</button></a></div>' . "\n" . 56 '<div><a href="' . $link_change_paths . '"><button>Menu et chemins</button></a></div>' . "\n" .
57 '<div><a href="' . $link_change_password . '"><button>Changer de mot de passe</button></a></div>' . "\n" . 57 '<div><a href="' . $link_change_password . '"><button>Mon compte</button></a></div>' . "\n" .
58 '<div><a href="' . $link_logout . '"><button>Déconnexion</button></a></div>' . "\n" . 58 '<div><a href="' . $link_logout . '"><button>Déconnexion</button></a></div>' . "\n" .
59 '</div>' . "\n"; 59 '</div>' . "\n";
60 } 60 }
diff --git a/src/view/LoginBuilder.php b/src/view/LoginBuilder.php
index 532f054..567c93d 100644
--- a/src/view/LoginBuilder.php
+++ b/src/view/LoginBuilder.php
@@ -9,9 +9,44 @@ class LoginBuilder extends AbstractBuilder
9{ 9{
10 public function __construct(Node $node) 10 public function __construct(Node $node)
11 { 11 {
12 global $entityManager; 12 // déjà connecté?
13 if($_SESSION['admin'])
14 {
15 header('Location: ' . new URL);
16 die;
17 }
13 18
14 // une classe Password ce serait pas mal!! 19 $viewFile = self::VIEWS_PATH . $node->getName() . '.php';
15 connect($this, $entityManager); 20
21 $captcha = new Captcha;
22 $_SESSION['captcha'] = $captcha->getSolution(); // enregistrement de la réponse du captcha pour vérification
23
24 //$this->html .= $header;
25
26 $error_messages = [
27 'error_non_valid_captcha' => 'Erreur au test anti-robot, veuillez saisir un nombre entier.',
28 'captcha_server_error' => 'captcha_server_error',
29 'bad_solution_captcha' => 'Erreur au test anti-robot, veuillez réessayer.',
30 'bad_login_or_password' => 'Mauvais identifiant ou mot de passe, veuillez réessayer.', // ne pas indiquer où est l'erreur
31 'forbidden_characters' => 'Caractères interdits: espaces, tabulations, sauts CR/LF.'
32 ];
33
34 $link_form = new URL(['action' => 'connection']);
35 isset($_GET['from']) ? $link_form->addParams(['from' => $_GET['from']]) : '';
36 isset($_GET['id']) ? $link_form->addParams(['id' => $_GET['id']]) : '';
37
38 $link_exit = new URL;
39 isset($_GET['from']) ? $link_exit->addParams(['page' => $_GET['from'] ]) : '';
40 isset($_GET['id']) ? $link_exit->addParams(['id' => $_GET['id']]) : '';
41
42 $error = isset($_GET['error']) ? $error_messages[$_GET['error']] : '';
43
44 ob_start();
45 require $viewFile;
46 $this->html = ob_get_clean(); // nouveau contenu
47
48 //$this->html .= <p class='connexionP' style='color: red;'>Ce site utilise un cookie « obligatoire » lorsque vous êtes connecté ainsi que sur cette page.<br>Il sera supprimé à votre déconnexion ou dès que vous aurez quitté le site.</p>;
49
50 //$this->html .= $footer;
16 } 51 }
17} 52}
diff --git a/src/view/MainBuilder.php b/src/view/MainBuilder.php
index 7f3a0f0..889df37 100644
--- a/src/view/MainBuilder.php
+++ b/src/view/MainBuilder.php
@@ -86,7 +86,7 @@ class MainBuilder extends AbstractBuilder
86 86
87 //$page_id = Director::$page_path->getLast()->getId(); 87 //$page_id = Director::$page_path->getLast()->getId();
88 $head_node = null; 88 $head_node = null;
89 foreach(ViewBuilder::$root_node->getChildren() as $first_level_node){ 89 foreach(ViewController::$root_node->getChildren() as $first_level_node){
90 if($first_level_node->getName() === 'head'){ 90 if($first_level_node->getName() === 'head'){
91 $head_node = $first_level_node; // normallement c'est le 1er enfant 91 $head_node = $first_level_node; // normallement c'est le 1er enfant
92 break; 92 break;
diff --git a/src/view/UserEditBuilder.php b/src/view/UserEditBuilder.php
new file mode 100644
index 0000000..63bbfad
--- /dev/null
+++ b/src/view/UserEditBuilder.php
@@ -0,0 +1,58 @@
1<?php
2// src/view/UserEditBuilder.php
3//
4// fonctionne avec UserController
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9
10class UserEditBuilder extends AbstractBuilder
11{
12 public function __construct(Node $node)
13 {
14 // pour éviter les arnaques
15 if(!$_SESSION['admin'])
16 {
17 header('Location: ' . new URL);
18 die;
19 }
20
21 $viewFile = self::VIEWS_PATH . $node->getName() . '.php';
22
23 $error_messages = [
24 'error_non_valid_captcha' => 'Erreur au test anti-robot, veuillez saisir un nombre entier.',
25 'captcha_server_error' => 'captcha_server_error',
26
27 'bad_login_or_password' => 'Mauvais identifiant ou mot de passe, veuillez réessayer.', // ne pas indiquer où est l'erreur
28 'bad_solution_captcha' => 'Erreur au test anti-robot, veuillez réessayer.',
29 'forbidden_characters' => 'Caractères interdits: espaces, tabulations, sauts CR/LF.',
30 'same_username_as_before' => 'Nouveau nom identique au précédent.',
31 'same_password_as_before' => 'Nouveau mot de passe identique au précédent.'
32 ];
33
34 $error_username = isset($_GET['error_login']) ? $error_messages[$_GET['error_login']] : '';
35 $success_username = (isset($_GET['success_login']) && $_GET['success_login']) ? 'Identifiant modifié avec succès.' : '';
36 $error_password = isset($_GET['error_password']) ? $error_messages[$_GET['error_password']] : '';
37 $success_password = (isset($_GET['success_password']) && $_GET['success_password']) ? 'Mot de passe modifié avec succès.' : '';
38
39 $captcha = new Captcha;
40 $_SESSION['captcha'] = $captcha->getSolution(); // enregistrement de la réponse du captcha pour vérification
41
42 $link_user_form = new URL(['action' => 'update_username']);
43 isset($_GET['from']) ? $link_user_form->addParams(['from' => $_GET['from']]) : '';
44 isset($_GET['id']) ? $link_user_form->addParams(['id' => $_GET['id']]) : '';
45
46 $link_password_form = new URL(['action' => 'update_password']);
47 isset($_GET['from']) ? $link_password_form->addParams(['from' => $_GET['from']]) : '';
48 isset($_GET['id']) ? $link_password_form->addParams(['id' => $_GET['id']]) : '';
49
50 $link_exit = new URL;
51 isset($_GET['from']) ? $link_exit->addParams(['page' => $_GET['from'] ]) : '';
52 isset($_GET['id']) ? $link_exit->addParams(['id' => $_GET['id']]) : '';
53
54 ob_start();
55 require $viewFile;
56 $this->html = ob_get_clean(); // nouveau contenu
57 }
58} \ No newline at end of file
diff --git a/src/view/ViewBuilder.php b/src/view/ViewBuilder.php
deleted file mode 100644
index 2e2fea6..0000000
--- a/src/view/ViewBuilder.php
+++ /dev/null
@@ -1,18 +0,0 @@
1<?php
2// src/view/ViewBuilder.php
3//
4// appelle les autres Builder
5
6declare(strict_types=1);
7
8use App\Entity\Node;
9
10class ViewBuilder extends AbstractBuilder
11{
12 static public Node $root_node;
13 public function __construct(Node $root_node)
14 {
15 self::$root_node = $root_node;
16 $this->useChildrenBuilder($root_node);
17 }
18}
diff --git a/src/view/password.php b/src/view/password.php
deleted file mode 100644
index 77f8736..0000000
--- a/src/view/password.php
+++ /dev/null
@@ -1,155 +0,0 @@
1<?php
2// src/view/password.php
3//
4// ce fichier contient le HTML de deux pages du site:
5// - connexion au mode admin
6// - changement de mot de passe
7//
8// rajouter la page "créationn du mot de passe"?
9
10declare(strict_types=1);
11
12// insertion du captcha
13$captchaHtml = '';
14if(isset($captcha)) // instance de Captcha?
15{
16 ob_start();
17 ?>
18 <p>Montrez que vous n'êtes pas un robot.<br>
19 <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label>
20 <input required type="text" id="captcha" name="captcha" autocomplete="off" size="1">
21 </p>
22 <?php
23 $captchaHtml = ob_get_clean();
24}
25
26
27// formulaire connexion
28$link = new URL(['page' => 'connexion']);
29isset($_GET['from']) ? $link->addParams(['from' => $_GET['from']]) : '';
30isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
31ob_start();
32?>
33 <form class="connexionFormulaire" method="post" action="<?= $link ?>" >
34 <p><label for="login" >Identifiant (E-mail):</label>
35 <input id="login" type="text" name="login" autofocus required></p>
36 <p><label for="password" >Mot de passe:</label>
37 <input id="password" type="password" name="password" required></p>
38
39 <?= $captchaHtml ?>
40
41 <input type="submit" value="Valider">
42 </form>
43<?php
44$formulaireConnexion = ob_get_clean();
45
46// formulaire création du mot de passe
47ob_start();
48?>
49 <form class="connexionFormulaire" method="post" action="index.php" >
50 <p><label for="login" >Identifiant (e-mail):</label>
51 <input id="login" type="text" name="login" autofocus required></p>
52 <p><label for="password" >Mot de passe:</label>
53 <input id="password" type="password" name="password" required></p>
54
55 <?= $captchaHtml ?>
56
57 <input type="submit" value="Valider">
58 </form>
59<?php
60$formulaireNouveauMDP = ob_get_clean();
61
62// formulaire changement de mot de passe
63$link = new URL(['action' => 'modif_mdp']);
64isset($_GET['from']) ? $link->addParams(['from' => $_GET['from']]) : '';
65isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
66ob_start();
67?>
68 <form class="connexionFormulaire" method="post" action="<?= $link ?>" >
69 <label for="login" >Identifiant (e-mail):</label>
70 <input id="login" type="login" name="login" autofocus required ><br><br>
71 <label for="old_password" >Ancien mot de passe:</label>
72 <input id="old_password" type="password" name="old_password" required ><br><br>
73 <label for="new_password" >Nouveau mot de passe:</label>
74 <input id="new_password" type="password" name="new_password" required autocomplete="off">
75 <input type="hidden" name="modify_password_hidden">
76 <br><br>
77 <input type="submit" value="Valider" >
78 </form>
79<?php
80$formulaireModifMDP = ob_get_clean();
81
82// en-tête
83ob_start();
84?>
85<!DOCTYPE html>
86
87<html lang="fr">
88 <head>
89 <meta charset="utf-8">
90 <title><?= $title ?></title>
91
92 <link rel="icon" type="image/png" href="assets/favicon48x48.png">
93 <script src="js/main.js" ></script>
94 <meta name="viewport" content="width=device-width, initial-scale=1.0">
95 <style>
96 body{background-color: #E3F3FF;}
97 #bloc_page{text-align: center;}
98 .avertissement{color: red;}
99 </style>
100 </head>
101
102 <body>
103 <div id="bloc_page" >
104 <h2 class="connexionTitre" ><?= $title ?></h2>
105 <p class="connexionP" ><?= $subHeading ?></p>
106<?php
107$header = ob_get_clean();
108
109
110$error_messages = [
111 'error_non_valid_captcha' => '<p class="avertissement" >Erreur au test anti-robot, veuillez saisir un nombre entier.</p>',
112 'bad_solution_captcha' => '<p class="avertissement" >Erreur au test anti-robot, veuillez réessayer.</p>',
113 'bad_login_or_password' => '<p class="avertissement" >Mauvais identifiant ou mot de passe, veuillez réessayer.</p>', // ne pas indiquer où est l'erreur
114 'forbidden_characters' => '<p class="avertissement" >Caractères interdits: espaces, tabulations, sauts CR/LF.</p>'
115];
116
117$warning_messages = [
118 'message_disconnect' => "<p class='connexionP' ><i>N'oubliez de cliquer sur 'déconnexion' quand vous aurez fini.</i></p>",
119 //'message_cookie' => "<p class='connexionP' style='color: red;'>Ce site utilise un cookie « obligatoire » lorsque vous êtes connecté ainsi que sur cette page.<br>Il sera supprimé à votre déconnexion ou dès que vous aurez quitté le site.</p>",
120 'private_browsing' =>"<p class='connexionP' >Au fait? Vous n'utilisez pas votre propre ordinateur ou téléphone?<br/>
121 Utilisez la navigation privée.</p>"
122];
123
124
125// confirmation modification du mot de passe
126$page = isset($_GET['from']) ? $_GET['from'] : 'accueil';
127$id = isset($_GET['id']) ? ', \'' . $_GET['id'] . '\'' : '';
128$js = "newPassword('" . $page . "'" . $id . ");";
129ob_start();
130?>
131<script><?= $js ?></script>
132<noscript>
133 <p class="avertissement" >Le mot de passe a été modifié<br>
134 <a href="<?= $link ?>" ><button>Retour au site.</button></a></p>
135</noscript>
136<?php
137$alertJSNewPassword = ob_get_clean();
138
139
140// bas de la page
141$link = new URL();
142isset($_GET['from']) ? $link->addParams(['page' => $_GET['from'] ]) : '';
143isset($_GET['id']) ? $link->addParams(['id' => $_GET['id']]) : '';
144ob_start();
145if(isset($_GET['from'])) // exclue la "création du mot de passe"
146{
147?>
148 <p class="connexionP connexionFooter" >
149 <a href="<?= $link ?>" >
150 <button>Retour au site.</button>
151 </a>
152 </p>
153<?php
154}
155$footer = ob_get_clean(); \ No newline at end of file
diff --git a/src/view/templates/login.php b/src/view/templates/login.php
new file mode 100644
index 0000000..766c114
--- /dev/null
+++ b/src/view/templates/login.php
@@ -0,0 +1,28 @@
1<?php declare(strict_types=1); ?>
2 <section>
3 <h3 class="connexionTitre" >Connexion à l'espace d'administration</h3>
4 <div class="login_form">
5 <p class="connexionP" >Veuillez saisir votre identifiant et votre mot de passe.</p>
6 <p style="color: red; font-style: italic;"><?= $error ?></p>
7 <form class="connexionFormulaire" method="post" action="<?= $link_form ?>" >
8 <p><label for="login" >Identifiant:</label>
9 <input id="login" type="text" name="login" autofocus required></p>
10 <p><label for="password" >Mot de passe:</label>
11 <input id="password" type="password" name="password" required></p>
12
13 <p>Montrez que vous n'êtes pas un robot.<br>
14 <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label>
15 <input required type="text" id="captcha" name="captcha" autocomplete="off" size="1">
16 </p>
17
18 <input type="submit" value="Valider">
19 </form>
20 <p class='connexionP' >Au fait? Vous n'utilisez pas votre propre ordinateur ou téléphone?<br/>
21 Utilisez la navigation privée.</p>
22 <p class="connexionP connexionFooter" >
23 <a href="<?= $link_exit ?>" >
24 <button>Retour au site</button>
25 </a>
26 </p>
27 </div>
28 </section> \ No newline at end of file
diff --git a/src/view/templates/user_create.php b/src/view/templates/user_create.php
new file mode 100644
index 0000000..dd17547
--- /dev/null
+++ b/src/view/templates/user_create.php
@@ -0,0 +1,52 @@
1<?php
2declare(strict_types=1);
3
4$error_messages = [
5 'error_non_valid_captcha' => 'Erreur au test anti-robot, veuillez saisir un nombre entier.',
6 'captcha_server_error' => 'captcha_server_error',
7 'bad_solution_captcha' => 'Erreur au test anti-robot, veuillez réessayer.',
8 'different_passwords' => 'Les deux mots de passe saisis sont différents',
9 'forbidden_characters' => 'Caractères interdits: espaces, tabulations, sauts CR/LF.'
10];
11$error = isset($_GET['error']) ? $error_messages[$_GET['error']] : '';
12
13$captcha = new Captcha;
14$_SESSION['captcha'] = $captcha->getSolution(); // enregistrement de la réponse du captcha pour vérification
15?>
16<!DOCTYPE html>
17<html lang="fr">
18 <head>
19 <meta charset="utf-8">
20 <title>Bienvenue</title>
21 <link rel="icon" type="image/png" href="assets/favicon48x48.png">
22 <link rel="stylesheet" href="css/body.css">
23 <meta name="viewport" content="width=device-width, initial-scale=1.0">
24 </head>
25 <body>
26 <main>
27 <section>
28 <h3>Bienvenue.</h3>
29 <p style="text-align: center;">Veuillez choisir les codes que vous utiliserez pour gérer le site.</p>
30 <div class="login_form">
31 <p style="color: red; font-style: italic;"><?= $error ?></p>
32 <form method="post" action="index.php?action=create_user" >
33 <p><label for="login" >Identifiant:</label>
34 <input id="login" type="text" name="login" autofocus required></p>
35 <p><label for="password" >Mot de passe:</label>
36 <input id="password" type="password" name="password" required></p>
37 <p><label for="password_confirmation" >Confirmer le mot de passe:</label>
38 <input id="password_confirmation" type="password" name="password_confirmation" required></p>
39 <input type="hidden" name="create_user_hidden">
40
41 <p>Montrez que vous n'êtes pas un robot.<br>
42 <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label>
43 <input required type="text" id="captcha" name="captcha" autocomplete="off" size="1">
44 </p>
45
46 <input type="submit" value="Valider">
47 </form>
48 </div>
49 </section>
50 </main>
51 </body>
52</html> \ No newline at end of file
diff --git a/src/view/templates/user_edit.php b/src/view/templates/user_edit.php
new file mode 100644
index 0000000..b4b35ed
--- /dev/null
+++ b/src/view/templates/user_edit.php
@@ -0,0 +1,62 @@
1<?php declare(strict_types=1); ?>
2 <section>
3 <div class="user_edit_header">
4 <div class="empty_column"></div>
5 <h3 class="connexionTitre" >Mon compte</h3>
6 <div>
7 <img class="user_icon" src="assets/user_hollow.svg">
8 <div><?= $_SESSION['user'] ?></div>
9 </div>
10 </div>
11 <div class="user_edit_flex">
12 <div class="login_form">
13 <p class="connexionP" >Modifier mon nom d'utilisateur.</p>
14 <p style="color: red; font-style: italic;"><?= $error_username ?></p>
15 <p style="color: green; font-style: italic;"><?= $success_username ?></p>
16 <form class="connexionFormulaire" method="post" action="<?= $link_user_form ?>" >
17 <p><label for="old_login" >Ancien nom:</label>
18 <input id="old_login" type="text" name="old_login" required></p>
19 <p><label for="password" >Mot de passe:</label>
20 <input id="password" type="password" name="password" required ></p>
21 <p><label for="new_login" >Nouveau nom:</label>
22 <input id="new_login" type="text" name="new_login" required></p>
23 <input type="hidden" name="modify_username_hidden">
24
25 <p>Montrez que vous n'êtes pas un robot.<br>
26 <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label>
27 <input required type="text" id="captcha" name="captcha" autocomplete="off" size="1">
28 </p>
29
30 <input type="submit" value="Valider">
31 </form>
32 </div>
33 <div class="login_form">
34 <p class="connexionP" >Modifier mon mot de passe.</p>
35 <p style="color: red; font-style: italic;"><?= $error_password ?></p>
36 <p style="color: green; font-style: italic;"><?= $success_password ?></p>
37 <form class="connexionFormulaire" method="post" action="<?= $link_password_form ?>" >
38 <p><label for="login" >Nom:</label>
39 <input id="login" type="text" name="login" required></p>
40 <p><label for="old_password" >Ancien mot de passe:</label>
41 <input id="old_password" type="password" name="old_password" required ></p>
42 <p><label for="new_password" >Nouveau mot de passe:</label>
43 <input id="new_password" type="password" name="new_password" required autocomplete="off"></p>
44 <input type="hidden" name="modify_password_hidden">
45
46 <p>Montrez que vous n'êtes pas un robot.<br>
47 <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label>
48 <input required type="text" id="captcha" name="captcha" autocomplete="off" size="1">
49 </p>
50
51 <input type="submit" value="Valider">
52 </form>
53 </div>
54 </div>
55 <div class="login_form">
56 <p class="connexionP connexionFooter" >
57 <a href="<?= $link_exit ?>" >
58 <button>Retour au site</button>
59 </a>
60 </p>
61 </div>
62 </section> \ No newline at end of file