aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/controller/UserController.php65
-rw-r--r--src/controller/ViewController.php6
-rw-r--r--src/installation.php161
-rw-r--r--src/model/Menu.php4
-rw-r--r--src/model/entities/AppMetadata.php46
-rw-r--r--src/model/entities/User.php19
-rw-r--r--src/service/AppMode.php56
-rw-r--r--src/service/Captcha.php (renamed from src/Captcha.php)2
-rw-r--r--src/service/Config.php (renamed from src/Config.php)2
-rw-r--r--src/service/EmailService.php (renamed from src/EmailService.php)2
-rw-r--r--src/service/FormValidation.php (renamed from src/FormValidation.php)6
-rw-r--r--src/service/Installation.php209
-rw-r--r--src/service/Security.php (renamed from src/Security.php)2
-rw-r--r--src/service/URL.php (renamed from src/URL.php)2
-rw-r--r--src/service/router.php (renamed from src/router.php)12
-rw-r--r--src/service/session.php86
-rw-r--r--src/view/CalendarBuilder.php2
-rw-r--r--src/view/FooterBuilder.php2
-rw-r--r--src/view/FormBuilder.php9
-rw-r--r--src/view/GaleryBuilder.php2
-rw-r--r--src/view/HeadBuilder.php2
-rw-r--r--src/view/HeaderBuilder.php2
-rw-r--r--src/view/LoginBuilder.php2
-rw-r--r--src/view/MainBuilder.php2
-rw-r--r--src/view/MenuBuilder.php2
-rw-r--r--src/view/NewBuilder.php2
-rw-r--r--src/view/NewPageBuilder.php2
-rw-r--r--src/view/NewsBlockBuilder.php2
-rw-r--r--src/view/PostBlockBuilder.php2
-rw-r--r--src/view/PostBuilder.php2
-rw-r--r--src/view/UserEditBuilder.php2
-rw-r--r--src/view/templates/footer.php2
-rw-r--r--src/view/templates/header.php2
-rw-r--r--src/view/templates/maintenance.php27
-rw-r--r--src/view/templates/user_create.php2
-rw-r--r--src/view/templates/user_edit.php2
36 files changed, 511 insertions, 241 deletions
diff --git a/src/controller/UserController.php b/src/controller/UserController.php
index f3c99e7..6928e86 100644
--- a/src/controller/UserController.php
+++ b/src/controller/UserController.php
@@ -22,14 +22,12 @@ class UserController
22 // account 22 // account
23 static public function existUsers(EntityManager $entityManager): bool 23 static public function existUsers(EntityManager $entityManager): bool
24 { 24 {
25 $nb_users = $entityManager 25 if(!$entityManager // table vide
26 ->createQuery('SELECT COUNT(u.id_user) FROM App\Entity\User u') 26 ->createQuery("SELECT u FROM App\Entity\User u")
27 ->getSingleScalarResult(); 27 ->setMaxResults(1)
28 28 ->getOneOrNullResult())
29 if($nb_users === 0) // table vide
30 { 29 {
31 $_SESSION['user'] = ''; 30 unset($_SESSION['user']);
32 $_SESSION['admin'] = false;
33 return false; 31 return false;
34 } 32 }
35 else{ 33 else{
@@ -38,7 +36,7 @@ class UserController
38 } 36 }
39 37
40 // account 38 // account
41 static public function createUser(EntityManager $entityManager) 39 static public function createAdminUser(EntityManager $entityManager)
42 { 40 {
43 unset($_SESSION['user']); 41 unset($_SESSION['user']);
44 42
@@ -48,7 +46,7 @@ class UserController
48 $error = ''; 46 $error = '';
49 if($form->validate()){ 47 if($form->validate()){
50 $password = password_hash($_POST['password'], PASSWORD_DEFAULT); 48 $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
51 $user = new App\Entity\User($_POST['login'], $password); 49 $user = new User($_POST['login'], 'admin', $password);
52 $entityManager->persist($user); 50 $entityManager->persist($user);
53 $entityManager->flush(); 51 $entityManager->flush();
54 } 52 }
@@ -64,31 +62,34 @@ class UserController
64 die; 62 die;
65 } 63 }
66 64
65 // account
66 //static public function createUser(EntityManager $entityManager){}
67
67 // auth 68 // auth
68 static public function connect(EntityManager $entityManager): void 69 static public function connect(EntityManager $entityManager): void
69 { 70 {
70 if($_SESSION['admin']) // déjà connecté? 71 if(IS_ADMIN) // déjà connecté?
71 { 72 {
72 header('Location: ' . new URL); 73 header('Location: ' . new URL);
73 die; 74 die;
74 } 75 }
75 $_SESSION['user'] = ''; 76 unset($_SESSION['user']);
76 $_SESSION['admin'] = false;
77 77
78 $form = new FormValidation($_POST, 'connection'); 78 $form = new FormValidation($_POST, 'connection');
79 79
80 $error = ''; 80 $error = '';
81 if($form->validate()){ 81 if($form->validate()){
82 // à mettre dans une classe métier UserService, Authentication, AuthService? 82 // à mettre dans une classe métier UserService, Authentication, AuthService?
83 $user = self::getUser($_POST['login'], $entityManager); 83 $user = self::getUserByName($_POST['login'], $entityManager);
84 if(!empty($user) && $_POST['login'] === $user->getLogin() && password_verify($_POST['password'], $user->getPassword())) 84 if(!empty($user) && $_POST['login'] === $user->getLogin() && password_verify($_POST['password'], $user->getPassword()))
85 { 85 {
86 $log = new Log(true); 86 $log = new Log(true);
87 87
88 // protection fixation de session, si l'attaquant crée un cookie de session, il est remplacé 88 // protection fixation de session, si l'attaquant crée un cookie de session, il est remplacé
89 session_regenerate_id(true); 89 session_regenerate_id(true);
90 $_SESSION['user'] = $_POST['login']; 90 $_SESSION['user']['id'] = $user->getId();
91 $_SESSION['admin'] = true; 91 $_SESSION['user']['username'] = $user->getLogin();
92 $_SESSION['user']['role'] = $user->getRole();
92 93
93 EmailService::cleanEmails($entityManager); 94 EmailService::cleanEmails($entityManager);
94 95
@@ -123,7 +124,7 @@ class UserController
123 static public function disconnect(): void 124 static public function disconnect(): void
124 { 125 {
125 // nettoyage complet 126 // nettoyage complet
126 $_SESSION = []; // mémoire vive 127 unset($_SESSION['user']); // mémoire vive
127 session_destroy(); // fichier côté serveur 128 session_destroy(); // fichier côté serveur
128 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session 129 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
129 130
@@ -138,7 +139,7 @@ class UserController
138 // user 139 // user
139 static public function updateUsername(EntityManager $entityManager): void 140 static public function updateUsername(EntityManager $entityManager): void
140 { 141 {
141 if(!$_SESSION['admin']){ // superflux, fait dans le routeur 142 if(!IS_ADMIN){ // superflux, fait dans le routeur
142 self::disconnect(); 143 self::disconnect();
143 } 144 }
144 145
@@ -150,11 +151,11 @@ class UserController
150 $error = ''; 151 $error = '';
151 if($form->validate()){ 152 if($form->validate()){
152 // à mettre dans une classe métier UserService? 153 // à mettre dans une classe métier UserService?
153 $user = self::getUser($_POST['login'], $entityManager); 154 $user = self::getUserByName($_POST['login'], $entityManager);
154 if(password_verify($_POST['password'], $user->getPassword())){ 155 if(password_verify($_POST['password'], $user->getPassword())){
155 $user->setLogin($_POST['new_login']); 156 $user->setLogin($_POST['new_login']);
156 $entityManager->flush(); 157 $entityManager->flush();
157 $_SESSION['user'] = $_POST['new_login']; 158 $_SESSION['user']['username'] = $_POST['new_login'];
158 159
159 $url->addParams(['success_username' => 'new_login']); 160 $url->addParams(['success_username' => 'new_login']);
160 $error = ''; 161 $error = '';
@@ -178,7 +179,7 @@ class UserController
178 // user 179 // user
179 static public function updatePassword(EntityManager $entityManager): void 180 static public function updatePassword(EntityManager $entityManager): void
180 { 181 {
181 if(!$_SESSION['admin']){ // superflux, fait dans le routeur 182 if(!IS_ADMIN){ // superflux, fait dans le routeur
182 self::disconnect(); 183 self::disconnect();
183 } 184 }
184 185
@@ -190,7 +191,7 @@ class UserController
190 $error = ''; 191 $error = '';
191 if($form->validate()){ 192 if($form->validate()){
192 // à mettre dans une classe métier UserService? 193 // à mettre dans une classe métier UserService?
193 $user = self::getUser($_POST['login'], $entityManager); 194 $user = self::getUserByName($_POST['login'], $entityManager);
194 if(password_verify($_POST['password'], $user->getPassword())){ 195 if(password_verify($_POST['password'], $user->getPassword())){
195 $new_password = password_hash($_POST['new_password'], PASSWORD_DEFAULT); 196 $new_password = password_hash($_POST['new_password'], PASSWORD_DEFAULT);
196 $user->setPassword($new_password); 197 $user->setPassword($new_password);
@@ -216,26 +217,22 @@ class UserController
216 } 217 }
217 218
218 // dans une classe mère ou un trait après découpage de UserController? 219 // dans une classe mère ou un trait après découpage de UserController?
219 static private function getUser(string $login, EntityManager $entityManager): ?User 220 static private function getUserByName(string $login, EntityManager $entityManager): ?User
220 { 221 {
221 $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]); 222 $users = $entityManager->getRepository(User::class)->findBy(['login' => $login]);
222 223 foreach($users as $user){
223 if(count($users) === 0) 224 if($user->getLogin() === $login){
224 {
225 $_SESSION['user'] = '';
226 $_SESSION['admin'] = false;
227 }
228
229 foreach($users as $user)
230 {
231 if($user->getLogin() === $login)
232 {
233 return $user; 225 return $user;
234 } 226 }
235 } 227 }
236 return null; 228 return null;
237 } 229 }
238 230
231 static public function getUserById(int $id, EntityManager $entityManager): ?User
232 {
233 return $entityManager->find(User::class, $id);
234 }
235
239 // dans une classe Form? 236 // dans une classe Form?
240 // erreurs à la création des mots de passe 237 // erreurs à la création des mots de passe
241 static private function removeSpacesTabsCRLF(string $chaine): string 238 static private function removeSpacesTabsCRLF(string $chaine): string
diff --git a/src/controller/ViewController.php b/src/controller/ViewController.php
index 8c95526..cf3477c 100644
--- a/src/controller/ViewController.php
+++ b/src/controller/ViewController.php
@@ -21,7 +21,7 @@ class ViewController extends AbstractBuilder // ViewController est aussi le prem
21 /* 1/ 1er contrôle des paramètres */ 21 /* 1/ 1er contrôle des paramètres */
22 22
23 // mode modification d'une page 23 // mode modification d'une page
24 if($_SESSION['admin'] 24 if(IS_ADMIN
25 && $request->query->has('mode') && $request->query->get('mode') === 'page_modif' 25 && $request->query->has('mode') && $request->query->get('mode') === 'page_modif'
26 && !in_array(CURRENT_PAGE, ['article', 'new_page', 'menu_paths', 'user_edit', 'connection'])) 26 && !in_array(CURRENT_PAGE, ['article', 'new_page', 'menu_paths', 'user_edit', 'connection']))
27 { 27 {
@@ -29,7 +29,7 @@ class ViewController extends AbstractBuilder // ViewController est aussi le prem
29 } 29 }
30 // page article: mode création et erreurs d'id 30 // page article: mode création et erreurs d'id
31 if(CURRENT_PAGE === 'article'){ 31 if(CURRENT_PAGE === 'article'){
32 if($_SESSION['admin']){ 32 if(IS_ADMIN){
33 if(!$request->query->has('id')){ 33 if(!$request->query->has('id')){
34 return new Response($this->html, 302); 34 return new Response($this->html, 302);
35 } 35 }
@@ -58,7 +58,7 @@ class ViewController extends AbstractBuilder // ViewController est aussi le prem
58 /* 3/ 2ème contrôle des paramètres avec les données récupérées */ 58 /* 3/ 2ème contrôle des paramètres avec les données récupérées */
59 59
60 // article non trouvé en BDD 60 // article non trouvé en BDD
61 if(CURRENT_PAGE === 'article' && !$_SESSION['admin'] && self::$root_node->getNodeByName('main')->getAdoptedChild() === null){ 61 if(CURRENT_PAGE === 'article' && !IS_ADMIN && self::$root_node->getNodeByName('main')->getAdoptedChild() === null){
62 return new Response($this->html, 302); 62 return new Response($this->html, 302);
63 } 63 }
64 64
diff --git a/src/installation.php b/src/installation.php
deleted file mode 100644
index 2bef8e5..0000000
--- a/src/installation.php
+++ /dev/null
@@ -1,161 +0,0 @@
1<?php
2// src/installation.php
3
4declare(strict_types=1);
5
6use App\Entity\Page;
7use App\Entity\Node;
8use App\Entity\NodeData;
9use App\Entity\Asset;
10use Doctrine\Common\Collections\ArrayCollection;
11use Doctrine\ORM\EntityManager;
12
13function phpDependancies(): void
14{
15 $flag = false;
16 //$extensions = ['pdo_mysql', 'mbstring', 'ctype', 'json', 'tokenizer', 'zip', 'dom']; // les 5 premières sont pour doctrine
17 $extensions = ['pdo_mysql', 'mbstring', 'ctype', 'json', 'tokenizer'];
18 foreach($extensions as $extension){
19 if(!extension_loaded($extension))
20 {
21 echo("<p>l'extension <b>" . $extension . '</b> est manquante</p>');
22 $flag = true;
23 }
24 }
25 if(!extension_loaded('imagick') && !extension_loaded('gd')){
26 echo("<p>il manque une de ces extensions au choix pour le traitement des images: <b>imagick</b> (de préférence) ou <b>gd</b>.</p>");
27 $flag = true;
28 }
29 if($flag){
30 echo '<p>Réalisez les actions nécéssaires sur le serveur ou contactez l\'administrateur du site.<br>
31 Quand le problème sera résolu, il vous suffira de <a href="#">recharger la page<a>.</p>';
32 die;
33 }
34}
35
36function installation(): void
37{
38 // -- droits des fichiers et dossiers --
39 $droits_dossiers = 0700;
40 $droits_fichiers = 0600;
41
42 if(!file_exists('user_data')){
43 // créer le dossier user_data
44 mkdir('user_data/');
45 chmod('user_data/', $droits_dossiers);
46 echo '<p style="color: red;">Le dossier public/user_data introuvable et le serveur n\'a pas la permission de le créer.<br>
47 Pour faire ça bien:<br>sudo -u "serveur web" mkdir /chemin/du/site/public/user_data</p>
48 <p>Aide: "serveur web" se nomme "www-data" sur debian et ubuntu, il s\'appelera "http" sur d\'autres distributions.</p>';
49 die;
50 }
51
52 if(!file_exists('../config/config.ini')){
53 // aide à la création du config.ini
54 echo '<p>Ce fichier contient les codes de la base de données et quelques paramètres utilisés pour créer les liens internes.<br>
55 Un modèle est disponible, il s\'agit du fichier config/config-template.ini</p>
56 <p>Quand vous aurez terminé votre config.ini, donnez-lui si possible des droits 600.</p>';
57 die;
58 }
59}
60
61/*
62 // droits du config.ini
63 if(substr(sprintf('%o', fileperms('../config/config.ini')), -4) != 600){
64 chmod('../config/config.ini', $droits_fichiers);
65 }
66
67 // création de data et sous-dossiers
68 if(!file_exists('../data')){
69 mkdir('../data/');
70 chmod('../data/', $droits_dossiers);
71 }
72 if(!touch('../data')){
73 echo("dossier data non autorisé en écriture");
74 die;
75 }
76 $sous_dossiers = array('images', 'images-mini', 'videos');
77 foreach ($sous_dossiers as $sous_dossier){
78 if(!file_exists('../data/' . $sous_dossier)){
79 mkdir('../data/' . $sous_dossier);
80 chmod('../data/' . $sous_dossier, $droits_dossiers);
81 }
82 if(!touch('../data/' . $sous_dossier)){
83 echo("dossier data non autorisé en écriture");
84 die;
85 }
86 }
87*/
88
89// création d'un site minimal avec une page d'accueil à la toute 1ère visite du site
90// fonctiona appelée après la première requête envoyée en BDD,
91// en l'occurence dans Menu parce que count($bulk_data) === 0
92function fillStartingDatabase(EntityManager $entityManager){
93 /* -- table page -- */
94 // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent
95 $accueil = new Page('Accueil', 'accueil', "Page d'accueil", true, true, false, 1, NULL);
96 $article = new Page('Article', 'article', "", true, false, false, NULL, NULL);
97 $connection = new Page('Connexion', 'connection', "Connexion", true, false, false, NULL, NULL);
98 $my_account = new Page('Mon compte', 'user_edit', "Mon compte", true, false, false, NULL, NULL);
99 $menu_paths = new Page("Menu et chemins", 'menu_paths', "Menu et chemins", true, false, false, NULL, NULL);
100 $menu_paths->addCSS('menu');
101 $menu_paths->addJS('menu');
102 $new_page = new Page('Nouvelle page', 'new_page', "Nouvelle page", true, false, false, NULL, NULL);
103 $new_page->addCSS('new_page');
104 $new_page->addJS('new_page');
105 $emails = new Page("Courriels", 'emails', "Consulter les courriels en base de données", true, false, false, NULL, NULL);
106 $emails->addCSS('show_emails');
107 $emails->addJS('form');
108
109 /* -- table node -- */
110 // paramètres: name_node, article_timestamp, attributes, position, parent, page, article
111 $head = new Node('head', 1, NULL, NULL, NULL);
112 $header = new Node('header', 2, NULL, NULL, NULL);
113 $nav = new Node('nav', 1, $header, NULL, NULL);
114 $main = new Node('main', 3, NULL, NULL, NULL);
115 $footer = new Node('footer', 4, NULL, NULL, NULL);
116 $breadcrumb = new Node('breadcrumb', 2, $header, NULL, NULL);
117 $login = new Node('login', 1, $main, $connection, NULL);
118 $user_edit = new Node('user_edit', 1, $main, $my_account, NULL);
119 $bloc_edit_menu = new Node('menu', 1, $main, $menu_paths, NULL);
120 $bloc_new_page = new Node('new_page', 1, $main, $new_page, NULL);
121 $bloc_emails = new Node('show_emails', 1, $main, $emails, NULL);
122
123 /* -- table node_data -- */
124 // paramètres: data, node, images
125 $head_data = new NodeData([], $head);
126 $header_data = new NodeData([], $header);
127 $footer_data = new NodeData([], $footer);
128 $emails_data = new NodeData([], $bloc_emails);
129
130 /* -- table page -- */
131 $entityManager->persist($accueil);
132 $entityManager->persist($article);
133 $entityManager->persist($connection);
134 $entityManager->persist($my_account);
135 $entityManager->persist($menu_paths);
136 $entityManager->persist($new_page);
137 $entityManager->persist($emails);
138
139 /* -- table node -- */
140 $entityManager->persist($head);
141 $entityManager->persist($header);
142 $entityManager->persist($nav);
143 $entityManager->persist($main);
144 $entityManager->persist($footer);
145 $entityManager->persist($breadcrumb);
146 $entityManager->persist($login);
147 $entityManager->persist($user_edit);
148 $entityManager->persist($bloc_edit_menu);
149 $entityManager->persist($bloc_new_page);
150 $entityManager->persist($bloc_emails);
151
152 /* -- table node_data -- */
153 $entityManager->persist($head_data);
154 $entityManager->persist($header_data);
155 $entityManager->persist($footer_data);
156 $entityManager->persist($emails_data);
157
158 $entityManager->flush();
159 header('Location: ' . new URL);
160 die;
161} \ No newline at end of file
diff --git a/src/model/Menu.php b/src/model/Menu.php
index 3d07d3f..d277259 100644
--- a/src/model/Menu.php
+++ b/src/model/Menu.php
@@ -18,10 +18,6 @@ class Menu extends Page
18 ->createQuery('SELECT n FROM App\Entity\Page n WHERE n.parent IS null') // :Doctrine\ORM\Query 18 ->createQuery('SELECT n FROM App\Entity\Page n WHERE n.parent IS null') // :Doctrine\ORM\Query
19 ->getResult(); // :array de Page 19 ->getResult(); // :array de Page
20 20
21 if(count($bulk_data) === 0){
22 fillStartingDatabase($entityManager); // => installation.php
23 }
24
25 foreach($bulk_data as $first_level_entries){ 21 foreach($bulk_data as $first_level_entries){
26 // dans le menu 22 // dans le menu
27 if($first_level_entries->isInMenu()){ 23 if($first_level_entries->isInMenu()){
diff --git a/src/model/entities/AppMetadata.php b/src/model/entities/AppMetadata.php
new file mode 100644
index 0000000..ae42ad9
--- /dev/null
+++ b/src/model/entities/AppMetadata.php
@@ -0,0 +1,46 @@
1<?php
2// src/model/entities/AppMetadata.php
3
4// comme dans AppMode, prévoir d'ajouter des champs "since" et "by" (qui a changé quoi quel jour?)
5
6declare(strict_types=1);
7
8namespace App\Entity;
9
10use Doctrine\ORM\Mapping as ORM;
11
12#[ORM\Entity]
13#[ORM\Table(name: TABLE_PREFIX . "app_metadata")]
14class AppMetadata
15{
16 #[ORM\Id]
17 #[ORM\Column(type: "string", length: 100)]
18 private string $key_name;
19
20 #[ORM\Column(type: "string")]
21 private string $value;
22
23 public function __construct(string $key, string $value)
24 {
25 $this->key_name = $key;
26 $this->value = $value;
27 }
28
29 public function getKey(): string
30 {
31 return $this->key_name;
32 }
33 public function getValue(): string
34 {
35 return $this->value;
36 }
37
38 public function setKey(string $key): void
39 {
40 $this->key_name = $key;
41 }
42 public function setValue(string $value): void
43 {
44 $this->value = $value;
45 }
46} \ No newline at end of file
diff --git a/src/model/entities/User.php b/src/model/entities/User.php
index 26802e2..36bc4db 100644
--- a/src/model/entities/User.php
+++ b/src/model/entities/User.php
@@ -22,15 +22,24 @@ class User
22 #[ORM\Column(type: "string", length: 255, unique: true)] // risque de modifier son mot de passe sans s'apercevoir qu'il fonctionne encore sur un autre compte 22 #[ORM\Column(type: "string", length: 255, unique: true)] // risque de modifier son mot de passe sans s'apercevoir qu'il fonctionne encore sur un autre compte
23 private string $login; 23 private string $login;
24 24
25 #[ORM\Column(type: "string", length: 50)]
26 private string $role;
27
25 #[ORM\Column(type: "string", length: 255)] 28 #[ORM\Column(type: "string", length: 255)]
26 private string $password; 29 private string $password;
27 30
28 public function __construct(string $login, string $password) 31 public function __construct(string $login, string $role, string $password)
29 { 32 {
30 $this->login = $login; 33 $this->login = $login;
34 $this->role = $role;
31 $this->password = $password; 35 $this->password = $password;
32 } 36 }
33 37
38 public function getId(): int
39 {
40 return $this->id_user;
41 }
42
34 public function getLogin(): string 43 public function getLogin(): string
35 { 44 {
36 return $this->login; 45 return $this->login;
@@ -39,6 +48,14 @@ class User
39 { 48 {
40 $this->login = $login; 49 $this->login = $login;
41 } 50 }
51 public function getRole(): string
52 {
53 return $this->role;
54 }
55 public function setRole(string $role): void
56 {
57 $this->role = $role;
58 }
42 public function getPassword(): string 59 public function getPassword(): string
43 { 60 {
44 return $this->password; 61 return $this->password;
diff --git a/src/service/AppMode.php b/src/service/AppMode.php
new file mode 100644
index 0000000..60b58bd
--- /dev/null
+++ b/src/service/AppMode.php
@@ -0,0 +1,56 @@
1<?php
2// src/service/AppMode.php
3
4// comme dans AppMetadata, prévoir d'ajouter des champs "since" et "by" (qui a changé quoi quel jour?)
5
6declare(strict_types=1);
7
8use App\Entity\AppMetadata;
9use Doctrine\ORM\EntityManager;
10
11class AppMode
12{
13 private static string $mode;
14
15 public static function load(EntityManager $entityManager): void
16 {
17 $metadata = $entityManager->getRepository(AppMetadata::class)->find('mode');
18 if(!$metadata){
19 self::$mode = 'maintenance';
20 }
21 else{
22 self::$mode = $metadata->getValue();
23 }
24 }
25
26 public static function is(string $mode): bool
27 {
28 return self::$mode === $mode;
29 }
30
31 public static function get(): string
32 {
33 return self::$mode;
34 }
35
36 public static function set(EntityManager $entityManager, string $mode): void
37 {
38 self::$mode = $mode;
39
40 $metadata = $entityManager->find(AppMetadata::class, 'mode');
41 if($metadata){
42 $metadata->setValue($mode);
43 }
44 else{
45 $metadata = new AppMetadata('mode', $mode);
46 $entityManager->persist($metadata);
47 }
48 $entityManager->flush();
49
50 /*self::$data = [
51 'mode' => $mode,
52 'since' => (new DateTimeImmutable())->format('c'),
53 'by' => $by,
54 ];*/
55 }
56} \ No newline at end of file
diff --git a/src/Captcha.php b/src/service/Captcha.php
index a0c7a54..d57f912 100644
--- a/src/Captcha.php
+++ b/src/service/Captcha.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/Captcha.php 2// src/service/Captcha.php
3// 3//
4// la solution est stockée dans une unique variable $_SESSION['captcha'] 4// la solution est stockée dans une unique variable $_SESSION['captcha']
5// => on pourrait appliquer le pattern "singleton" (justification = le captcha devient une sorte de ressource partagée) 5// => on pourrait appliquer le pattern "singleton" (justification = le captcha devient une sorte de ressource partagée)
diff --git a/src/Config.php b/src/service/Config.php
index 76b34e2..e59f728 100644
--- a/src/Config.php
+++ b/src/service/Config.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/Config.php 2// src/service/Config.php
3 3
4declare(strict_types=1); 4declare(strict_types=1);
5 5
diff --git a/src/EmailService.php b/src/service/EmailService.php
index c6d97b4..6f4e93d 100644
--- a/src/EmailService.php
+++ b/src/service/EmailService.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/EmailService.php 2// src/service/EmailService.php
3 3
4declare(strict_types=1); 4declare(strict_types=1);
5 5
diff --git a/src/FormValidation.php b/src/service/FormValidation.php
index b3a3793..4677bef 100644
--- a/src/FormValidation.php
+++ b/src/service/FormValidation.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/FormValidation.php 2// src/service/FormValidation.php
3 3
4declare(strict_types=1); 4declare(strict_types=1);
5 5
@@ -181,7 +181,7 @@ class FormValidation
181 $this->errors[] = 'forbidden_characters'; 181 $this->errors[] = 'forbidden_characters';
182 } 182 }
183 183
184 if($this->data['login'] !== $_SESSION['user']){ 184 if($this->data['login'] !== $_SESSION['user']['username']){
185 $this->errors[] = 'bad_login_or_password'; 185 $this->errors[] = 'bad_login_or_password';
186 } 186 }
187 if($this->data['login'] === $new_login){ 187 if($this->data['login'] === $new_login){
@@ -205,7 +205,7 @@ class FormValidation
205 $this->errors[] = 'forbidden_characters'; 205 $this->errors[] = 'forbidden_characters';
206 } 206 }
207 207
208 if($this->data['login'] !== $_SESSION['user']){ 208 if($this->data['login'] !== $_SESSION['user']['username']){
209 $this->errors[] = 'bad_login_or_password'; 209 $this->errors[] = 'bad_login_or_password';
210 } 210 }
211 if($this->data['password'] === $new_password){ 211 if($this->data['password'] === $new_password){
diff --git a/src/service/Installation.php b/src/service/Installation.php
new file mode 100644
index 0000000..5c2a901
--- /dev/null
+++ b/src/service/Installation.php
@@ -0,0 +1,209 @@
1<?php
2// src/service/Installation.php
3
4declare(strict_types=1);
5
6use App\Entity\AppMetadata;
7use App\Entity\Page;
8use App\Entity\Node;
9use App\Entity\NodeData;
10use Doctrine\ORM\EntityManager;
11
12class Installation
13{
14 static public function phpDependancies(): void
15 {
16 $flag = false;
17 //$extensions = ['pdo_mysql', 'mbstring', 'ctype', 'json', 'tokenizer', 'zip', 'dom']; // les 5 premières sont pour doctrine
18 $extensions = ['pdo_mysql', 'mbstring', 'ctype', 'json', 'tokenizer'];
19 foreach($extensions as $extension){
20 if(!extension_loaded($extension))
21 {
22 echo("<p>l'extension <b>" . $extension . '</b> est manquante</p>');
23 $flag = true;
24 }
25 }
26 if(!extension_loaded('imagick') && !extension_loaded('gd')){
27 echo("<p>il manque une de ces extensions au choix pour le traitement des images: <b>imagick</b> (de préférence) ou <b>gd</b>.</p>");
28 $flag = true;
29 }
30 if($flag){
31 echo '<p>Réalisez les actions nécéssaires sur le serveur ou contactez l\'administrateur du site.<br>
32 Quand le problème sera résolu, il vous suffira de <a href="#">recharger la page<a>.</p>';
33 die;
34 }
35 }
36
37 static public function checkFilesAndFoldersRights(): void
38 {
39 // -- droits des fichiers et dossiers --
40 $droits_dossiers = 0700;
41 $droits_fichiers = 0600;
42
43 if(!file_exists('user_data')){
44 // créer le dossier user_data
45 mkdir('user_data/');
46 chmod('user_data/', $droits_dossiers);
47 echo '<p style="color: red;">Le dossier public/user_data introuvable et le serveur n\'a pas la permission de le créer.<br>
48 Pour faire ça bien:<br>sudo -u "serveur web" mkdir /chemin/du/site/public/user_data</p>
49 <p>Aide: "serveur web" se nomme "www-data" sur debian et ubuntu, il s\'appelera "http" sur d\'autres distributions.</p>';
50 die;
51 }
52
53 if(!file_exists('../config/config.ini')){
54 // aide à la création du config.ini
55 echo '<p>Le fichier config/config.ini est introuvable.</p>';
56 echo '<p>Il doit obligatoirement contenir les codes de la base de données, le protocole http ou https (et éventuellement le port) utilisé pour créer les liens internes.<br>
57 Un modèle est disponible, il s\'agit du fichier config/config-template.ini</p>
58 <p>Quand vous aurez terminé votre config.ini, donnez-lui par sécurité des droits 600.</p>';
59 die;
60 }
61 else{
62 // droits du config.ini
63 /*if(substr(sprintf('%o', fileperms('../config/config.ini')), -4) != 600){
64 chmod('../config/config.ini', $droits_fichiers);
65 }*/
66
67 // tester les liens internes
68 //
69
70 // le test de connexion à la BDD est dans le doctrine bootstrap
71 }
72 }
73
74
75 /* création d'un site minimal avec une page d'accueil à la toute 1ère visite du site, ne doit surtout pas être exécutée une seconde fois */
76
77 // protection 1 utilisé à chaque requête
78 static private function isFirstRun(EntityManager $entityManager): bool
79 {
80 $metadata = $entityManager->getRepository(AppMetadata::class)->find('installed');
81 return !$metadata || $metadata->getValue() !== '1';
82 }
83
84 // protection 2, qui vérifie vraiment que les tables concernées sont vides
85 static private function areTablesEmpty(EntityManager $entityManager): bool
86 {
87 $empty = true;
88 $entities = ['Page', 'Node', 'NodeData'];
89 foreach($entities as $entity){
90 $entity = 'App\Entity\\' . $entity; // nécéssaire quand on insère le nom avec une variable
91
92 if($entityManager
93 ->createQuery("SELECT e FROM $entity e")
94 ->setMaxResults(1)
95 ->getOneOrNullResult()){
96 $empty = false;
97 }
98 }
99
100 // cas anormal détecté, on remet en place la clé "installed"
101 if(!$empty){
102 self::preventReinstallation($entityManager);
103 }
104
105 return $empty;
106 }
107
108 // met en place la protection
109 static private function preventReinstallation(EntityManager $entityManager): void
110 {
111 $metadata = $entityManager->getRepository(AppMetadata::class)->find('installed');
112 if($metadata){
113 $metadata->setValue('1');
114 }
115 else{
116 $metadata = new AppMetadata('installed', '1');
117 $entityManager->persist($metadata);
118 }
119 $entityManager->flush();
120 }
121
122 static public function fillStartingDatabase(EntityManager $entityManager): void
123 {
124 if(!Installation::isFirstRun($entityManager)){
125 return;
126 }
127
128 // la BDD n'est pas vierge, on ne touche à rien
129 if(!self::areTablesEmpty($entityManager)){
130 return;
131 }
132
133 /* -- table page -- */
134 // paramètres: name_page, end_of_path, reachable, in_menu, hidden, position, parent
135 $accueil = new Page('Accueil', 'accueil', "Page d'accueil", true, true, false, 1, NULL);
136 $article = new Page('Article', 'article', "", true, false, false, NULL, NULL);
137 $connection = new Page('Connexion', 'connection', "Connexion", true, false, false, NULL, NULL);
138 $my_account = new Page('Mon compte', 'user_edit', "Mon compte", true, false, false, NULL, NULL);
139 $menu_paths = new Page("Menu et chemins", 'menu_paths', "Menu et chemins", true, false, false, NULL, NULL);
140 $menu_paths->addCSS('menu');
141 $menu_paths->addJS('menu');
142 $new_page = new Page('Nouvelle page', 'new_page', "Nouvelle page", true, false, false, NULL, NULL);
143 $new_page->addCSS('new_page');
144 $new_page->addJS('new_page');
145 $emails = new Page("Courriels", 'emails', "Consulter les courriels en base de données", true, false, false, NULL, NULL);
146 $emails->addCSS('show_emails');
147 $emails->addJS('form');
148
149 /* -- table node -- */
150 // paramètres: name_node, article_timestamp, attributes, position, parent, page, article
151 $head = new Node('head', 1, NULL, NULL, NULL);
152 $header = new Node('header', 2, NULL, NULL, NULL);
153 $nav = new Node('nav', 1, $header, NULL, NULL);
154 $main = new Node('main', 3, NULL, NULL, NULL);
155 $footer = new Node('footer', 4, NULL, NULL, NULL);
156 $breadcrumb = new Node('breadcrumb', 2, $header, NULL, NULL);
157 $login = new Node('login', 1, $main, $connection, NULL);
158 $user_edit = new Node('user_edit', 1, $main, $my_account, NULL);
159 $bloc_edit_menu = new Node('menu', 1, $main, $menu_paths, NULL);
160 $bloc_new_page = new Node('new_page', 1, $main, $new_page, NULL);
161 $bloc_emails = new Node('show_emails', 1, $main, $emails, NULL);
162
163 /* -- table node_data -- */
164 // paramètres: data, node, images
165 $head_data = new NodeData([], $head);
166 $header_data = new NodeData([], $header);
167 $footer_data = new NodeData([], $footer);
168 $emails_data = new NodeData([], $bloc_emails);
169
170 /* -- table page -- */
171 $entityManager->persist($accueil);
172 $entityManager->persist($article);
173 $entityManager->persist($connection);
174 $entityManager->persist($my_account);
175 $entityManager->persist($menu_paths);
176 $entityManager->persist($new_page);
177 $entityManager->persist($emails);
178
179 /* -- table node -- */
180 $entityManager->persist($head);
181 $entityManager->persist($header);
182 $entityManager->persist($nav);
183 $entityManager->persist($main);
184 $entityManager->persist($footer);
185 $entityManager->persist($breadcrumb);
186 $entityManager->persist($login);
187 $entityManager->persist($user_edit);
188 $entityManager->persist($bloc_edit_menu);
189 $entityManager->persist($bloc_new_page);
190 $entityManager->persist($bloc_emails);
191
192 /* -- table node_data -- */
193 $entityManager->persist($head_data);
194 $entityManager->persist($header_data);
195 $entityManager->persist($footer_data);
196 $entityManager->persist($emails_data);
197
198 $entityManager->flush();
199
200 // empêcher la réutilisation de cette fonction
201 self::preventReinstallation($entityManager);
202
203 // fin de l'installation
204 AppMode::set($entityManager, 'run');
205
206 // recharger la page?
207 //header('Location: ' . new URL);
208 }
209} \ No newline at end of file
diff --git a/src/Security.php b/src/service/Security.php
index c825994..356f4f4 100644
--- a/src/Security.php
+++ b/src/service/Security.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/Security.php 2// src/service/Security.php
3// 3//
4// htmlawed nettoie les entrées de l'utilisateur, en particulier le html de l'éditeur 4// htmlawed nettoie les entrées de l'utilisateur, en particulier le html de l'éditeur
5 5
diff --git a/src/URL.php b/src/service/URL.php
index a6d6379..5bd2594 100644
--- a/src/URL.php
+++ b/src/service/URL.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/URL.php 2// src/service/URL.php
3 3
4declare(strict_types=1); 4declare(strict_types=1);
5 5
diff --git a/src/router.php b/src/service/router.php
index ff219da..fc6b028 100644
--- a/src/router.php
+++ b/src/service/router.php
@@ -1,5 +1,5 @@
1<?php 1<?php
2// src/router.php 2// src/service/router.php
3// 3//
4/* fonctionnement: 4/* fonctionnement:
5=> 1er test, méthode http: GET, POST ou autre chose 5=> 1er test, méthode http: GET, POST ou autre chose
@@ -8,7 +8,7 @@
8"application/json" = requête AJAX avec fetch() 8"application/json" = requête AJAX avec fetch()
9"multipart/form-data" = upload d'image par tinymce 9"multipart/form-data" = upload d'image par tinymce
10$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' requête AJAX xhs, non utilisée 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 11=> 3ème test, comme le 2ème test mais uniquement si IS_ADMIN est vrai
12*/ 12*/
13 13
14declare(strict_types=1); 14declare(strict_types=1);
@@ -39,12 +39,12 @@ if($request->getMethod() === 'GET'){
39 } 39 }
40 40
41 // pages interdites 41 // pages interdites
42 if(!$_SESSION['admin'] && in_array(CURRENT_PAGE, ['menu_paths', 'new_page', 'user_edit', 'emails'])){ 42 if(!IS_ADMIN && in_array(CURRENT_PAGE, ['menu_paths', 'new_page', 'user_edit', 'emails'])){
43 header('Location: ' . new URL); 43 header('Location: ' . new URL);
44 die; 44 die;
45 } 45 }
46 46
47 if($_SESSION['admin'] === true){ 47 if(IS_ADMIN === true){
48 // ... 48 // ...
49 } 49 }
50 50
@@ -59,7 +59,7 @@ elseif($request->getMethod() === 'POST'){
59 59
60 // table "user" vide 60 // table "user" vide
61 if(!UserController::existUsers($entityManager)){ 61 if(!UserController::existUsers($entityManager)){
62 UserController::createUser($entityManager); 62 UserController::createAdminUser($entityManager);
63 } 63 }
64 64
65 // requêtes JSON avec fetch() 65 // requêtes JSON avec fetch()
@@ -86,7 +86,7 @@ elseif($request->getMethod() === 'POST'){
86 } 86 }
87 87
88 88
89 if($_SESSION['admin'] === true) 89 if(IS_ADMIN === true)
90 { 90 {
91 /* -- requêtes AJAX -- */ 91 /* -- requêtes AJAX -- */
92 92
diff --git a/src/service/session.php b/src/service/session.php
new file mode 100644
index 0000000..57f2143
--- /dev/null
+++ b/src/service/session.php
@@ -0,0 +1,86 @@
1<?php
2// src/service/session.php
3
4// à voir si c'est mieux avec:
5//use Symfony\Component\HttpFoundation\Session\Session;
6
7
8ini_set('session.cookie_samesite', 'Strict');
9ini_set('session.cookie_httponly', 'On');
10ini_set('session.use_strict_mode', 'On');
11ini_set('session.cookie_secure', 'On');
12session_start();
13validateSession($entityManager);
14
15// note: session_regenerate_id(true) se trouve dans UserController::connect
16
17function validateSession($entityManager): void
18{
19 if(defined('IS_ADMIN')){
20 return;
21 }
22
23 $is_admin = false;
24
25 if(isset($_SESSION['user']['id'])){
26 $user = UserController::getUserById($_SESSION['user']['id'], $entityManager);
27
28 // visiteur normal
29 if(!$user){
30 session_unset();
31 session_destroy();
32 header('Location: ' . new URL(['message' => 'session_invalide']));
33 die;
34 }
35
36 // MAJ de la session avec CERTAINES données
37 $_SESSION['user']['username'] = $user->getLogin();
38 $_SESSION['user']['role'] = $user->getRole();
39
40 $is_admin = $user->getRole() === 'admin';
41 }
42
43 define('IS_ADMIN', $is_admin);
44
45 // si on a un jour besoin d'une variable globale au lieu d'une constante
46 //$GLOBALS['is_admin'] = $is_admin; // version modifiable 1
47 /*function isAdmin(): bool { // version modifiable 2
48 return $_SESSION['user']['role'] ?? null === 'admin';
49 }*/
50
51
52 // => système de cache à ajouter pour ne pas lire la BDD à chaque fois
53 //remplacer ce qui est en haut
54 /*$user = $_SESSION['user'] ?? null;
55 if (!$user) {
56 // visiteur
57 }
58 // Vérification périodique (ex: toutes les 5 minutes)
59 if (time() - $user['last_check'] > 300) {
60 $user = UserController::getUserById($user['id'], $entityManager);
61 if (!$user) {
62 session_destroy();
63 header('Location: /login.php');
64 exit;
65 }
66 // cache pour ne pas avoir à lire la BDD à chaque page
67 $_SESSION['user'] = [
68 'id' => $user['id'],
69 'role' => $user['role'],
70 'username' => $user['username'],
71 'last_check' => time()
72 ];
73 $user = $_SESSION['user'];
74 }
75 $is_admin = ($user['role'] === 'admin');*/
76
77
78 // améliorations possibles: ajouter expiration automatique + protection contre vol de session (IP / user-agent) sans casser ton app.
79}
80
81// nettoyage complet
82/*function cleanSession(){
83 unset($_SESSION['user']); // mémoire vive
84 session_destroy(); // fichier côté serveur
85 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
86}*/ \ No newline at end of file
diff --git a/src/view/CalendarBuilder.php b/src/view/CalendarBuilder.php
index bdabcd2..0c0006d 100644
--- a/src/view/CalendarBuilder.php
+++ b/src/view/CalendarBuilder.php
@@ -12,7 +12,7 @@ class CalendarBuilder extends AbstractBuilder
12 parent::__construct($node); 12 parent::__construct($node);
13 $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; 13 $viewFile = self::VIEWS_PATH . $node->getName() . '.php';
14 14
15 $calendar_js_file = $_SESSION['admin'] ? 'calendar_admin' : 'calendar'; 15 $calendar_js_file = IS_ADMIN ? 'calendar_admin' : 'calendar';
16 16
17 if(file_exists($viewFile)) 17 if(file_exists($viewFile))
18 { 18 {
diff --git a/src/view/FooterBuilder.php b/src/view/FooterBuilder.php
index 8d24f25..f1623e7 100644
--- a/src/view/FooterBuilder.php
+++ b/src/view/FooterBuilder.php
@@ -27,7 +27,7 @@ class FooterBuilder extends AbstractBuilder
27 $breadcrumb = $this->html; 27 $breadcrumb = $this->html;
28 28
29 $empty_admin_zone = ''; 29 $empty_admin_zone = '';
30 if($_SESSION['admin']) 30 if(IS_ADMIN)
31 { 31 {
32 // données du footer 32 // données du footer
33 $admin_footer_name = '<input type="text" id="footer_name_input" class="hidden" value="' . htmlspecialchars($name ?? '') . '" placeholder="raison sociale" size="30"> 33 $admin_footer_name = '<input type="text" id="footer_name_input" class="hidden" value="' . htmlspecialchars($name ?? '') . '" placeholder="raison sociale" size="30">
diff --git a/src/view/FormBuilder.php b/src/view/FormBuilder.php
index 6986dea..9a900ce 100644
--- a/src/view/FormBuilder.php
+++ b/src/view/FormBuilder.php
@@ -9,12 +9,10 @@ class FormBuilder extends AbstractBuilder
9{ 9{
10 static private ?Captcha $captcha = null; 10 static private ?Captcha $captcha = null;
11 11
12 public function __construct(Node $node) 12 public function __construct(Node $node){
13 {
14 parent::__construct($node); 13 parent::__construct($node);
15 14
16 if(!empty($node->getNodeData()->getData())) 15 if(!empty($node->getNodeData()->getData())){
17 {
18 extract($node->getNodeData()->getData()); 16 extract($node->getNodeData()->getData());
19 } 17 }
20 18
@@ -34,8 +32,7 @@ class FormBuilder extends AbstractBuilder
34 $retention_period_sensible = $this->getRetentionPeriod($retention_period_sensible ?? null, App\Entity\Email::DEFAULT_RETENTION_PERIOD_SENSITIVE); 32 $retention_period_sensible = $this->getRetentionPeriod($retention_period_sensible ?? null, App\Entity\Email::DEFAULT_RETENTION_PERIOD_SENSITIVE);
35 33
36 $admin_content = ''; 34 $admin_content = '';
37 if($_SESSION['admin']) 35 if(IS_ADMIN){
38 {
39 ob_start(); 36 ob_start();
40 require self::VIEWS_PATH . 'form_admin.php'; 37 require self::VIEWS_PATH . 'form_admin.php';
41 $admin_content = ob_get_clean(); 38 $admin_content = ob_get_clean();
diff --git a/src/view/GaleryBuilder.php b/src/view/GaleryBuilder.php
index 749cb30..019a2c7 100644
--- a/src/view/GaleryBuilder.php
+++ b/src/view/GaleryBuilder.php
@@ -21,7 +21,7 @@ class GaleryBuilder extends AbstractBuilder
21 21
22 // ajouter un article 22 // ajouter un article
23 $new_article = ''; 23 $new_article = '';
24 if($_SESSION['admin']) 24 if(IS_ADMIN)
25 { 25 {
26 $id = 'n' . $this->id_node; 26 $id = 'n' . $this->id_node;
27 $js = 'onclick="openEditor(\'' . $id . '\')"'; 27 $js = 'onclick="openEditor(\'' . $id . '\')"';
diff --git a/src/view/HeadBuilder.php b/src/view/HeadBuilder.php
index 76d8d9d..fe57b55 100644
--- a/src/view/HeadBuilder.php
+++ b/src/view/HeadBuilder.php
@@ -32,7 +32,7 @@ class HeadBuilder extends AbstractBuilder
32 $js .= self::insertJS('modif_page'); 32 $js .= self::insertJS('modif_page');
33 } 33 }
34 34
35 if($_SESSION['admin']){ 35 if(IS_ADMIN){
36 // édition éléments sur toutes les pages (header, footer et favicon) 36 // édition éléments sur toutes les pages (header, footer et favicon)
37 $js .= self::insertJS('Input'); 37 $js .= self::insertJS('Input');
38 38
diff --git a/src/view/HeaderBuilder.php b/src/view/HeaderBuilder.php
index 6934e10..bfd5963 100644
--- a/src/view/HeaderBuilder.php
+++ b/src/view/HeaderBuilder.php
@@ -52,7 +52,7 @@ class HeaderBuilder extends AbstractBuilder
52 $social_networks = ''; 52 $social_networks = '';
53 53
54 // boutons mode admin 54 // boutons mode admin
55 if($_SESSION['admin']){ 55 if(IS_ADMIN){
56 // assets dans classe header_additional_inputs 56 // assets dans classe header_additional_inputs
57 $admin_head_favicon = '<input type="file" id="head_favicon_input" class="hidden" accept="image/png, image/jpeg, image/gif, image/webp, image/tiff, image/x-icon, image/bmp"> 57 $admin_head_favicon = '<input type="file" id="head_favicon_input" class="hidden" accept="image/png, image/jpeg, image/gif, image/webp, image/tiff, image/x-icon, image/bmp">
58 <button id="head_favicon_open" onclick="head_favicon.open()"><img id="head_favicon_content" class="action_icon"> Favicon</button> 58 <button id="head_favicon_open" onclick="head_favicon.open()"><img id="head_favicon_content" class="action_icon"> Favicon</button>
diff --git a/src/view/LoginBuilder.php b/src/view/LoginBuilder.php
index 639f953..479398c 100644
--- a/src/view/LoginBuilder.php
+++ b/src/view/LoginBuilder.php
@@ -10,7 +10,7 @@ class LoginBuilder extends AbstractBuilder
10 public function __construct(Node $node) 10 public function __construct(Node $node)
11 { 11 {
12 // déjà connecté? 12 // déjà connecté?
13 if($_SESSION['admin']) 13 if(IS_ADMIN)
14 { 14 {
15 header('Location: ' . new URL); 15 header('Location: ' . new URL);
16 die; 16 die;
diff --git a/src/view/MainBuilder.php b/src/view/MainBuilder.php
index 332efa5..b488703 100644
--- a/src/view/MainBuilder.php
+++ b/src/view/MainBuilder.php
@@ -40,7 +40,7 @@ class MainBuilder extends AbstractBuilder
40 } 40 }
41 else{ 41 else{
42 // si action = "modif_page", affiche des commandes supplémentaires 42 // si action = "modif_page", affiche des commandes supplémentaires
43 if($_SESSION['admin'] && self::$modif_mode){ 43 if(IS_ADMIN && self::$modif_mode){
44 // ajouter un contrôle du champ in_menu 44 // ajouter un contrôle du champ in_menu
45 $this->viewEditBlocks($node); 45 $this->viewEditBlocks($node);
46 } 46 }
diff --git a/src/view/MenuBuilder.php b/src/view/MenuBuilder.php
index b8e9396..41ee189 100644
--- a/src/view/MenuBuilder.php
+++ b/src/view/MenuBuilder.php
@@ -20,7 +20,7 @@ class MenuBuilder extends AbstractBuilder
20 20
21 if(file_exists($viewFile)) 21 if(file_exists($viewFile))
22 { 22 {
23 if($_SESSION['admin']){ 23 if(IS_ADMIN){
24 $this->unfoldMenu(Model::$menu); 24 $this->unfoldMenu(Model::$menu);
25 25
26 if($template){ 26 if($template){
diff --git a/src/view/NewBuilder.php b/src/view/NewBuilder.php
index a31a1c4..7459cc8 100644
--- a/src/view/NewBuilder.php
+++ b/src/view/NewBuilder.php
@@ -75,7 +75,7 @@ class NewBuilder extends AbstractBuilder
75 $article_buttons = ''; 75 $article_buttons = '';
76 $date_buttons = ''; 76 $date_buttons = '';
77 $admin_buttons = ''; 77 $admin_buttons = '';
78 if($_SESSION['admin']){ 78 if(IS_ADMIN){
79 if(CURRENT_PAGE === 'article'){ 79 if(CURRENT_PAGE === 'article'){
80 $title_js = 'onclick="openEditor(\'' . $id_title . '\')"'; 80 $title_js = 'onclick="openEditor(\'' . $id_title . '\')"';
81 $modify_title = '<p id="edit-' . $id_title . '"><button ' . $title_js . '><img class="action_icon" src="assets/edit.svg">Titre</button></p>' . "\n"; 81 $modify_title = '<p id="edit-' . $id_title . '"><button ' . $title_js . '><img class="action_icon" src="assets/edit.svg">Titre</button></p>' . "\n";
diff --git a/src/view/NewPageBuilder.php b/src/view/NewPageBuilder.php
index d519a22..0a3a137 100644
--- a/src/view/NewPageBuilder.php
+++ b/src/view/NewPageBuilder.php
@@ -18,7 +18,7 @@ class NewPageBuilder extends AbstractBuilder
18 //parent::__construct($node); 18 //parent::__construct($node);
19 $viewFile = self::VIEWS_PATH . $node->getName() . '.php'; 19 $viewFile = self::VIEWS_PATH . $node->getName() . '.php';
20 20
21 if(isset($_SESSION['admin']) && $_SESSION['admin'] && file_exists($viewFile)) 21 if(IS_ADMIN && file_exists($viewFile))
22 { 22 {
23 /*if(!empty($node->getNodeData()->getData())) 23 /*if(!empty($node->getNodeData()->getData()))
24 { 24 {
diff --git a/src/view/NewsBlockBuilder.php b/src/view/NewsBlockBuilder.php
index 4c7c4ec..f1fe12b 100644
--- a/src/view/NewsBlockBuilder.php
+++ b/src/view/NewsBlockBuilder.php
@@ -32,7 +32,7 @@ class NewsBlockBuilder extends AbstractBuilder
32 32
33 // ajouter un article 33 // ajouter un article
34 $new_article = ''; 34 $new_article = '';
35 if($_SESSION['admin']) 35 if(IS_ADMIN)
36 { 36 {
37 $id = 'n' . $this->id_node; 37 $id = 'n' . $this->id_node;
38 38
diff --git a/src/view/PostBlockBuilder.php b/src/view/PostBlockBuilder.php
index ba4de12..c6094e8 100644
--- a/src/view/PostBlockBuilder.php
+++ b/src/view/PostBlockBuilder.php
@@ -33,7 +33,7 @@ class PostBlockBuilder extends AbstractBuilder
33 // ajouter un article 33 // ajouter un article
34 // => fait un peu double emploi avec PostBuilder 34 // => fait un peu double emploi avec PostBuilder
35 $new_article = ''; 35 $new_article = '';
36 if($_SESSION['admin']) 36 if(IS_ADMIN)
37 { 37 {
38 $id = 'n' . $this->id_node; 38 $id = 'n' . $this->id_node;
39 39
diff --git a/src/view/PostBuilder.php b/src/view/PostBuilder.php
index de7a818..e0bf985 100644
--- a/src/view/PostBuilder.php
+++ b/src/view/PostBuilder.php
@@ -26,7 +26,7 @@ class PostBuilder extends AbstractBuilder
26 // modifier un article 26 // modifier un article
27 // => fait un peu double emploi avec PostBlockBuilder 27 // => fait un peu double emploi avec PostBlockBuilder
28 $admin_buttons = ''; 28 $admin_buttons = '';
29 if($_SESSION['admin']) 29 if(IS_ADMIN)
30 { 30 {
31 $modify_js = 'onclick="openEditor(\'' . $id . '\')"'; 31 $modify_js = 'onclick="openEditor(\'' . $id . '\')"';
32 $modify_article = '<p id="edit-' . $id . '"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n"; 32 $modify_article = '<p id="edit-' . $id . '"><img class="action_icon" src="assets/edit.svg" ' . $modify_js . '></p>' . "\n";
diff --git a/src/view/UserEditBuilder.php b/src/view/UserEditBuilder.php
index 3604e91..0a347d4 100644
--- a/src/view/UserEditBuilder.php
+++ b/src/view/UserEditBuilder.php
@@ -12,7 +12,7 @@ class UserEditBuilder extends AbstractBuilder
12 public function __construct(Node $node) 12 public function __construct(Node $node)
13 { 13 {
14 // pour éviter les arnaques 14 // pour éviter les arnaques
15 if(!$_SESSION['admin']) 15 if(!IS_ADMIN)
16 { 16 {
17 header('Location: ' . new URL); 17 header('Location: ' . new URL);
18 die; 18 die;
diff --git a/src/view/templates/footer.php b/src/view/templates/footer.php
index 7809818..6450e21 100644
--- a/src/view/templates/footer.php
+++ b/src/view/templates/footer.php
@@ -20,7 +20,7 @@
20 <a href="<?= new URL ?>"><img id="footer_logo_content" src="<?= $footer_logo ?? '' ?>" alt=""></a> 20 <a href="<?= new URL ?>"><img id="footer_logo_content" src="<?= $footer_logo ?? '' ?>" alt=""></a>
21 <?= $admin_footer_logo ?> 21 <?= $admin_footer_logo ?>
22 </div> 22 </div>
23<?php if($_SESSION['admin']){ ?> 23<?php if(IS_ADMIN){ ?>
24 <script> 24 <script>
25 let footer_name = new InputText('footer_name'); 25 let footer_name = new InputText('footer_name');
26 let footer_address = new InputText('footer_address'); 26 let footer_address = new InputText('footer_address');
diff --git a/src/view/templates/header.php b/src/view/templates/header.php
index 8d58dc0..400c7c0 100644
--- a/src/view/templates/header.php
+++ b/src/view/templates/header.php
@@ -42,7 +42,7 @@
42 <?= $breadcrumb ?? '' ?> 42 <?= $breadcrumb ?? '' ?>
43 </div> 43 </div>
44 </div> 44 </div>
45<?php if($_SESSION['admin']){ ?> 45<?php if(IS_ADMIN){ ?>
46 <script> 46 <script>
47 document.getElementById("head_favicon_content").src = window.Config.favicon; 47 document.getElementById("head_favicon_content").src = window.Config.favicon;
48 let head_favicon = new InputFileFavicon('head_favicon'); 48 let head_favicon = new InputFileFavicon('head_favicon');
diff --git a/src/view/templates/maintenance.php b/src/view/templates/maintenance.php
new file mode 100644
index 0000000..217dcb7
--- /dev/null
+++ b/src/view/templates/maintenance.php
@@ -0,0 +1,27 @@
1<?php declare(strict_types=1); ?>
2<!DOCTYPE html>
3<html lang="fr">
4 <head>
5 <meta charset="utf-8">
6 <title>Site en maintenance</title>
7 <link rel="icon" type="" href="">
8 <meta name="description" content="site en maintenance">
9 <meta name="viewport" content="width=device-width">
10 <link rel="stylesheet" href="css/head.css">
11 <link rel="stylesheet" href="css/body.css">
12 <link rel="stylesheet" href="css/foot.css">
13 </head>
14 <body>
15 <main>
16 <p>Le site est en cours de maintenance.</p>
17 <p>Il devrait être de nouveau accessible très bientôt.</p>
18 </main>
19 <footer>
20 <div class="logged_out">
21 <button>
22 <a href="<?= new URL(['page' => 'connection']) ?>">Mode admin</a>
23 </button>
24 </div>
25 </footer>
26 </body>
27</html> \ No newline at end of file
diff --git a/src/view/templates/user_create.php b/src/view/templates/user_create.php
index 8572efe..870b904 100644
--- a/src/view/templates/user_create.php
+++ b/src/view/templates/user_create.php
@@ -27,7 +27,7 @@ $_SESSION['captcha'] = $captcha->getSolution(); // enregistrement de la réponse
27 <main> 27 <main>
28 <section> 28 <section>
29 <h3>Bienvenue.</h3> 29 <h3>Bienvenue.</h3>
30 <p style="text-align: center;">Veuillez choisir les codes que vous utiliserez pour gérer le site.</p> 30 <p style="text-align: center;">Pour commencer, veuillez créer un compte administrateur.</p>
31 <div class="basic_div"> 31 <div class="basic_div">
32 <p style="color: red; font-style: italic;"><?= $error ?></p> 32 <p style="color: red; font-style: italic;"><?= $error ?></p>
33 <form method="post" action="index.php?action=create_user" > 33 <form method="post" action="index.php?action=create_user" >
diff --git a/src/view/templates/user_edit.php b/src/view/templates/user_edit.php
index 28caac4..9191e7d 100644
--- a/src/view/templates/user_edit.php
+++ b/src/view/templates/user_edit.php
@@ -5,7 +5,7 @@
5 <h3>Mon compte</h3> 5 <h3>Mon compte</h3>
6 <div> 6 <div>
7 <img class="user_icon" src="assets/user_hollow.svg"> 7 <img class="user_icon" src="assets/user_hollow.svg">
8 <div><?= $_SESSION['user'] ?></div> 8 <div><?= $_SESSION['user']['username'] ?></div>
9 </div> 9 </div>
10 </div> 10 </div>
11 <div class="user_edit_flex"> 11 <div class="user_edit_flex">