aboutsummaryrefslogtreecommitdiff
path: root/src/Controller/UserController.php
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2026-10-23 00:47:32 +0200
committerpolo <ordipolo@gmx.fr>2026-10-23 00:47:32 +0200
commitf27cca08ff786ceff1870147f6d6bad14d71117f (patch)
treed36597a72025313d6faf4ed228755fa267ebe2f6 /src/Controller/UserController.php
parentc7309f900ef05bd5cb313110ec159b761af394ec (diff)
downloadcms-f27cca08ff786ceff1870147f6d6bad14d71117f.tar.gz
cms-f27cca08ff786ceff1870147f6d6bad14d71117f.tar.bz2
cms-f27cca08ff786ceff1870147f6d6bad14d71117f.zip
dossiers avec majuscule, namespace pour toutes les classes, autoload psr-4, UserDataService::createZip déplacé dans Backup
Diffstat (limited to 'src/Controller/UserController.php')
-rw-r--r--src/Controller/UserController.php237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php
new file mode 100644
index 0000000..812a2da
--- /dev/null
+++ b/src/Controller/UserController.php
@@ -0,0 +1,237 @@
1<?php
2// src/Controller/UserController.php
3//
4/* actuellement un fourre-tout de méthodes en rapport avec les utilisateurs
5pour 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)
7il 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é:
11Auth (connexion, deconnexion), User (infos, choix photo), Account (créer, supprimer compte), Avatar (upload photo...)
12*/
13
14declare(strict_types=1);
15
16namespace App\Controller;
17
18use Symfony\Component\HttpFoundation\RedirectResponse;
19use Doctrine\ORM\EntityManager;
20use App\Entity\User;
21use App\Entity\Log;
22use App\Service\FormValidation;
23use App\Service\ValidationStrategy;
24use App\Service\URL;
25use App\Service\Backup;
26use App\Service\EmailService;
27
28class UserController
29{
30 // account
31 static public function createAdminUser(EntityManager $entityManager): RedirectResponse
32 {
33 unset($_SESSION['user']);
34
35 $form = new FormValidation($_POST, ValidationStrategy::CreateUser);
36
37 $url = new URL;
38 $error = '';
39 if($form->validate()){
40 $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
41 $user = new User($_POST['login'], 'admin', $password);
42 $entityManager->persist($user);
43 $entityManager->flush();
44 }
45 else{
46 $error = $form->getError();
47 }
48
49 if(!empty($error)){
50 $url->addParams(['error' => $error]);
51 }
52
53 return new RedirectResponse((string)$url);
54 }
55
56 // account
57 //static public function createUser(EntityManager $entityManager){}
58
59 // auth
60 static public function connect(EntityManager $entityManager): RedirectResponse
61 {
62 $url = new URL;
63 if(IS_ADMIN){ // déjà connecté?
64 return new RedirectResponse((string)$url);
65 }
66 unset($_SESSION['user']);
67
68 $form = new FormValidation($_POST, ValidationStrategy::Connection);
69
70 $error = '';
71 if($form->validate()){
72 // à mettre dans une classe métier UserService, Authentication, AuthService?
73 $user = self::getUserByName($_POST['login'], $entityManager);
74 if(!empty($user) && $_POST['login'] === $user->getLogin() && password_verify($_POST['password'], $user->getPassword())){
75 $log = new Log(true);
76
77 // protection fixation de session, si l'attaquant crée un cookie de session, il est remplacé
78 session_regenerate_id(true);
79 $_SESSION['user']['id'] = $user->getId();
80 $_SESSION['user']['username'] = $user->getLogin();
81 $_SESSION['user']['role'] = $user->getRole();
82
83 EmailService::cleanEmails($entityManager);
84
85 try{
86 if(file_exists('../var/backups')){
87 Backup::mySQLdump($entityManager, 'auto'); // créer un nouveau backup, sauf si les dossiers nécessaires sont encore à créer
88 }
89 }
90 catch(\RuntimeException $e){
91 echo '<script>window.error_message = "' . $e->getMessage() . '";</script>';
92 }
93
94 $url->addParams(isset($_GET['from']) ? ['page' => $_GET['from']] : []);
95 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
96 }
97 else
98 {
99 $log = new Log(false);
100 $error = 'bad_login_or_password';
101 }
102 $entityManager->persist($log);
103 $entityManager->flush();
104 }
105 else{
106 $error = $form->getError();
107 }
108
109 if(!empty($error)){
110 sleep(1); // défense basique à la force brute
111 $url->addParams(['page' => 'connection']);
112 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
113 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : null;
114 $url->addParams(['error' => $error]);
115 }
116
117 return new RedirectResponse((string)$url);
118 }
119
120 // auth
121 static public function disconnect(): RedirectResponse
122 {
123 // nettoyage complet
124 unset($_SESSION['user']); // mémoire vive
125 session_destroy(); // fichier côté serveur
126 setcookie('PHPSESSID', '', time() - 86400, '/'); // cookie de session
127
128 // retour même page
129 $url = new URL;
130 isset($_GET['from']) ? $url->addParams(['page' => $_GET['from']]) : '';
131 isset($_GET['id']) ? $url->addParams(['id' => $_GET['id']]) : '';
132 return new RedirectResponse((string)$url);
133 }
134
135 // user
136 static public function updateUsername(EntityManager $entityManager): RedirectResponse
137 {
138 if(!IS_ADMIN){ // superflux, fait dans le routeur
139 return self::disconnect();
140 }
141
142 $url = new URL(['page' => 'user_edit']);
143 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
144
145 $form = new FormValidation($_POST, ValidationStrategy::UsernameUpdate);
146
147 $error = '';
148 if($form->validate()){
149 // à mettre dans une classe métier UserService?
150 $user = self::getUserByName($_POST['login'], $entityManager);
151 if(password_verify($_POST['password'], $user->getPassword())){
152 $user->setLogin($_POST['new_login']);
153 $entityManager->flush();
154 $_SESSION['user']['username'] = $_POST['new_login'];
155
156 $url->addParams(['success_username' => 'new_login']);
157 $error = '';
158 }
159 else{
160 $error = 'bad_login_or_password';
161 }
162 }
163 else{
164 $error = $form->getError();
165 }
166
167 if(!empty($error)){
168 sleep(1);
169 $url->addParams(['error_username' => $error]);
170 }
171 return new RedirectResponse((string)$url);
172 }
173
174 // user
175 static public function updatePassword(EntityManager $entityManager): RedirectResponse
176 {
177 if(!IS_ADMIN){ // superflux, fait dans le routeur
178 return self::disconnect();
179 }
180
181 $url = new URL(['page' => 'user_edit']);
182 isset($_GET['from']) ? $url->addParams(['from' => $_GET['from']]) : null;
183
184 $form = new FormValidation($_POST, ValidationStrategy::PasswordUpdate);
185
186 $error = '';
187 if($form->validate()){
188 // à mettre dans une classe métier UserService?
189 $user = self::getUserByName($_POST['login'], $entityManager);
190 if(password_verify($_POST['password'], $user->getPassword())){
191 $new_password = password_hash($_POST['new_password'], PASSWORD_DEFAULT);
192 $user->setPassword($new_password);
193 $entityManager->flush();
194
195 $url->addParams(['success_password' => 'new_password']);
196 $error = '';
197 }
198 else{
199 $error = 'bad_login_or_password';
200 }
201 }
202 else{
203 $error = $form->getError();
204 }
205
206 if(!empty($error)){
207 sleep(1);
208 $url->addParams(['error_password' => $error]);
209 }
210 return new RedirectResponse((string)$url);
211 }
212
213 // dans une classe mère ou un trait après découpage de UserController?
214 static private function getUserByName(string $login, EntityManager $entityManager): ?User
215 {
216 $users = $entityManager->getRepository(User::class)->findBy(['login' => $login]);
217 foreach($users as $user){
218 if($user->getLogin() === $login){
219 return $user;
220 }
221 }
222 return null;
223 }
224
225 static public function getUserById(int $id, EntityManager $entityManager): ?User
226 {
227 return $entityManager->find(User::class, $id);
228 }
229
230 // dans une classe Form?
231 // erreurs à la création des mots de passe
232 static private function removeSpacesTabsCRLF(string $chaine): string
233 {
234 $cibles = [' ', "\t", "\n", "\r"]; // doubles quotes !!
235 return(str_replace($cibles, '', $chaine));
236 }
237} \ No newline at end of file