]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/AuthController.php
92850a9b72259affc7ab004e89899793c3dd9667
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 (defined('NON_UTF_DBCONNECT')) {
140 $this->flash
->addMessage(
142 'It appears you are using NON_UTF_DBCONNECT constant, it will be in next major release.'
146 if (!$checkpass->isValid($password)) {
147 //password is no longer valid with current rules, must be changed
148 $this->flash
->addMessage(
150 _T("Your password is too weak! Please consider updating it.") .
151 '<br/> -' . implode('<br/>', $checkpass->getErrors())
154 $this->session
->login
= $this->login
;
155 $this->history
->add(_T("Login"));
156 return $this->galetteRedirect($request, $response);
158 $this->flash
->addMessage('error_detected', _T("Login failed."));
159 $this->history
->add(_T("Authentication failed"), $nick);
160 return $response->withStatus(301)->withHeader('Location', $this->routeparser
->urlFor('login'));
167 * @param Request $request PSR Request
168 * @param Response $response PSR Response
172 public function logout(Request
$request, Response
$response)
174 $this->login
->logOut();
175 $this->history
->add(_T("Log off"));
176 \RKA\Session
::destroy();
179 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
185 * @param Request $request PSR Request
186 * @param Response $response PSR Response
187 * @param integer $id Member to impersonate
191 public function impersonate(Request
$request, Response
$response, int $id)
193 $success = $this->login
->impersonate($id);
195 if ($success === true) {
196 $this->session
->login
= $this->login
;
200 _T("Impersonating as %login")
203 $this->history
->add($msg);
204 $this->flash
->addMessage(
212 _T("Unable to impersonate as %id")
214 $this->flash
->addMessage(
218 $this->history
->add($msg);
223 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
229 * @param Request $request PSR Request
230 * @param Response $response PSR Response
234 public function unimpersonate(Request
$request, Response
$response)
236 $login = new Login($this->zdb
, $this->i18n
);
237 $login->logAdmin($this->preferences
->pref_admin_login
, $this->preferences
);
238 $this->history
->add(_T("Impersonating ended"));
239 $this->session
->login
= $login;
240 $this->login
= $login;
241 $this->flash
->addMessage(
243 _T("Impersonating ended")
247 ->withHeader('Location', $this->routeparser
->urlFor('slash'));
253 * @param Request $request PSR Request
254 * @param Response $response PSR Response
258 public function lostPassword(Request
$request, Response
$response): Response
260 if ($this->preferences
->pref_mail_method
=== GaletteMail
::METHOD_DISABLED
) {
261 throw new \
RuntimeException('Mailing disabled.');
266 'pages/password_lost.html.twig',
268 'page_title' => _T("Password recovery")
275 * Retrieve password procedure
277 * @param Request $request PSR Request
278 * @param Response $response PSR Response
279 * @param integer $id_adh Member id
283 public function retrievePassword(Request
$request, Response
$response, int $id_adh = null): Response
286 $redirect_url = $this->routeparser
->urlFor('slash');
287 if ((($this->login
->isAdmin() ||
$this->login
->isStaff()) && $id_adh !== null)) {
289 $redirect_url = $this->routeparser
->urlFor('member', ['id' => $id_adh]);
293 ($this->login
->isLogged()
294 ||
$this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
)
297 if ($this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
) {
298 $this->flash
->addMessage(
300 _T("Email sent is disabled in the preferences. Ask galette admin")
305 ->withHeader('Location', $redirect_url);
310 if (($this->login
->isAdmin() ||
$this->login
->isStaff()) && $id_adh !== null) {
311 $adh = new Adherent($this->zdb
, $id_adh);
312 $login_adh = $adh->login
;
314 $post = $request->getParsedBody();
315 $login_adh = htmlspecialchars($post['login'], ENT_QUOTES
);
316 $adh = new Adherent($this->zdb
, $login_adh);
319 if ($adh->id
!= '') {
320 //account has been found, proceed
321 if (GaletteMail
::isValidEmail($adh->email
)) {
322 $texts = new Texts($this->preferences
, $this->routeparser
);
325 ->setNoContribution();
327 //check if account is active
328 if (!$adh->isActive()) { //https://bugs.galette.eu/issues/1529
330 $text_id = 'pwddisabled';
332 $password = new Password($this->zdb
);
333 $res = $password->generateNewPassword($adh->id
);
337 ->setChangePasswordURI($password);
341 $texts->getTexts($text_id, $adh->language
);
343 $mail = new GaletteMail($this->preferences
);
344 $mail->setSubject($texts->getSubject());
345 $mail->setRecipients(
347 $adh->email
=> $adh->sname
351 $mail->setMessage($texts->getBody());
352 $sent = $mail->send();
354 if ($sent == GaletteMail
::MAIL_SENT
) {
359 _T("Email sent to '%s' for password recovery.")
362 if ($from_admin === false) {
363 $message = _T("An email has been sent to your address.<br/>Please check your inbox and follow the instructions.");
365 $message = _T("An email has been sent to the member.");
368 $this->flash
->addMessage(
376 _T("A problem happened while sending password for account '%s'")
378 $this->history
->add($str);
379 $this->flash
->addMessage(
384 $error_detected[] = $str;
390 _T("An error occurred storing temporary password for %s. Please inform an admin.")
392 $this->history
->add($str);
393 $this->flash
->addMessage(
402 _T("Your account (%s) do not contain any valid email address")
404 $this->history
->add($str);
405 $this->flash
->addMessage(
411 //account has not been found
412 if (GaletteMail
::isValidEmail($login_adh)) {
416 _T("Mails address %s does not exist")
422 _T("Login %s does not exist")
426 $this->history
->add($str);
427 $this->flash
->addMessage(
435 ->withHeader('Location', $redirect_url);
439 * Password recovery page
441 * @param Request $request PSR Request
442 * @param Response $response PSR Response
443 * @param string $hash Hash
447 public function recoverPassword(Request
$request, Response
$response, string $hash): Response
449 $password = new Password($this->zdb
);
450 if (!$password->isHashValid(base64_decode($hash))) {
451 $this->flash
->addMessage(
453 _T("This link is no longer valid. You should ask to retrieve your password again.")
459 $this->routeparser
->urlFor('password-lost')
466 'pages/password_recover.html.twig',
469 'page_title' => _T("Password recovery")
478 * @param Request $request PSR Request
479 * @param Response $response PSR Response
483 public function doRecoverPassword(Request
$request, Response
$response): Response
485 $post = $request->getParsedBody();
486 $password = new Password($this->zdb
);
488 if (!$id_adh = $password->isHashValid(base64_decode($post['hash']))) {
493 $this->routeparser
->urlFor('password-recovery', ['hash' => $post['hash']])
498 if ($post['mdp_adh'] == '') {
499 $error = _T("No password");
500 } elseif (isset($post['mdp_adh2'])) {
501 if (strcmp($post['mdp_adh'], $post['mdp_adh2'])) {
502 $error = _T("- The passwords don't match!");
504 $checkpass = new \Galette\Util\
Password($this->preferences
);
506 if (!$checkpass->isValid($post['mdp_adh'])) {
507 //password is not valid with current rules
508 $error = _T("Your password is too weak!") .
509 '<br/> -' . implode('<br/>', $checkpass->getErrors());
511 $res = Adherent
::updatePassword(
517 $error = _T("An error occurred while updating your password.");
523 _T("Password changed for member '%s'.")
526 //once password has been changed, we can remove the
527 //temporary password entry
528 $password->removeHash(base64_decode($post['hash']));
529 $this->flash
->addMessage(
531 _T("Your password has been changed!")
537 $this->routeparser
->urlFor('slash')
544 if ($error !== null) {
545 $this->flash
->addMessage(
555 $this->routeparser
->urlFor('password-recovery', ['hash' => $post['hash']])