diff options
| author | polo <ordipolo@gmx.fr> | 2025-08-17 19:46:20 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2025-08-17 19:46:20 +0200 |
| commit | dba24b8c18aed84a71c3169b2df5598d62deab06 (patch) | |
| tree | cf913cd986f01894bc32a71997014434bf3ec7ad | |
| parent | d7468fc363b5d028db84373d4abfa6d7d19bacb9 (diff) | |
| download | cms-dba24b8c18aed84a71c3169b2df5598d62deab06.tar.gz cms-dba24b8c18aed84a71c3169b2df5598d62deab06.tar.bz2 cms-dba24b8c18aed84a71c3169b2df5598d62deab06.zip | |
classe FormValidation et amélioration des envois d'e-mail
| -rw-r--r-- | public/js/form.js | 24 | ||||
| -rw-r--r-- | public/js/main.js | 2 | ||||
| -rw-r--r-- | src/EmailService.php (renamed from src/controller/EmailController.php) | 44 | ||||
| -rw-r--r-- | src/FormValidation.php | 186 | ||||
| -rw-r--r-- | src/controller/ContactFormController.php | 40 | ||||
| -rw-r--r-- | src/controller/UserController.php | 284 | ||||
| -rw-r--r-- | src/router.php | 2 | ||||
| -rw-r--r-- | src/view/UserEditBuilder.php | 8 | ||||
| -rw-r--r-- | src/view/templates/form.php | 8 | ||||
| -rw-r--r-- | src/view/templates/login.php | 1 | ||||
| -rw-r--r-- | src/view/templates/user_create.php | 1 | ||||
| -rw-r--r-- | src/view/templates/user_edit.php | 15 |
12 files changed, 358 insertions, 257 deletions
diff --git a/public/js/form.js b/public/js/form.js index 5c5a164..cf138e6 100644 --- a/public/js/form.js +++ b/public/js/form.js | |||
| @@ -26,6 +26,12 @@ function changeRecipient(id){ | |||
| 26 | }); | 26 | }); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | function checkCase(){ | ||
| 30 | if(document.getElementById('email_address').value.match('[A-Z]')){ | ||
| 31 | toastNotify("Votre e-mail comporte une lettre majuscule, il s'agit probablement d'une erreur."); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 29 | function sendTestEmail(id){ | 35 | function sendTestEmail(id){ |
| 30 | const admin_form = document.querySelector('.admin_form'); | 36 | const admin_form = document.querySelector('.admin_form'); |
| 31 | const test_email_success = document.querySelector('.test_email_success'); | 37 | const test_email_success = document.querySelector('.test_email_success'); |
| @@ -61,15 +67,21 @@ function sendTestEmail(id){ | |||
| 61 | } | 67 | } |
| 62 | 68 | ||
| 63 | function sendVisitorEmail(id){ | 69 | function sendVisitorEmail(id){ |
| 64 | const send_email_success = document.querySelector('.send_email_success'); | ||
| 65 | send_email_success.innerHTML = 'Envoi en cours, veuillez patienter'; | ||
| 66 | send_email_success.style.backgroundColor = 'yellow'; | ||
| 67 | |||
| 68 | const email_name = document.getElementById('email_name').value; | 70 | const email_name = document.getElementById('email_name').value; |
| 69 | const email_address = document.getElementById('email_address').value; | 71 | const email_address = document.getElementById('email_address').value; |
| 70 | const email_message = document.getElementById('email_message').value; | 72 | const email_message = document.getElementById('email_message').value; |
| 71 | const email_captcha = document.getElementById('email_captcha').value; | 73 | const email_captcha = document.getElementById('email_captcha').value; |
| 72 | const email_hidden = document.getElementById('email_hidden').value; | 74 | const email_hidden = document.getElementById('email_hidden').value; |
| 75 | const send_email_success = document.querySelector('.send_email_success'); | ||
| 76 | |||
| 77 | if(email_name === '' || email_address === '' || email_message === '' || email_captcha === ''){ | ||
| 78 | toastNotify('Veuillez remplir tous les champs.'); | ||
| 79 | return; | ||
| 80 | } | ||
| 81 | else{ | ||
| 82 | send_email_success.innerHTML = 'Envoi en cours, veuillez patienter'; | ||
| 83 | send_email_success.style.backgroundColor = 'yellow'; | ||
| 84 | } | ||
| 73 | 85 | ||
| 74 | fetch('index.php?action=send_email', { | 86 | fetch('index.php?action=send_email', { |
| 75 | method: 'POST', | 87 | method: 'POST', |
| @@ -90,7 +102,7 @@ function sendVisitorEmail(id){ | |||
| 90 | let message; | 102 | let message; |
| 91 | let color; | 103 | let color; |
| 92 | if(data.success){ | 104 | if(data.success){ |
| 93 | message = 'Votre E-mail a été envoyé!'; | 105 | message = 'Votre e-mail a été envoyé!'; |
| 94 | color = 'lawngreen'; | 106 | color = 'lawngreen'; |
| 95 | } | 107 | } |
| 96 | else{ | 108 | else{ |
| @@ -98,8 +110,8 @@ function sendVisitorEmail(id){ | |||
| 98 | color = "orangered" | 110 | color = "orangered" |
| 99 | } | 111 | } |
| 100 | send_email_success.innerHTML = message; | 112 | send_email_success.innerHTML = message; |
| 101 | toastNotify(message); | ||
| 102 | send_email_success.style.backgroundColor = color; | 113 | send_email_success.style.backgroundColor = color; |
| 114 | toastNotify(message); | ||
| 103 | }) | 115 | }) |
| 104 | .catch(error => { | 116 | .catch(error => { |
| 105 | console.error('Erreur:', error); | 117 | console.error('Erreur:', error); |
diff --git a/public/js/main.js b/public/js/main.js index 2ffd33b..4be7843 100644 --- a/public/js/main.js +++ b/public/js/main.js | |||
| @@ -33,7 +33,7 @@ function toastNotify(message) { | |||
| 33 | var toast = document.getElementById('toast'); | 33 | var toast = document.getElementById('toast'); |
| 34 | toast.textContent = message; | 34 | toast.textContent = message; |
| 35 | toast.className = 'toast show'; | 35 | toast.className = 'toast show'; |
| 36 | setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 3000); | 36 | setTimeout(function(){ toast.className = toast.className.replace('show', ''); }, 5000); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | 39 | ||
diff --git a/src/controller/EmailController.php b/src/EmailService.php index 1eea257..c1f74d1 100644 --- a/src/controller/EmailController.php +++ b/src/EmailService.php | |||
| @@ -1,16 +1,16 @@ | |||
| 1 | <?php | 1 | <?php |
| 2 | // src/controller/EmailController.php | 2 | // src/EmailService.php |
| 3 | 3 | ||
| 4 | declare(strict_types=1); | 4 | declare(strict_types=1); |
| 5 | 5 | ||
| 6 | use PHPMailer\PHPMailer\PHPMailer; | 6 | use PHPMailer\PHPMailer\PHPMailer; |
| 7 | use PHPMailer\PHPMailer\Exception; | 7 | //use PHPMailer\PHPMailer\Exception; |
| 8 | use App\Entity\Email; | 8 | use App\Entity\Email; |
| 9 | use Doctrine\ORM\EntityManager; | 9 | use Doctrine\ORM\EntityManager; |
| 10 | 10 | ||
| 11 | class EmailController | 11 | class EmailService |
| 12 | { | 12 | { |
| 13 | static public function send(string $recipient, bool $true_email, string $name = '', string $email = '', string $message = ''): bool | 13 | static public function send(EntityManager $entityManager, string $recipient, bool $true_email, string $name = '', string $email = '', string $message = ''): bool |
| 14 | { | 14 | { |
| 15 | $mail = new PHPMailer(true); // true => exceptions | 15 | $mail = new PHPMailer(true); // true => exceptions |
| 16 | $mail->CharSet = 'UTF-8'; | 16 | $mail->CharSet = 'UTF-8'; |
| @@ -43,7 +43,6 @@ class EmailController | |||
| 43 | $mail->isHTML(true); | 43 | $mail->isHTML(true); |
| 44 | if($true_email){ | 44 | if($true_email){ |
| 45 | $mail->Subject = 'Message envoyé par: ' . $name . ' (' . $email . ') depuis le site web'; | 45 | $mail->Subject = 'Message envoyé par: ' . $name . ' (' . $email . ') depuis le site web'; |
| 46 | |||
| 47 | } | 46 | } |
| 48 | else{ | 47 | else{ |
| 49 | $mail->Subject = "TEST d'un envoi d'e-mail depuis le site web"; | 48 | $mail->Subject = "TEST d'un envoi d'e-mail depuis le site web"; |
| @@ -52,6 +51,12 @@ class EmailController | |||
| 52 | $mail->AltBody = $message; | 51 | $mail->AltBody = $message; |
| 53 | 52 | ||
| 54 | $mail->send(); | 53 | $mail->send(); |
| 54 | |||
| 55 | // copie en BDD | ||
| 56 | $db_email = new Email($email, Config::$email_dest, $message); | ||
| 57 | $entityManager->persist($db_email); | ||
| 58 | $entityManager->flush(); | ||
| 59 | |||
| 55 | return true; | 60 | return true; |
| 56 | } | 61 | } |
| 57 | catch(Exception $e){ | 62 | catch(Exception $e){ |
| @@ -59,33 +64,4 @@ class EmailController | |||
| 59 | //echo "Le message n'a pas pu être envoyé. Erreur : {$mail->ErrorInfo}"; | 64 | //echo "Le message n'a pas pu être envoyé. Erreur : {$mail->ErrorInfo}"; |
| 60 | } | 65 | } |
| 61 | } | 66 | } |
| 62 | |||
| 63 | static public function submit(array $json, EntityManager $entityManager): void | ||
| 64 | { | ||
| 65 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | ||
| 66 | $captcha_try = isset($json['captcha']) ? Captcha::controlInput($json['captcha']) : 0; | ||
| 67 | |||
| 68 | // contrôles des entrées | ||
| 69 | $name = htmlspecialchars(trim($json['name'])); | ||
| 70 | $email = strtolower(htmlspecialchars(trim($json['email']))); | ||
| 71 | $message = htmlspecialchars(trim($json['message'])); | ||
| 72 | |||
| 73 | // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur | ||
| 74 | $form_data = $entityManager->find('App\Entity\NodeData', $json['id']); | ||
| 75 | $recipient = $form_data->getData()['email'] ?? Config::$email_dest; | ||
| 76 | |||
| 77 | if($captcha_try != 0 && $captcha_solution != 0 && ($captcha_try === $captcha_solution) | ||
| 78 | && filter_var($email, FILTER_VALIDATE_EMAIL) && isset($json['hidden']) && empty($json['hidden']) | ||
| 79 | && self::send($recipient, true, $name, $email, $message)) | ||
| 80 | { | ||
| 81 | $db_email = new Email($email, Config::$email_dest, $message); | ||
| 82 | $entityManager->persist($db_email); | ||
| 83 | $entityManager->flush(); | ||
| 84 | echo json_encode(['success' => true]); | ||
| 85 | } | ||
| 86 | else{ | ||
| 87 | echo json_encode(['success' => false]); | ||
| 88 | } | ||
| 89 | die; | ||
| 90 | } | ||
| 91 | } \ No newline at end of file | 67 | } \ No newline at end of file |
diff --git a/src/FormValidation.php b/src/FormValidation.php new file mode 100644 index 0000000..743cd13 --- /dev/null +++ b/src/FormValidation.php | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | <?php | ||
| 2 | // src/FormValidation.php | ||
| 3 | |||
| 4 | class FormValidation | ||
| 5 | { | ||
| 6 | private array $data; // tableau associatif (probablement $_POST) | ||
| 7 | private string $validation_strategy; // à remplacer plus tard par un objet (pattern stratégie) d'interface ValidationStrategy | ||
| 8 | private array $errors; | ||
| 9 | private bool $validated = false; | ||
| 10 | |||
| 11 | public function __construct(array $data, string $validation_strategy){ | ||
| 12 | $this->data = $data; | ||
| 13 | $this->validation_strategy = $validation_strategy; | ||
| 14 | } | ||
| 15 | |||
| 16 | public function validate(): bool | ||
| 17 | { | ||
| 18 | $this->errors = []; | ||
| 19 | |||
| 20 | // pattern stratégie en une seule classe | ||
| 21 | switch($this->validation_strategy){ | ||
| 22 | case 'email': | ||
| 23 | $this->emailStrategy(); | ||
| 24 | break; | ||
| 25 | case 'create_user': | ||
| 26 | $this->createUserStrategy(); | ||
| 27 | break; | ||
| 28 | case 'connection': | ||
| 29 | $this->connectionStrategy(); | ||
| 30 | break; | ||
| 31 | case 'username_update': | ||
| 32 | $this->usernameUpdateStrategy(); | ||
| 33 | break; | ||
| 34 | case 'password_update': | ||
| 35 | $this->passwordUpdateStrategy(); | ||
| 36 | break; | ||
| 37 | default: | ||
| 38 | http_response_code(500); // c'est un peu comme jeter une exception | ||
| 39 | echo json_encode(['success' => false, 'error' => 'server_error']); | ||
| 40 | die; | ||
| 41 | } | ||
| 42 | |||
| 43 | $this->validated = true; | ||
| 44 | return empty($this->errors); | ||
| 45 | } | ||
| 46 | |||
| 47 | public function getErrors(): array | ||
| 48 | { | ||
| 49 | return $this->errors; | ||
| 50 | } | ||
| 51 | |||
| 52 | public function getField(string $field): string | ||
| 53 | { | ||
| 54 | return $this->validated ? $this->data[$field] : ''; | ||
| 55 | } | ||
| 56 | |||
| 57 | // méthodes de validation | ||
| 58 | private function captchaValidate(bool $clean_session = true): void | ||
| 59 | { | ||
| 60 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | ||
| 61 | $captcha_try = isset($this->data['captcha']) ? Captcha::controlInput($this->data['captcha']) : 0; | ||
| 62 | if($clean_session){ | ||
| 63 | unset($_SESSION['captcha']); | ||
| 64 | } | ||
| 65 | |||
| 66 | if($captcha_try == 0){ | ||
| 67 | $error = 'error_non_valid_captcha'; | ||
| 68 | } | ||
| 69 | elseif($captcha_solution == 0){ // ne peut pas arriver, si? | ||
| 70 | $error = 'captcha_server_error'; | ||
| 71 | } | ||
| 72 | elseif($captcha_try !== $captcha_solution){ | ||
| 73 | $this->errors[] = 'bad_solution_captcha'; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | // erreurs à la création des mots de passe | ||
| 78 | static private function removeSpacesTabsCRLF(string $chaine): string | ||
| 79 | { | ||
| 80 | $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !! | ||
| 81 | return(str_replace($cibles, '', $chaine)); | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | // stratégies | ||
| 86 | private function emailStrategy(): void | ||
| 87 | { | ||
| 88 | $this->captchaValidate(false); | ||
| 89 | |||
| 90 | if(!isset($this->data['name']) || empty($this->data['name']) | ||
| 91 | || !isset($this->data['email']) || empty($this->data['email']) | ||
| 92 | || !isset($this->data['message']) || empty($this->data['message']) | ||
| 93 | || !isset($this->data['hidden']) || !empty($this->data['hidden'])){ | ||
| 94 | $this->errors[] = 'missing_fields'; | ||
| 95 | } | ||
| 96 | |||
| 97 | if(!filter_var(trim($this->data['email']), FILTER_VALIDATE_EMAIL)){ | ||
| 98 | $this->errors[] = 'bad_email_address'; | ||
| 99 | } | ||
| 100 | |||
| 101 | $this->data['name'] = htmlspecialchars(trim($this->data['name'])); | ||
| 102 | $this->data['email'] = htmlspecialchars(trim($this->data['email'])); | ||
| 103 | $this->data['message'] = htmlspecialchars($this->data['message']); | ||
| 104 | } | ||
| 105 | private function createUserStrategy(): void | ||
| 106 | { | ||
| 107 | $this->captchaValidate(); | ||
| 108 | |||
| 109 | // test mauvais paramètres | ||
| 110 | if(!isset($this->data['login']) || empty($this->data['login']) | ||
| 111 | || !isset($this->data['password']) || empty($this->data['password']) | ||
| 112 | || !isset($this->data['password_confirmation']) || empty($this->data['password_confirmation']) | ||
| 113 | || !isset($this->data['create_user_hidden']) || !empty($this->data['create_user_hidden'])) | ||
| 114 | { | ||
| 115 | $this->errors[] = 'bad_login_or_password'; | ||
| 116 | } | ||
| 117 | |||
| 118 | if($this->data['password'] !== $this->data['password_confirmation']){ | ||
| 119 | $this->errors[] = 'different_passwords'; | ||
| 120 | } | ||
| 121 | |||
| 122 | if($this->data['login'] !== self::removeSpacesTabsCRLF(htmlspecialchars($this->data['login'])) | ||
| 123 | || $this->data['password'] !== self::removeSpacesTabsCRLF(htmlspecialchars($this->data['password']))){ | ||
| 124 | $this->errors[] = 'forbidden_characters'; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | private function connectionStrategy(): void | ||
| 128 | { | ||
| 129 | $this->captchaValidate(); | ||
| 130 | |||
| 131 | if(!isset($this->data['login']) || empty($this->data['login']) | ||
| 132 | || !isset($this->data['password']) || empty($this->data['password']) | ||
| 133 | || !isset($this->data['connection_hidden']) || !empty($this->data['connection_hidden'])) | ||
| 134 | { | ||
| 135 | $this->errors[] = 'bad_login_or_password'; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | private function usernameUpdateStrategy(): void | ||
| 139 | { | ||
| 140 | $this->captchaValidate(); | ||
| 141 | |||
| 142 | if(!isset($this->data['login']) || empty($this->data['login']) | ||
| 143 | || !isset($this->data['password']) || empty($this->data['password']) | ||
| 144 | || !isset($this->data['new_login']) || empty($this->data['new_login']) | ||
| 145 | || !isset($this->data['modify_username_hidden']) || !empty($this->data['modify_username_hidden'])) | ||
| 146 | { | ||
| 147 | $this->errors[] = 'bad_login_or_password'; | ||
| 148 | } | ||
| 149 | |||
| 150 | $new_login = self::removeSpacesTabsCRLF(htmlspecialchars($this->data['new_login'])); | ||
| 151 | if($new_login !== $this->data['new_login']){ | ||
| 152 | $this->errors[] = 'forbidden_characters'; | ||
| 153 | } | ||
| 154 | |||
| 155 | if($this->data['login'] !== $_SESSION['user']){ | ||
| 156 | $this->errors[] = 'bad_login_or_password'; | ||
| 157 | } | ||
| 158 | if($this->data['login'] === $new_login){ | ||
| 159 | $this->errors[] = 'same_username_as_before'; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | private function passwordUpdateStrategy(): void | ||
| 163 | { | ||
| 164 | $this->captchaValidate(); | ||
| 165 | |||
| 166 | if(!isset($this->data['login']) || empty($this->data['login']) | ||
| 167 | || !isset($this->data['password']) || empty($this->data['password']) | ||
| 168 | || !isset($this->data['new_password']) || empty($this->data['new_password']) | ||
| 169 | || !isset($this->data['modify_password_hidden']) || !empty($this->data['modify_password_hidden'])) | ||
| 170 | { | ||
| 171 | $this->errors[] = 'bad_login_or_password'; | ||
| 172 | } | ||
| 173 | |||
| 174 | $new_password = self::removeSpacesTabsCRLF(htmlspecialchars($this->data['new_password'])); | ||
| 175 | if($new_password !== $this->data['new_password']){ | ||
| 176 | $this->errors[] = 'forbidden_characters'; | ||
| 177 | } | ||
| 178 | |||
| 179 | if($this->data['login'] !== $_SESSION['user']){ | ||
| 180 | $this->errors[] = 'bad_login_or_password'; | ||
| 181 | } | ||
| 182 | if($this->data['password'] === $new_password){ | ||
| 183 | $this->errors[] = 'same_password_as_before'; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } \ No newline at end of file | ||
diff --git a/src/controller/ContactFormController.php b/src/controller/ContactFormController.php index 9d62a77..dcea868 100644 --- a/src/controller/ContactFormController.php +++ b/src/controller/ContactFormController.php | |||
| @@ -27,17 +27,53 @@ class ContactFormController | |||
| 27 | } | 27 | } |
| 28 | die; | 28 | die; |
| 29 | } | 29 | } |
| 30 | static public function sendVisitorEmail(EntityManager $entityManager, array $json): void | ||
| 31 | { | ||
| 32 | $form = new FormValidation($json, 'email'); | ||
| 33 | |||
| 34 | $error = ''; | ||
| 35 | if($form->validate()){ | ||
| 36 | // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur | ||
| 37 | $form_data = $entityManager->find('App\Entity\NodeData', $json['id']); | ||
| 38 | if($form_data === null){ | ||
| 39 | http_response_code(500); | ||
| 40 | echo json_encode(['success' => false, 'error' => 'server_error']); | ||
| 41 | die; | ||
| 42 | } | ||
| 43 | $recipient = $form_data->getData()['email'] ?? Config::$email_dest; | ||
| 44 | |||
| 45 | if(!EmailService::send($entityManager, $recipient, true, $form->getField('name'), $form->getField('email'), $form->getField('message'))){ | ||
| 46 | $error = 'email_not_sent'; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | else{ | ||
| 50 | $error = $form->getErrors()[0]; // la 1ère erreur sera affichée | ||
| 51 | } | ||
| 52 | |||
| 53 | if(empty($error)){ | ||
| 54 | echo json_encode(['success' => true]); | ||
| 55 | } | ||
| 56 | else{ | ||
| 57 | echo json_encode(['success' => false, 'error' => $error]); | ||
| 58 | } | ||
| 59 | die; | ||
| 60 | } | ||
| 30 | static public function sendTestEmail(EntityManager $entityManager, array $json): void | 61 | static public function sendTestEmail(EntityManager $entityManager, array $json): void |
| 31 | { | 62 | { |
| 32 | // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur | 63 | // destinataire = e-mail par défaut dans config.ini OU choisi par l'utilisateur |
| 33 | $form_data = $entityManager->find('App\Entity\NodeData', $json['id']); | 64 | $form_data = $entityManager->find('App\Entity\NodeData', $json['id']); |
| 65 | if($form_data === null){ | ||
| 66 | http_response_code(500); | ||
| 67 | echo json_encode(['success' => false, 'error' => 'server_error']); | ||
| 68 | die; | ||
| 69 | } | ||
| 34 | $recipient = $form_data->getData()['email'] ?? Config::$email_dest; | 70 | $recipient = $form_data->getData()['email'] ?? Config::$email_dest; |
| 35 | 71 | ||
| 36 | if(EmailController::send($recipient, false, 'nom du visiteur', 'adresse@du_visiteur.fr', "TEST d'un envoi d'e-mail depuis le site web")){ | 72 | if(EmailService::send($entityManager, $recipient, false, 'nom du visiteur', 'adresse@du_visiteur.fr', "TEST d'un envoi d'e-mail depuis le site web")){ |
| 37 | echo json_encode(['success' => true]); | 73 | echo json_encode(['success' => true]); |
| 38 | } | 74 | } |
| 39 | else{ | 75 | else{ |
| 40 | echo json_encode(['success' => false]); | 76 | echo json_encode(['success' => false, 'error' => 'email_not_sent']); |
| 41 | } | 77 | } |
| 42 | die; | 78 | die; |
| 43 | } | 79 | } |
diff --git a/src/controller/UserController.php b/src/controller/UserController.php index 50e8bf7..f0880bb 100644 --- a/src/controller/UserController.php +++ b/src/controller/UserController.php | |||
| @@ -1,7 +1,15 @@ | |||
| 1 | <?php | 1 | <?php |
| 2 | // src/controller/PasswordController.php | 2 | // src/controller/UserController.php |
| 3 | // | 3 | // |
| 4 | // test mot de passe et captcha | 4 | /* actuellement un fourre-tout de méthodes en rapport avec les utilisateurs |
| 5 | pour l'améliorer on pourrait appliquer le principe de reponsabilité unique | ||
| 6 | => UserController devrait se limiter à gérer des requêtes et réponses (changement transparent pour le routeur) | ||
| 7 | il instancierait un classe correspondant au formulaire (prend POST et SESSION) et une classe "métier" UserService | ||
| 8 | => UserService contiendrait des méthodes utilisant l'objet formulaire pour agir sur la BDD | ||
| 9 | => les formulaires peuvent tenir dans une classe "UserUpdateForm" avec des stratégies ou plusieurs, les données y sont validées | ||
| 10 | => il est aussi possible de découper UserController en contrôleurs par fonctionnalité: | ||
| 11 | Auth (connexion, deconnexion), User (infos, choix photo), Account (créer, supprimer compte), Avatar (upload photo...) | ||
| 12 | */ | ||
| 5 | 13 | ||
| 6 | declare(strict_types=1); | 14 | declare(strict_types=1); |
| 7 | 15 | ||
| @@ -11,6 +19,7 @@ use App\Entity\Log; | |||
| 11 | 19 | ||
| 12 | class UserController | 20 | class UserController |
| 13 | { | 21 | { |
| 22 | // account | ||
| 14 | static public function existUsers(EntityManager $entityManager): bool | 23 | static public function existUsers(EntityManager $entityManager): bool |
| 15 | { | 24 | { |
| 16 | // optimiser ça si possible, on veut juste savoir si la table est vide ou non | 25 | // optimiser ça si possible, on veut juste savoir si la table est vide ou non |
| @@ -28,71 +37,34 @@ class UserController | |||
| 28 | } | 37 | } |
| 29 | } | 38 | } |
| 30 | 39 | ||
| 40 | // account | ||
| 31 | static public function createUser(EntityManager $entityManager) | 41 | static public function createUser(EntityManager $entityManager) |
| 32 | { | 42 | { |
| 33 | // test mauvais paramètres | ||
| 34 | if(!isset($_POST['login']) || empty($_POST['login']) | ||
| 35 | || !isset($_POST['password']) || empty($_POST['password']) | ||
| 36 | || !isset($_POST['password_confirmation']) || empty($_POST['password_confirmation']) | ||
| 37 | || !isset($_POST['create_user_hidden']) || !empty($_POST['create_user_hidden'])) | ||
| 38 | { | ||
| 39 | header('Location: ' . new URL); | ||
| 40 | die; | ||
| 41 | } | ||
| 42 | |||
| 43 | unset($_SESSION['user']); | 43 | unset($_SESSION['user']); |
| 44 | 44 | ||
| 45 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | 45 | $form = new FormValidation($_POST, 'create_user'); |
| 46 | $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; | ||
| 47 | unset($_SESSION['captcha']); | ||
| 48 | 46 | ||
| 47 | $url = new URL; | ||
| 49 | $error = ''; | 48 | $error = ''; |
| 50 | if($captcha_try == 0) | 49 | if($form->validate()){ |
| 51 | { | 50 | $password = password_hash($_POST['password'], PASSWORD_DEFAULT); |
| 52 | $error = 'error_non_valid_captcha'; | 51 | $user = new App\Entity\User($_POST['login'], $password); |
| 53 | } | 52 | $entityManager->persist($user); |
| 54 | elseif($captcha_solution == 0) // ne peut pas arriver, si? | 53 | $entityManager->flush(); |
| 55 | { | ||
| 56 | $error = 'captcha_server_error'; | ||
| 57 | } | ||
| 58 | elseif($captcha_try != $captcha_solution) // le test! | ||
| 59 | { | ||
| 60 | $error = 'bad_solution_captcha'; | ||
| 61 | } | 54 | } |
| 62 | elseif($_POST['password'] !== $_POST['password_confirmation']) | 55 | else{ |
| 63 | { | 56 | $error = $form->getErrors()[0]; // la 1ère erreur sera affichée |
| 64 | $error = 'different_passwords'; | ||
| 65 | } | 57 | } |
| 66 | else | 58 | |
| 67 | { | 59 | if(!empty($error)){ |
| 68 | $login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['login'])); | 60 | $url->addParams(['error' => $error]); |
| 69 | $password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['password'])); | ||
| 70 | |||
| 71 | // self::removeSpacesTabsCRLF prévient la validation par erreur d'une chaine "vide" | ||
| 72 | |||
| 73 | // conformité | ||
| 74 | if(!empty($password) && !empty($login) | ||
| 75 | && $password === $_POST['password'] && $login === $_POST['login']) | ||
| 76 | { | ||
| 77 | // enregistrement et redirection | ||
| 78 | $password = password_hash($password, PASSWORD_DEFAULT); | ||
| 79 | $user = new App\Entity\User($login, $password); | ||
| 80 | $entityManager->persist($user); | ||
| 81 | $entityManager->flush(); | ||
| 82 | |||
| 83 | header('Location: ' . new URL); | ||
| 84 | die; | ||
| 85 | } | ||
| 86 | else{ | ||
| 87 | $error = 'forbidden_characters'; | ||
| 88 | } | ||
| 89 | } | 61 | } |
| 90 | 62 | ||
| 91 | $url = empty($error) ? new URL : new URL(['error' => $error]); | ||
| 92 | header('Location: ' . $url); | 63 | header('Location: ' . $url); |
| 93 | die; | 64 | die; |
| 94 | } | 65 | } |
| 95 | 66 | ||
| 67 | // auth | ||
| 96 | static public function connect(EntityManager $entityManager): void | 68 | static public function connect(EntityManager $entityManager): void |
| 97 | { | 69 | { |
| 98 | if($_SESSION['admin']) // déjà connecté? | 70 | if($_SESSION['admin']) // déjà connecté? |
| @@ -100,74 +72,52 @@ class UserController | |||
| 100 | header('Location: ' . new URL); | 72 | header('Location: ' . new URL); |
| 101 | die; | 73 | die; |
| 102 | } | 74 | } |
| 103 | |||
| 104 | $_SESSION['user'] = ''; | 75 | $_SESSION['user'] = ''; |
| 105 | $_SESSION['admin'] = false; | 76 | $_SESSION['admin'] = false; |
| 106 | 77 | ||
| 107 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | 78 | $form = new FormValidation($_POST, 'connection'); |
| 108 | $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; | ||
| 109 | unset($_SESSION['captcha']); | ||
| 110 | 79 | ||
| 111 | $error = ''; | 80 | $error = ''; |
| 112 | if($captcha_try == 0) | 81 | if($form->validate()){ |
| 113 | { | 82 | // à mettre dans une classe métier UserService, Authentication, AuthService? |
| 114 | $error = 'error_non_valid_captcha'; | 83 | $user = self::getUser($_POST['login'], $entityManager); |
| 115 | } | 84 | if(!empty($user) && $_POST['login'] === $user->getLogin() && password_verify($_POST['password'], $user->getPassword())) |
| 116 | elseif($captcha_solution == 0) // pas censé se produire | ||
| 117 | { | ||
| 118 | $error = 'captcha_server_error'; | ||
| 119 | } | ||
| 120 | elseif($captcha_try != $captcha_solution) // le test! | ||
| 121 | { | ||
| 122 | $error = 'bad_solution_captcha'; | ||
| 123 | } | ||
| 124 | elseif(!isset($_POST['login']) || empty($_POST['login']) | ||
| 125 | || !isset($_POST['password']) || empty($_POST['password'])) | ||
| 126 | { | ||
| 127 | $error = 'bad_login_or_password'; | ||
| 128 | } | ||
| 129 | else // c'est OK | ||
| 130 | { | ||
| 131 | $login = trim($_POST['login']); | ||
| 132 | $password = trim($_POST['password']); | ||
| 133 | $user = self::getUser($login, $entityManager); | ||
| 134 | |||
| 135 | // enregistrement et redirection | ||
| 136 | if(!empty($user) && $login === $user->getLogin() && password_verify($password, $user->getPassword())) | ||
| 137 | { | 85 | { |
| 138 | $log = new Log(true); | 86 | $log = new Log(true); |
| 139 | $entityManager->persist($log); | ||
| 140 | $entityManager->flush(); | ||
| 141 | 87 | ||
| 142 | // 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é |
| 143 | session_regenerate_id(true); | 89 | session_regenerate_id(true); |
| 144 | 90 | $_SESSION['user'] = $_POST['login']; | |
| 145 | $_SESSION['user'] = $login; | ||
| 146 | $_SESSION['admin'] = true; | 91 | $_SESSION['admin'] = true; |
| 147 | 92 | ||
| 148 | $url = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []); | 93 | $url = new URL(isset($_GET['from']) ? ['page' => $_GET['from']] : []); |
| 149 | isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : ''; | 94 | isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : ''; |
| 150 | header('Location: ' . $url); | ||
| 151 | die; | ||
| 152 | } | 95 | } |
| 153 | else | 96 | else |
| 154 | { | 97 | { |
| 155 | $log = new Log(false); | 98 | $log = new Log(false); |
| 156 | $entityManager->persist($log); | ||
| 157 | $entityManager->flush(); | ||
| 158 | $error = 'bad_login_or_password'; | 99 | $error = 'bad_login_or_password'; |
| 159 | } | 100 | } |
| 101 | $entityManager->persist($log); | ||
| 102 | $entityManager->flush(); | ||
| 103 | } | ||
| 104 | else{ | ||
| 105 | $error = $form->getErrors()[0]; // la 1ère erreur sera affichée | ||
| 106 | } | ||
| 107 | |||
| 108 | if(!empty($error)){ | ||
| 109 | sleep(1); // défense basique à la force brute | ||
| 110 | $url = new URL(['page' => 'connexion']); | ||
| 111 | isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null; | ||
| 112 | isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : null; | ||
| 113 | $url->addParams(['error' => $error]); | ||
| 160 | } | 114 | } |
| 161 | 115 | ||
| 162 | // tous les cas sauf connexion réussie | ||
| 163 | sleep(1); // défense basique à la force brute | ||
| 164 | $url = new URL(isset($_GET['from']) ? ['page' => 'connexion', 'from' => $_GET['from']] : []); | ||
| 165 | isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : ''; | ||
| 166 | !empty($error) ? $url->addParams(['error' => $error]) : ''; | ||
| 167 | header('Location: ' . $url); | 116 | header('Location: ' . $url); |
| 168 | die; | 117 | die; |
| 169 | } | 118 | } |
| 170 | 119 | ||
| 120 | // auth | ||
| 171 | static public function disconnect(): void | 121 | static public function disconnect(): void |
| 172 | { | 122 | { |
| 173 | // nettoyage complet | 123 | // nettoyage complet |
| @@ -183,154 +133,87 @@ class UserController | |||
| 183 | die; | 133 | die; |
| 184 | } | 134 | } |
| 185 | 135 | ||
| 136 | // user | ||
| 186 | static public function updateUsername(EntityManager $entityManager): void | 137 | static public function updateUsername(EntityManager $entityManager): void |
| 187 | { | 138 | { |
| 188 | if(!$_SESSION['admin']) // superflux, fait dans le routeur | 139 | if(!$_SESSION['admin']){ // superflux, fait dans le routeur |
| 189 | { | ||
| 190 | self::disconnect(); | 140 | self::disconnect(); |
| 191 | } | 141 | } |
| 192 | 142 | ||
| 193 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | ||
| 194 | $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; | ||
| 195 | unset($_SESSION['captcha']); | ||
| 196 | |||
| 197 | $url = new URL(['page' => 'user_edit']); | 143 | $url = new URL(['page' => 'user_edit']); |
| 198 | isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null; | 144 | isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null; |
| 199 | 145 | ||
| 146 | $form = new FormValidation($_POST, 'username_update'); | ||
| 147 | |||
| 200 | $error = ''; | 148 | $error = ''; |
| 201 | if(!isset($_POST['old_login']) || empty($_POST['old_login']) | 149 | if($form->validate()){ |
| 202 | || !isset($_POST['password']) || empty($_POST['password']) | 150 | // à mettre dans une classe métier UserService? |
| 203 | || !isset($_POST['new_login']) || empty($_POST['new_login']) | 151 | $user = self::getUser($_POST['login'], $entityManager); |
| 204 | || !isset($_POST['modify_username_hidden']) || !empty($_POST['modify_username_hidden'])) | 152 | if(password_verify($_POST['password'], $user->getPassword())){ |
| 205 | { | 153 | $user->setLogin($_POST['new_login']); |
| 206 | $error = 'bad_login_or_password'; | 154 | $entityManager->flush(); |
| 207 | } | 155 | $_SESSION['user'] = $_POST['new_login']; |
| 208 | elseif($captcha_try != $captcha_solution) // le test! | ||
| 209 | { | ||
| 210 | $error = 'bad_solution_captcha'; | ||
| 211 | } | ||
| 212 | else | ||
| 213 | { | ||
| 214 | // sécurisation de la saisie | ||
| 215 | $old_login = $_POST['old_login']; | ||
| 216 | $password = $_POST['password']; | ||
| 217 | $new_login = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_login'])); | ||
| 218 | // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide | ||
| 219 | 156 | ||
| 220 | // tests de conformité | 157 | $url->addParams(['success_username' => 'new_login']); |
| 221 | if($old_login !== $_POST['old_login'] || $password !== $_POST['password'] || $new_login !== $_POST['new_login']) | 158 | $error = ''; |
| 222 | { | ||
| 223 | $error = 'forbidden_characters'; | ||
| 224 | } | 159 | } |
| 225 | elseif($old_login !== $_SESSION['user']){ | 160 | else{ |
| 226 | $error = 'bad_login_or_password'; | 161 | $error = 'bad_login_or_password'; |
| 227 | } | 162 | } |
| 228 | elseif($old_login === $new_login){ | ||
| 229 | $error = 'same_username_as_before'; | ||
| 230 | } | ||
| 231 | else | ||
| 232 | { | ||
| 233 | $user = self::getUser($old_login, $entityManager); | ||
| 234 | |||
| 235 | if(password_verify($password, $user->getPassword())) | ||
| 236 | { | ||
| 237 | $user->setLogin($new_login); | ||
| 238 | $entityManager->flush(); | ||
| 239 | $_SESSION['user'] = $new_login; | ||
| 240 | |||
| 241 | $url->addParams(['success_login' => 'new_login']); | ||
| 242 | $error = ''; | ||
| 243 | } | ||
| 244 | else | ||
| 245 | { | ||
| 246 | $error = 'bad_login_or_password'; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | } | 163 | } |
| 250 | 164 | else{ | |
| 165 | $error = $form->getErrors()[0]; // la 1ère erreur sera affichée | ||
| 166 | } | ||
| 167 | |||
| 251 | if(!empty($error)){ | 168 | if(!empty($error)){ |
| 252 | sleep(1); | 169 | sleep(1); |
| 253 | $url->addParams(['error_login' => $error]); | 170 | $url->addParams(['error_username' => $error]); |
| 254 | } | 171 | } |
| 255 | |||
| 256 | header('Location: ' . $url); | 172 | header('Location: ' . $url); |
| 257 | die; | 173 | die; |
| 258 | } | 174 | } |
| 259 | 175 | ||
| 176 | // user | ||
| 260 | static public function updatePassword(EntityManager $entityManager): void | 177 | static public function updatePassword(EntityManager $entityManager): void |
| 261 | { | 178 | { |
| 262 | if(!$_SESSION['admin']) // superflux, fait dans le routeur | 179 | if(!$_SESSION['admin']){ // superflux, fait dans le routeur |
| 263 | { | ||
| 264 | self::disconnect(); | 180 | self::disconnect(); |
| 265 | } | 181 | } |
| 266 | 182 | ||
| 267 | $captcha_solution = (isset($_SESSION['captcha']) && is_int($_SESSION['captcha'])) ? $_SESSION['captcha'] : 0; | ||
| 268 | $captcha_try = isset($_POST['captcha']) ? Captcha::controlInput($_POST['captcha']) : 0; | ||
| 269 | unset($_SESSION['captcha']); | ||
| 270 | |||
| 271 | $url = new URL(['page' => 'user_edit']); | 183 | $url = new URL(['page' => 'user_edit']); |
| 272 | isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null; | 184 | isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null; |
| 273 | 185 | ||
| 186 | $form = new FormValidation($_POST, 'password_update'); | ||
| 187 | |||
| 274 | $error = ''; | 188 | $error = ''; |
| 275 | if(!isset($_POST['login']) || empty($_POST['login']) | 189 | if($form->validate()){ |
| 276 | || !isset($_POST['old_password']) || empty($_POST['old_password']) | 190 | // à mettre dans une classe métier UserService? |
| 277 | || !isset($_POST['new_password']) || empty($_POST['new_password']) | 191 | $user = self::getUser($_POST['login'], $entityManager); |
| 278 | || !isset($_POST['modify_password_hidden']) || !empty($_POST['modify_password_hidden'])) | 192 | if(password_verify($_POST['password'], $user->getPassword())){ |
| 279 | { | 193 | $new_password = password_hash($_POST['new_password'], PASSWORD_DEFAULT); |
| 280 | $error = 'bad_login_or_password'; | 194 | $user->setPassword($new_password); |
| 281 | } | 195 | $entityManager->flush(); |
| 282 | elseif($captcha_try != $captcha_solution) // le test! | ||
| 283 | { | ||
| 284 | $error = 'bad_solution_captcha'; | ||
| 285 | } | ||
| 286 | else | ||
| 287 | { | ||
| 288 | // sécurisation de la saisie | ||
| 289 | $login = $_POST['login']; | ||
| 290 | $old_password = $_POST['old_password']; | ||
| 291 | $new_password = self::removeSpacesTabsCRLF(htmlspecialchars($_POST['new_password'])); | ||
| 292 | // removeSpacesTabsCRLF pour éviter d'enregistrer une chaîne vide | ||
| 293 | 196 | ||
| 294 | // tests de conformité | 197 | $url->addParams(['success_password' => 'new_password']); |
| 295 | if($login !== $_POST['login'] || $old_password !== $_POST['old_password'] || $new_password !== $_POST['new_password']) | 198 | $error = ''; |
| 296 | { | ||
| 297 | $error = 'forbidden_characters'; | ||
| 298 | } | 199 | } |
| 299 | elseif($login !== $_SESSION['user']){ | 200 | else{ |
| 300 | $error = 'bad_login_or_password'; | 201 | $error = 'bad_login_or_password'; |
| 301 | } | 202 | } |
| 302 | elseif($old_password === $new_password){ | ||
| 303 | $error = 'same_password_as_before'; | ||
| 304 | } | ||
| 305 | else | ||
| 306 | { | ||
| 307 | $user = self::getUser($login, $entityManager); | ||
| 308 | |||
| 309 | if(password_verify($old_password, $user->getPassword())) | ||
| 310 | { | ||
| 311 | $new_password = password_hash($new_password, PASSWORD_DEFAULT); | ||
| 312 | $user->setPassword($new_password); | ||
| 313 | $entityManager->flush(); | ||
| 314 | |||
| 315 | $url->addParams(['success_password' => 'new_password']); | ||
| 316 | $error = ''; | ||
| 317 | } | ||
| 318 | else | ||
| 319 | { | ||
| 320 | $error = 'bad_login_or_password'; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | } | 203 | } |
| 324 | 204 | else{ | |
| 205 | $error = $form->getErrors()[0]; // la 1ère erreur sera affichée | ||
| 206 | } | ||
| 207 | |||
| 325 | if(!empty($error)){ | 208 | if(!empty($error)){ |
| 326 | sleep(1); | 209 | sleep(1); |
| 327 | $url->addParams(['error_password' => $error]); | 210 | $url->addParams(['error_password' => $error]); |
| 328 | } | 211 | } |
| 329 | |||
| 330 | header('Location: ' . $url); | 212 | header('Location: ' . $url); |
| 331 | die; | 213 | die; |
| 332 | } | 214 | } |
| 333 | 215 | ||
| 216 | // dans une classe mère ou un trait après découpage de UserController? | ||
| 334 | static private function getUser(string $login, EntityManager $entityManager): ?User | 217 | static private function getUser(string $login, EntityManager $entityManager): ?User |
| 335 | { | 218 | { |
| 336 | $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]); | 219 | $users = $entityManager->getRepository('App\Entity\User')->findBy(['login' => $login]); |
| @@ -351,6 +234,7 @@ class UserController | |||
| 351 | return null; | 234 | return null; |
| 352 | } | 235 | } |
| 353 | 236 | ||
| 237 | // dans une classe Form? | ||
| 354 | // erreurs à la création des mots de passe | 238 | // erreurs à la création des mots de passe |
| 355 | static private function removeSpacesTabsCRLF(string $chaine): string | 239 | static private function removeSpacesTabsCRLF(string $chaine): string |
| 356 | { | 240 | { |
diff --git a/src/router.php b/src/router.php index 19fe1c1..238cac9 100644 --- a/src/router.php +++ b/src/router.php | |||
| @@ -63,7 +63,7 @@ elseif($_SERVER['REQUEST_METHOD'] === 'POST'){ | |||
| 63 | { | 63 | { |
| 64 | // formulaire de contact | 64 | // formulaire de contact |
| 65 | if($_GET['action'] === 'send_email'){ | 65 | if($_GET['action'] === 'send_email'){ |
| 66 | EmailController::submit($json, $entityManager); | 66 | ContactFormController::sendVisitorEmail($entityManager, $json); |
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
diff --git a/src/view/UserEditBuilder.php b/src/view/UserEditBuilder.php index 63bbfad..3604e91 100644 --- a/src/view/UserEditBuilder.php +++ b/src/view/UserEditBuilder.php | |||
| @@ -31,8 +31,8 @@ class UserEditBuilder extends AbstractBuilder | |||
| 31 | 'same_password_as_before' => 'Nouveau mot de passe identique au précédent.' | 31 | 'same_password_as_before' => 'Nouveau mot de passe identique au précédent.' |
| 32 | ]; | 32 | ]; |
| 33 | 33 | ||
| 34 | $error_username = isset($_GET['error_login']) ? $error_messages[$_GET['error_login']] : ''; | 34 | $error_username = isset($_GET['error_username']) ? $error_messages[$_GET['error_username']] : ''; |
| 35 | $success_username = (isset($_GET['success_login']) && $_GET['success_login']) ? 'Identifiant modifié avec succès.' : ''; | 35 | $success_username = (isset($_GET['success_username']) && $_GET['success_username']) ? 'Identifiant modifié avec succès.' : ''; |
| 36 | $error_password = isset($_GET['error_password']) ? $error_messages[$_GET['error_password']] : ''; | 36 | $error_password = isset($_GET['error_password']) ? $error_messages[$_GET['error_password']] : ''; |
| 37 | $success_password = (isset($_GET['success_password']) && $_GET['success_password']) ? 'Mot de passe modifié avec succès.' : ''; | 37 | $success_password = (isset($_GET['success_password']) && $_GET['success_password']) ? 'Mot de passe modifié avec succès.' : ''; |
| 38 | 38 | ||
| @@ -51,6 +51,10 @@ class UserEditBuilder extends AbstractBuilder | |||
| 51 | isset($_GET['from']) ? $link_exit->addParams(['page' => $_GET['from'] ]) : ''; | 51 | isset($_GET['from']) ? $link_exit->addParams(['page' => $_GET['from'] ]) : ''; |
| 52 | isset($_GET['id']) ? $link_exit->addParams(['id' => $_GET['id']]) : ''; | 52 | isset($_GET['id']) ? $link_exit->addParams(['id' => $_GET['id']]) : ''; |
| 53 | 53 | ||
| 54 | $link_logout = new URL(['action' => 'deconnection']); | ||
| 55 | isset($_GET['from']) ? $link_logout->addParams(['from' => $_GET['from'] ]) : ''; | ||
| 56 | isset($_GET['id']) ? $link_logout->addParams(['id' => $_GET['id']]) : ''; | ||
| 57 | |||
| 54 | ob_start(); | 58 | ob_start(); |
| 55 | require $viewFile; | 59 | require $viewFile; |
| 56 | $this->html = ob_get_clean(); // nouveau contenu | 60 | $this->html = ob_get_clean(); // nouveau contenu |
diff --git a/src/view/templates/form.php b/src/view/templates/form.php index bcde2f4..25446c1 100644 --- a/src/view/templates/form.php +++ b/src/view/templates/form.php | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | <h3><?= $title ?></h3> | 4 | <h3><?= $title ?></h3> |
| 5 | <div class="form_inputs"> | 5 | <div class="form_inputs"> |
| 6 | <label for="email_name">Votre nom</label> | 6 | <label for="email_name">Votre nom</label> |
| 7 | <input id="email_name" type="text" name="email_name" value="" required> | 7 | <input id="email_name" type="text" name="email_name" value=""> |
| 8 | 8 | ||
| 9 | <label for="email_address">Votre e-mail</label> | 9 | <label for="email_address">Votre e-mail</label> |
| 10 | <input id="email_address" type="email" name="email_address" placeholder="mon-adresse@email.fr" value="" required> | 10 | <input id="email_address" type="email" name="email_address" placeholder="mon-adresse@email.fr" value="" onchange="checkCase()"> |
| 11 | 11 | ||
| 12 | <label for="email_message">Votre message</label> | 12 | <label for="email_message">Votre message</label> |
| 13 | <textarea id="email_message" type="text" name="email_message" rows="4" required></textarea> | 13 | <textarea id="email_message" type="text" name="email_message" rows="4"></textarea> |
| 14 | 14 | ||
| 15 | <div class="full_width_column"> | 15 | <div class="full_width_column"> |
| 16 | <label for="captcha" >Montrez que vous n'êtes pas un robot</label> | 16 | <label for="captcha" >Montrez que vous n'êtes pas un robot</label> |
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | <label for="email_captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label> | 19 | <label for="email_captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label> |
| 20 | <div> | 20 | <div> |
| 21 | <input id="email_captcha" type="text" name="email_captcha" size="1" required> | 21 | <input id="email_captcha" type="text" name="email_captcha" size="1" autocomplete="off"> |
| 22 | </div> | 22 | </div> |
| 23 | 23 | ||
| 24 | <input id="form_id_hidden" type="hidden" name="form_id_hidden" value=""> | 24 | <input id="form_id_hidden" type="hidden" name="form_id_hidden" value=""> |
diff --git a/src/view/templates/login.php b/src/view/templates/login.php index 766c114..c40b3a7 100644 --- a/src/view/templates/login.php +++ b/src/view/templates/login.php | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | <input id="login" type="text" name="login" autofocus required></p> | 9 | <input id="login" type="text" name="login" autofocus required></p> |
| 10 | <p><label for="password" >Mot de passe:</label> | 10 | <p><label for="password" >Mot de passe:</label> |
| 11 | <input id="password" type="password" name="password" required></p> | 11 | <input id="password" type="password" name="password" required></p> |
| 12 | <input type="hidden" name="connection_hidden"> | ||
| 12 | 13 | ||
| 13 | <p>Montrez que vous n'êtes pas un robot.<br> | 14 | <p>Montrez que vous n'êtes pas un robot.<br> |
| 14 | <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label> | 15 | <label for="captcha" >Combien font <?= $captcha->getA() ?> fois <?= $captcha->getB() ?>?</label> |
diff --git a/src/view/templates/user_create.php b/src/view/templates/user_create.php index dd17547..68e115c 100644 --- a/src/view/templates/user_create.php +++ b/src/view/templates/user_create.php | |||
| @@ -5,6 +5,7 @@ $error_messages = [ | |||
| 5 | 'error_non_valid_captcha' => 'Erreur au test anti-robot, veuillez saisir un nombre entier.', | 5 | 'error_non_valid_captcha' => 'Erreur au test anti-robot, veuillez saisir un nombre entier.', |
| 6 | 'captcha_server_error' => 'captcha_server_error', | 6 | 'captcha_server_error' => 'captcha_server_error', |
| 7 | 'bad_solution_captcha' => 'Erreur au test anti-robot, veuillez réessayer.', | 7 | 'bad_solution_captcha' => 'Erreur au test anti-robot, veuillez réessayer.', |
| 8 | 'bad_login_or_password' => 'Mauvais identifiant ou mot de passe, veuillez réessayer.', | ||
| 8 | 'different_passwords' => 'Les deux mots de passe saisis sont différents', | 9 | 'different_passwords' => 'Les deux mots de passe saisis sont différents', |
| 9 | 'forbidden_characters' => 'Caractères interdits: espaces, tabulations, sauts CR/LF.' | 10 | 'forbidden_characters' => 'Caractères interdits: espaces, tabulations, sauts CR/LF.' |
| 10 | ]; | 11 | ]; |
diff --git a/src/view/templates/user_edit.php b/src/view/templates/user_edit.php index b4b35ed..77cd9f2 100644 --- a/src/view/templates/user_edit.php +++ b/src/view/templates/user_edit.php | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | <p style="color: red; font-style: italic;"><?= $error_username ?></p> | 14 | <p style="color: red; font-style: italic;"><?= $error_username ?></p> |
| 15 | <p style="color: green; font-style: italic;"><?= $success_username ?></p> | 15 | <p style="color: green; font-style: italic;"><?= $success_username ?></p> |
| 16 | <form class="connexionFormulaire" method="post" action="<?= $link_user_form ?>" > | 16 | <form class="connexionFormulaire" method="post" action="<?= $link_user_form ?>" > |
| 17 | <p><label for="old_login" >Ancien nom:</label> | 17 | <p><label for="login" >Ancien nom:</label> |
| 18 | <input id="old_login" type="text" name="old_login" required></p> | 18 | <input id="login" type="text" name="login" required></p> |
| 19 | <p><label for="password" >Mot de passe:</label> | 19 | <p><label for="password" >Mot de passe:</label> |
| 20 | <input id="password" type="password" name="password" required ></p> | 20 | <input id="password" type="password" name="password" required ></p> |
| 21 | <p><label for="new_login" >Nouveau nom:</label> | 21 | <p><label for="new_login" >Nouveau nom:</label> |
| @@ -37,8 +37,8 @@ | |||
| 37 | <form class="connexionFormulaire" method="post" action="<?= $link_password_form ?>" > | 37 | <form class="connexionFormulaire" method="post" action="<?= $link_password_form ?>" > |
| 38 | <p><label for="login" >Nom:</label> | 38 | <p><label for="login" >Nom:</label> |
| 39 | <input id="login" type="text" name="login" required></p> | 39 | <input id="login" type="text" name="login" required></p> |
| 40 | <p><label for="old_password" >Ancien mot de passe:</label> | 40 | <p><label for="password" >Ancien mot de passe:</label> |
| 41 | <input id="old_password" type="password" name="old_password" required ></p> | 41 | <input id="password" type="password" name="password" required ></p> |
| 42 | <p><label for="new_password" >Nouveau mot de passe:</label> | 42 | <p><label for="new_password" >Nouveau mot de passe:</label> |
| 43 | <input id="new_password" type="password" name="new_password" required autocomplete="off"></p> | 43 | <input id="new_password" type="password" name="new_password" required autocomplete="off"></p> |
| 44 | <input type="hidden" name="modify_password_hidden"> | 44 | <input type="hidden" name="modify_password_hidden"> |
| @@ -54,9 +54,10 @@ | |||
| 54 | </div> | 54 | </div> |
| 55 | <div class="login_form"> | 55 | <div class="login_form"> |
| 56 | <p class="connexionP connexionFooter" > | 56 | <p class="connexionP connexionFooter" > |
| 57 | <a href="<?= $link_exit ?>" > | 57 | <a href="<?= $link_exit ?>"> |
| 58 | <button>Retour au site</button> | 58 | <button>Retour au site</button></a> |
| 59 | </a> | 59 | <a href="<?= $link_logout ?>"> |
| 60 | <button>Déconnexion</button></a> | ||
| 60 | </p> | 61 | </p> |
| 61 | </div> | 62 | </div> |
| 62 | </section> \ No newline at end of file | 63 | </section> \ No newline at end of file |
