@@ -39,6 +39,7 @@ private function redirectToRoute(Request $request, Response $response, string $r
3939
4040 /**
4141 * Valide la page de connexion après soumission du formulaire.
42+ * Vérifie aussi que l'email est confirmé.
4243 */
4344 public function login (Request $ request , Response $ response ): Response
4445 {
@@ -48,6 +49,10 @@ public function login(Request $request, Response $response): Response
4849 $ user = $ this ->userRepository ->select ($ email );
4950
5051 if ($ user && password_verify ($ password , $ user ->password )) {
52+ if (isset ($ user ->email_verified ) && !$ user ->email_verified ) {
53+ $ this ->messages ->addMessage ('email_not_verified ' , true );
54+ return $ this ->redirectToRoute ($ request , $ response , 'app_index ' );
55+ }
5156 session_regenerate_id (true );
5257 $ _SESSION ['user ' ] = $ user ;
5358 return $ this ->redirectToRoute ($ request , $ response , 'app_admin_index ' );
@@ -57,6 +62,128 @@ public function login(Request $request, Response $response): Response
5762 return $ this ->redirectToRoute ($ request , $ response , 'app_index ' );
5863 }
5964
65+ /**
66+ * Inscrit un nouvel utilisateur avec vérification par email.
67+ */
68+ public function register (Request $ request , Response $ response ): Response
69+ {
70+ $ data = $ request ->getParsedBody ();
71+ $ email = trim ($ data ['email ' ] ?? '' );
72+ $ password = $ data ['password ' ] ?? '' ;
73+ $ passwordRepeat = $ data ['passwordRepeat ' ] ?? '' ;
74+
75+ // Validation email
76+ if (!$ email || !filter_var ($ email , FILTER_VALIDATE_EMAIL )) {
77+ $ this ->messages ->addMessage ('register_error ' , 'Adresse email invalide. ' );
78+ return $ this ->redirectToRoute ($ request , $ response , 'app_register ' );
79+ }
80+
81+ // Validation mot de passe
82+ $ passwordErrors = $ this ->validatePassword ($ password , $ passwordRepeat );
83+ if (!empty ($ passwordErrors )) {
84+ $ this ->messages ->addMessage ('register_error ' , implode (' ' , $ passwordErrors ));
85+ return $ this ->redirectToRoute ($ request , $ response , 'app_register ' );
86+ }
87+
88+ // Vérifier si l'utilisateur existe déjà
89+ $ existing = $ this ->userRepository ->select ($ email );
90+ if ($ existing ) {
91+ $ this ->messages ->addMessage ('register_error ' , 'Un compte avec cet email existe déjà. ' );
92+ return $ this ->redirectToRoute ($ request , $ response , 'app_register ' );
93+ }
94+
95+ // Créer l'utilisateur (email non vérifié)
96+ $ user = $ this ->userRepository ->insertWithPassword ($ email , $ password );
97+ $ user = $ this ->userRepository ->insertResetToken ($ user );
98+
99+ // Envoyer l'email de vérification
100+ $ routeParser = RouteContext::fromRequest ($ request )->getRouteParser ();
101+ $ verifyUrl = $ _SERVER ['WEBSITE_DOMAIN ' ] . $ routeParser ->urlFor ('app_verify_email ' , ["token " => $ user ->reset_token ]);
102+
103+ $ this ->mailchimp ->messages ->send ([
104+ "message " => [
105+ "from_email " => "contact@helloasso.io " ,
106+ "from_name " => "HelloAsso " ,
107+ "subject " => "Confirmez votre adresse email " ,
108+ "html " => $ this ->buildVerificationEmail ($ verifyUrl ),
109+ "to " => [["email " => $ user ->email ]],
110+ ],
111+ ]);
112+
113+ $ this ->messages ->addMessage ('register_success ' , true );
114+ return $ this ->redirectToRoute ($ request , $ response , 'app_index ' );
115+ }
116+
117+ /**
118+ * Vérifie l'email via le token reçu par mail.
119+ */
120+ public function verifyEmail (Request $ request , Response $ response , array $ args ): Response
121+ {
122+ $ token = $ args ['token ' ] ?? '' ;
123+ $ user = $ this ->userRepository ->selectByToken ($ token );
124+
125+ if ($ user ) {
126+ $ this ->userRepository ->verifyEmail ($ user );
127+ $ this ->messages ->addMessage ('email_verified ' , true );
128+ } else {
129+ $ this ->messages ->addMessage ('email_verify_error ' , true );
130+ }
131+
132+ return $ this ->redirectToRoute ($ request , $ response , 'app_index ' );
133+ }
134+
135+ /**
136+ * Valide les règles de mot de passe.
137+ */
138+ private function validatePassword (string $ password , string $ passwordRepeat ): array
139+ {
140+ $ errors = [];
141+
142+ if ($ password !== $ passwordRepeat ) {
143+ $ errors [] = 'Les mots de passe ne correspondent pas. ' ;
144+ }
145+ if (strlen ($ password ) < 8 ) {
146+ $ errors [] = 'Le mot de passe doit contenir au moins 8 caractères. ' ;
147+ }
148+ if (!preg_match ('/[A-Z]/ ' , $ password )) {
149+ $ errors [] = 'Le mot de passe doit contenir au moins une majuscule. ' ;
150+ }
151+ if (!preg_match ('/[a-z]/ ' , $ password )) {
152+ $ errors [] = 'Le mot de passe doit contenir au moins une minuscule. ' ;
153+ }
154+ if (!preg_match ('/[0-9]/ ' , $ password )) {
155+ $ errors [] = 'Le mot de passe doit contenir au moins un chiffre. ' ;
156+ }
157+ if (!preg_match ('/[^A-Za-z0-9]/ ' , $ password )) {
158+ $ errors [] = 'Le mot de passe doit contenir au moins un caractère spécial. ' ;
159+ }
160+
161+ return $ errors ;
162+ }
163+
164+ /**
165+ * Génère le contenu HTML de l'email de vérification.
166+ */
167+ private function buildVerificationEmail (string $ verifyUrl ): string
168+ {
169+ return <<<HTML
170+ <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; color: #333;">
171+ <h1 style="color: #2C88D9;">Confirmez votre adresse email 📧</h1>
172+ <p>Bonjour,</p>
173+ <p>Merci de vous être inscrit sur <strong>HelloAsso Stream</strong> !</p>
174+ <p>Pour activer votre compte, veuillez confirmer votre adresse email en cliquant sur le bouton ci-dessous :</p>
175+ <p style="text-align: center; margin: 30px 0;">
176+ <a href=" {$ verifyUrl }" style="background-color: #2C88D9; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;">Confirmer mon email</a>
177+ </p>
178+ <p style="font-size: 12px; color: #888;">Ou copiez ce lien dans votre navigateur : {$ verifyUrl }</p>
179+ <p style="font-size: 12px; color: #888;">Ce lien est valable 1 heure.</p>
180+ <hr style="border: none; border-top: 1px solid #eee; margin: 30px 0;" />
181+ <p>Si vous n'êtes pas à l'origine de cette inscription, vous pouvez ignorer cet email.</p>
182+ <p>L'équipe HelloAsso</p>
183+ </div>
184+ HTML ;
185+ }
186+
60187 /**
61188 * Envoie un email de réinitialisation de mot de passe si l'adresse existe.
62189 */
0 commit comments