diff options
| author | polo <ordipolo@gmx.fr> | 2026-03-24 22:39:29 +0100 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2026-03-24 22:40:33 +0100 |
| commit | 3b369122645b07b290f7fcc7bccb4787745cd5ea (patch) | |
| tree | 3f9c2d1fbd5fe8b26162202e9b1e6cd5c8a940f6 /src | |
| parent | a70dee9b5021a137ae07041c38921553442b0c11 (diff) | |
| download | cms-3b369122645b07b290f7fcc7bccb4787745cd5ea.tar.gz cms-3b369122645b07b290f7fcc7bccb4787745cd5ea.tar.bz2 cms-3b369122645b07b290f7fcc7bccb4787745cd5ea.zip | |
mode maintenance, optimisation moins de contrôles en mode run, dossier service et déplacement fichiers, sessions et entité User préparées à l'implémentation hypothétique des rôles, entité AppMetadata, meilleure sécurité de fillStartingDatabase
Diffstat (limited to 'src')
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 | |||
| 4 | declare(strict_types=1); | ||
| 5 | |||
| 6 | use App\Entity\Page; | ||
| 7 | use App\Entity\Node; | ||
| 8 | use App\Entity\NodeData; | ||
| 9 | use App\Entity\Asset; | ||
| 10 | use Doctrine\Common\Collections\ArrayCollection; | ||
| 11 | use Doctrine\ORM\EntityManager; | ||
| 12 | |||
| 13 | function 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 | |||
| 36 | function 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 | ||
| 92 | function 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 | |||
| 6 | declare(strict_types=1); | ||
| 7 | |||
| 8 | namespace App\Entity; | ||
| 9 | |||
| 10 | use Doctrine\ORM\Mapping as ORM; | ||
| 11 | |||
| 12 | #[ORM\Entity] | ||
| 13 | #[ORM\Table(name: TABLE_PREFIX . "app_metadata")] | ||
| 14 | class 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 | |||
| 6 | declare(strict_types=1); | ||
| 7 | |||
| 8 | use App\Entity\AppMetadata; | ||
| 9 | use Doctrine\ORM\EntityManager; | ||
| 10 | |||
| 11 | class 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 | ||
| 4 | declare(strict_types=1); | 4 | declare(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 | ||
| 4 | declare(strict_types=1); | 4 | declare(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 | ||
| 4 | declare(strict_types=1); | 4 | declare(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 | |||
| 4 | declare(strict_types=1); | ||
| 5 | |||
| 6 | use App\Entity\AppMetadata; | ||
| 7 | use App\Entity\Page; | ||
| 8 | use App\Entity\Node; | ||
| 9 | use App\Entity\NodeData; | ||
| 10 | use Doctrine\ORM\EntityManager; | ||
| 11 | |||
| 12 | class 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 | ||
| 4 | declare(strict_types=1); | 4 | declare(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 | ||
| 14 | declare(strict_types=1); | 14 | declare(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 | |||
| 8 | ini_set('session.cookie_samesite', 'Strict'); | ||
| 9 | ini_set('session.cookie_httponly', 'On'); | ||
| 10 | ini_set('session.use_strict_mode', 'On'); | ||
| 11 | ini_set('session.cookie_secure', 'On'); | ||
| 12 | session_start(); | ||
| 13 | validateSession($entityManager); | ||
| 14 | |||
| 15 | // note: session_regenerate_id(true) se trouve dans UserController::connect | ||
| 16 | |||
| 17 | function 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"> |
