]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/AuthController.php
e812ea18662998d3d6713134e282657566ebb869
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * Galette authentication controller
10 * Copyright © 2019-2023 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2019-2023 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.9.4dev - 2019-12-02
37 namespace Galette\Controllers
;
39 use Slim\Psr7\Request
;
40 use Slim\Psr7\Response
;
41 use Galette\Core\Login
;
42 use Galette\Core\Password
;
43 use Galette\Core\GaletteMail
;
44 use Galette\Entity\Adherent
;
45 use Galette\Entity\Texts
;
48 * Galette authentication controller
50 * @category Controllers
51 * @name AuthController
53 * @author Johan Cwiklinski <johan@x-tnd.be>
54 * @copyright 2019-2023 The Galette Team
55 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
56 * @link http://galette.tuxfamily.org
57 * @since Available since 0.9.4dev - 2019-12-02
60 class AuthController
extends AbstractController
65 * @param Request $request PSR Request
66 * @param Response $response PSR Response
67 * @param string $r Redirect after login
71 public function login(Request
$request, Response
$response, string $r = null)
73 //store redirect path if any
79 $this->session
->urlRedirect
= $r;
82 if (!$this->login
->isLogged()) {
86 'pages/index.html.twig',
88 'page_title' => _T("Login"),
93 return $this->galetteRedirect($request, $response);
100 * @param Request $request PSR Request
101 * @param Response $response PSR Response
105 public function doLogin(Request
$request, Response
$response)
107 $nick = $request->getParsedBody()['login'];
108 $password = $request->getParsedBody()['password'];
109 $checkpass = new \Galette\Util\
Password($this->preferences
);
111 if (trim($nick) == '' ||
trim($password) == '') {
112 $this->flash
->addMessage(
114 _T("You must provide both login and password.")
118 ->withHeader('Location', $this->routeparser
->urlFor('login'));
121 if ($nick === $this->preferences
->pref_admin_login
) {
122 $pw_superadmin = password_verify(
124 $this->preferences
->pref_admin_pass
126 if (!$pw_superadmin) {
128 md5($password) === $this->preferences
->pref_admin_pass
131 if ($pw_superadmin) {
132 $this->login
->logAdmin($nick, $this->preferences
);
135 $this->login
->logIn($nick, $password);
138 if ($this->login
->isLogged()) {
139 if (!$checkpass->isValid($password)) {
140 //password is no longer valid with current rules, must be changed
141 $this->flash
->addMessage(
143 _T("Your password is too weak! Please consider updating it.") .
144 '<br/> -' . implode('<br/>', $checkpass->getErrors())
147 $this->session
->login
= $this->login
;
148 $this->history
->add(_T("Login"));
149 return $this->galetteRedirect($request, $response);
151 $this->flash
->addMessage('error_detected', _T("Login failed."));
152 $this->history
->add(_T("Authentication failed"), $nick);
153 return $response->withStatus(301)->withHeader('Location', $this->routeparser
->urlFor('login'));
160 * @param Request $request PSR Request
161 * @param Response $response PSR Response
165 public function logout(Request
$request, Response
$response)
167 $this->login
->logOut();
168 $this->history
->add(_T("Log off"));
169 \RKA\Session
::destroy();
172 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
178 * @param Request $request PSR Request
179 * @param Response $response PSR Response
180 * @param integer $id Member to impersonate
184 public function impersonate(Request
$request, Response
$response, int $id)
186 $success = $this->login
->impersonate($id);
188 if ($success === true) {
189 $this->session
->login
= $this->login
;
193 _T("Impersonating as %login")
196 $this->history
->add($msg);
197 $this->flash
->addMessage(
205 _T("Unable to impersonate as %id")
207 $this->flash
->addMessage(
211 $this->history
->add($msg);
216 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
222 * @param Request $request PSR Request
223 * @param Response $response PSR Response
227 public function unimpersonate(Request
$request, Response
$response)
229 $login = new Login($this->zdb
, $this->i18n
);
230 $login->logAdmin($this->preferences
->pref_admin_login
, $this->preferences
);
231 $this->history
->add(_T("Impersonating ended"));
232 $this->session
->login
= $login;
233 $this->login
= $login;
234 $this->flash
->addMessage(
236 _T("Impersonating ended")
240 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
246 * @param Request $request PSR Request
247 * @param Response $response PSR Response
251 public function lostPassword(Request
$request, Response
$response): Response
253 if ($this->preferences
->pref_mail_method
=== GaletteMail
::METHOD_DISABLED
) {
254 throw new \
RuntimeException('Mailing disabled.');
259 'pages/password_lost.html.twig',
261 'page_title' => _T("Password recovery")
268 * Retrieve password procedure
270 * @param Request $request PSR Request
271 * @param Response $response PSR Response
272 * @param integer $id_adh Member id
276 public function retrievePassword(Request
$request, Response
$response, int $id_adh = null): Response
279 $redirect_url = $this->routeparser
->urlFor('slash');
280 if ((($this->login
->isAdmin() ||
$this->login
->isStaff()) && $id_adh !== null)) {
282 $redirect_url = $this->routeparser
->urlFor('member', ['id' => $id_adh]);
286 ($this->login
->isLogged()
287 ||
$this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
)
290 if ($this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
) {
291 $this->flash
->addMessage(
293 _T("Email sent is disabled in the preferences. Ask galette admin")
298 ->withHeader('Location', $redirect_url);
303 if (($this->login
->isAdmin() ||
$this->login
->isStaff()) && $id_adh !== null) {
304 $adh = new Adherent($this->zdb
, $id_adh);
305 $login_adh = $adh->login
;
307 $post = $request->getParsedBody();
308 $login_adh = htmlspecialchars($post['login'], ENT_QUOTES
);
309 $adh = new Adherent($this->zdb
, $login_adh);
312 if ($adh->id
!= '') {
313 //account has been found, proceed
314 if (GaletteMail
::isValidEmail($adh->email
)) {
315 $texts = new Texts($this->preferences
, $this->routeparser
);
318 ->setNoContribution();
320 //check if account is active
321 if (!$adh->isActive()) { //https://bugs.galette.eu/issues/1529
323 $text_id = 'pwddisabled';
325 $password = new Password($this->zdb
);
326 $res = $password->generateNewPassword($adh->id
);
330 ->setChangePasswordURI($password);
334 $texts->getTexts($text_id, $adh->language
);
336 $mail = new GaletteMail($this->preferences
);
337 $mail->setSubject($texts->getSubject());
338 $mail->setRecipients(
340 $adh->email
=> $adh->sname
344 $mail->setMessage($texts->getBody());
345 $sent = $mail->send();
347 if ($sent == GaletteMail
::MAIL_SENT
) {
352 _T("Email sent to '%s' for password recovery.")
355 if ($from_admin === false) {
356 $message = _T("An email has been sent to your address.<br/>Please check your inbox and follow the instructions.");
358 $message = _T("An email has been sent to the member.");
361 $this->flash
->addMessage(
369 _T("A problem happened while sending password for account '%s'")
371 $this->history
->add($str);
372 $this->flash
->addMessage(
377 $error_detected[] = $str;
383 _T("An error occurred storing temporary password for %s. Please inform an admin.")
385 $this->history
->add($str);
386 $this->flash
->addMessage(
395 _T("Your account (%s) do not contain any valid email address")
397 $this->history
->add($str);
398 $this->flash
->addMessage(
404 //account has not been found
405 if (GaletteMail
::isValidEmail($login_adh)) {
409 _T("Mails address %s does not exist")
415 _T("Login %s does not exist")
419 $this->history
->add($str);
420 $this->flash
->addMessage(
428 ->withHeader('Location', $redirect_url);
432 * Password recovery page
434 * @param Request $request PSR Request
435 * @param Response $response PSR Response
436 * @param string $hash Hash
440 public function recoverPassword(Request
$request, Response
$response, string $hash): Response
442 $password = new Password($this->zdb
);
443 if (!$password->isHashValid(base64_decode($hash))) {
444 $this->flash
->addMessage(
446 _T("This link is no longer valid. You should ask to retrieve your password again.")
452 $this->routeparser
->urlFor('password-lost')
459 'pages/password_recover.html.twig',
462 'page_title' => _T("Password recovery")
471 * @param Request $request PSR Request
472 * @param Response $response PSR Response
476 public function doRecoverPassword(Request
$request, Response
$response): Response
478 $post = $request->getParsedBody();
479 $password = new Password($this->zdb
);
481 if (!$id_adh = $password->isHashValid(base64_decode($post['hash']))) {
486 $this->routeparser
->urlFor('password-recovery', ['hash' => $post['hash']])
491 if ($post['mdp_adh'] == '') {
492 $error = _T("No password");
493 } elseif (isset($post['mdp_adh2'])) {
494 if (strcmp($post['mdp_adh'], $post['mdp_adh2'])) {
495 $error = _T("- The passwords don't match!");
497 $checkpass = new \Galette\Util\
Password($this->preferences
);
499 if (!$checkpass->isValid($post['mdp_adh'])) {
500 //password is not valid with current rules
501 $error = _T("Your password is too weak!") .
502 '<br/> -' . implode('<br/>', $checkpass->getErrors());
504 $res = Adherent
::updatePassword(
510 $error = _T("An error occurred while updating your password.");
516 _T("Password changed for member '%s'.")
519 //once password has been changed, we can remove the
520 //temporary password entry
521 $password->removeHash(base64_decode($post['hash']));
522 $this->flash
->addMessage(
524 _T("Your password has been changed!")
530 $this->routeparser
->urlFor('slash')
537 if ($error !== null) {
538 $this->flash
->addMessage(
548 $this->routeparser
->urlFor('password-recovery', ['hash' => $post['hash']])