]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/AuthController.php
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * Galette authentication controller
10 * Copyright © 2019-2020 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-2020 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\Http\Request
;
40 use Slim\Http\Response
;
41 use Galette\Core\SysInfos
;
42 use Galette\Core\Login
;
43 use Galette\Core\Password
;
44 use Galette\Core\GaletteMail
;
45 use Galette\Entity\Adherent
;
46 use Galette\Entity\Texts
;
50 * Galette authentication controller
52 * @category Controllers
53 * @name AuthController
55 * @author Johan Cwiklinski <johan@x-tnd.be>
56 * @copyright 2019-2020 The Galette Team
57 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
58 * @link http://galette.tuxfamily.org
59 * @since Available since 0.9.4dev - 2019-12-02
62 class AuthController
extends AbstractController
67 * @param Request $request PSR Request
68 * @param Response $response PSR Response
69 * @param array $args Request arguments ['r']
73 public function login(Request
$request, Response
$response, array $args = [])
75 //store redirect path if any
78 && $args['r'] != '/logout'
79 && $args['r'] != '/login'
81 $this->session
->urlRedirect
= $args['r'];
84 if (!$this->login
->isLogged()) {
90 'page_title' => _T("Login"),
95 return $this->galetteRedirect($request, $response, $args);
102 * @param Request $request PSR Request
103 * @param Response $response PSR Response
107 public function doLogin(Request
$request, Response
$response)
109 $nick = $request->getParsedBody()['login'];
110 $password = $request->getParsedBody()['password'];
111 $checkpass = new \Galette\Util\
Password($this->preferences
);
113 if (trim($nick) == '' ||
trim($password) == '') {
114 $this->flash
->addMessage(
116 _T("You must provide both login and password.")
120 ->withHeader('Location', $this->router
->pathFor('login'));
123 if ($nick === $this->preferences
->pref_admin_login
) {
124 $pw_superadmin = password_verify(
126 $this->preferences
->pref_admin_pass
128 if (!$pw_superadmin) {
130 md5($password) === $this->preferences
->pref_admin_pass
133 if ($pw_superadmin) {
134 $this->login
->logAdmin($nick, $this->preferences
);
137 $this->login
->logIn($nick, $password);
140 if ($this->login
->isLogged()) {
141 if (!$checkpass->isValid($password)) {
142 //password is no longer valid with current rules, must be changed
143 $this->flash
->addMessage(
145 _T("Your password is too weak! Please consider updating it.") .
146 '<br/> -' . implode('<br/>', $checkpass->getErrors())
149 $this->session
->login
= $this->login
;
150 $this->history
->add(_T("Login"));
151 return $this->galetteRedirect($request, $response, []);
153 $this->flash
->addMessage('error_detected', _T("Login failed."));
154 $this->history
->add(_T("Authentication failed"), $nick);
155 return $response->withStatus(301)->withHeader('Location', $this->router
->pathFor('login'));
162 * @param Request $request PSR Request
163 * @param Response $response PSR Response
167 public function logout(Request
$request, Response
$response)
169 $this->login
->logOut();
170 $this->history
->add(_T("Log off"));
171 \RKA\Session
::destroy();
174 ->withHeader('Location', $this->router
->pathFor('slash'));
180 * @param Request $request PSR Request
181 * @param Response $response PSR Response
182 * @param array $args Request arguments ['id']
186 public function impersonate(Request
$request, Response
$response, array $args)
188 $success = $this->login
->impersonate((int)$args['id']);
190 if ($success === true) {
191 $this->session
->login
= $this->login
;
195 _T("Impersonating as %login")
198 $this->history
->add($msg);
199 $this->flash
->addMessage(
207 _T("Unable to impersonate as %id")
209 $this->flash
->addMessage(
213 $this->history
->add($msg);
218 ->withHeader('Location', $this->router
->pathFor('slash'));
224 * @param Request $request PSR Request
225 * @param Response $response PSR Response
229 public function unimpersonate(Request
$request, Response
$response)
231 $login = new Login($this->zdb
, $this->i18n
, $this->session
);
232 $login->logAdmin($this->preferences
->pref_admin_login
, $this->preferences
);
233 $this->history
->add(_T("Impersonating ended"));
234 $this->session
->login
= $login;
235 $this->login
= $login;
236 $this->flash
->addMessage(
238 _T("Impersonating ended")
242 ->withHeader('Location', $this->router
->pathFor('slash'));
248 * @param Request $request PSR Request
249 * @param Response $response PSR Response
253 public function lostPassword(Request
$request, Response
$response): Response
255 if ($this->preferences
->pref_mail_method
=== GaletteMail
::METHOD_DISABLED
) {
256 throw new \
RuntimeException('Mailing disabled.');
263 'page_title' => _T("Password recovery")
270 * Retrieve password procedure
272 * @param Request $request PSR Request
273 * @param Response $response PSR Response
274 * @param array $args Request arguments ['id']
278 public function retrievePassword(Request
$request, Response
$response, array $args): Response
281 $redirect_url = $this->router
->pathFor('slash');
282 if ((($this->login
->isAdmin() ||
$this->login
->isStaff()) && isset($args[Adherent
::PK
]))) {
284 $redirect_url = $this->router
->pathFor('member', ['id' => $args[Adherent
::PK
]]);
288 ($this->login
->isLogged()
289 ||
$this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
)
292 if ($this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
) {
293 $this->flash
->addMessage(
295 _T("Email sent is disabled in the preferences. Ask galette admin")
300 ->withHeader('Location', $redirect_url);
305 if (($this->login
->isAdmin() ||
$this->login
->isStaff()) && isset($args[Adherent
::PK
])) {
306 $adh = new Adherent($this->zdb
, (int)$args[Adherent
::PK
]);
307 $login_adh = $adh->login
;
309 $post = $request->getParsedBody();
310 $login_adh = $post['login'];
311 $adh = new Adherent($this->zdb
, $login_adh);
314 if ($adh->id
!= '') {
315 //account has been found, proceed
316 if (GaletteMail
::isValidEmail($adh->email
)) {
317 $password = new Password($this->zdb
);
318 $res = $password->generateNewPassword($adh->id
);
320 $link_validity = new \
DateTime();
321 $link_validity->add(new \
DateInterval('PT24H'));
323 $df = _T("Y-m-d H:i:s");
329 'change_pass_uri' => $this->preferences
->getURL() .
330 $this->router
->pathFor(
332 ['hash' => base64_encode($password->getHash())]
334 'link_validity' => $link_validity->format(_T("Y-m-d H:i:s")),
335 'login_adh' => custom_html_entity_decode($adh->login
, ENT_QUOTES
)
338 $mtxt = $texts->getTexts('pwd', $adh->language
);
340 $mail = new GaletteMail($this->preferences
);
341 $mail->setSubject($texts->getSubject());
342 $mail->setRecipients(
344 $adh->email
=> $adh->sname
348 $mail->setMessage($texts->getBody());
349 $sent = $mail->send();
351 if ($sent == GaletteMail
::MAIL_SENT
) {
356 _T("Email sent to '%s' for password recovery.")
359 if ($from_admin === false) {
360 $message = _T("An email has been sent to your address.<br/>Please check your inbox and follow the instructions.");
363 $message = _T("An email has been sent to the member.");
366 $this->flash
->addMessage(
374 _T("A problem happened while sending password for account '%s'")
376 $this->history
->add($str);
377 $this->flash
->addMessage(
382 $error_detected[] = $str;
388 _T("An error occurred storing temporary password for %s. Please inform an admin.")
390 $this->history
->add($str);
391 $this->flash
->addMessage(
400 _T("Your account (%s) do not contain any valid email address")
402 $this->history
->add($str);
403 $this->flash
->addMessage(
409 //account has not been found
410 if (GaletteMail
::isValidEmail($login_adh)) {
414 _T("Mails address %s does not exist")
420 _T("Login %s does not exist")
424 $this->history
->add($str);
425 $this->flash
->addMessage(
433 ->withHeader('Location', $redirect_url);
437 * Password recovery page
439 * @param Request $request PSR Request
440 * @param Response $response PSR Response
441 * @param array $args Request arguments
445 public function recoverPassword(Request
$request, Response
$response, array $args): Response
447 $password = new Password($this->zdb
);
448 if (!$id_adh = $password->isHashValid(base64_decode($args['hash']))) {
449 $this->flash
->addMessage(
451 _T("This link is no longer valid. You should ask to retrieve your password again.")
457 $this->router
->pathFor('password-lost')
466 'hash' => $args['hash'],
467 'page_title' => _T("Password recovery")
476 * @param Request $request PSR Request
477 * @param Response $response PSR Response
481 public function doRecoverPassword(Request
$request, Response
$response): Response
483 $post = $request->getParsedBody();
484 $password = new Password($this->zdb
);
487 if (!$id_adh = $password->isHashValid(base64_decode($post['hash']))) {
492 $this->router
->pathFor('password-recovery', ['hash' => $post['hash']])
497 if ($post['mdp_adh'] == '') {
498 $error = _T("No password");
499 } elseif (isset($post['mdp_adh2'])) {
500 if (strcmp($post['mdp_adh'], $post['mdp_adh2'])) {
501 $error = _T("- The passwords don't match!");
503 $checkpass = new \Galette\Util\
Password($this->preferences
);
505 if (!$checkpass->isValid($post['mdp_adh'])) {
506 //password is not valid with current rules
507 $error = _T("Your password is too weak!") .
508 '<br/> -' . implode('<br/>', $checkpass->getErrors());
510 $res = Adherent
::updatePassword(
516 $error = _T("An error occurred while updating your password.");
522 _T("Password changed for member '%s'.")
525 //once password has been changed, we can remove the
526 //temporary password entry
527 $password->removeHash(base64_decode($post['hash']));
528 $password_updated = true;
529 $this->flash
->addMessage(
531 _T("Your password has been changed!")
537 $this->router
->pathFor('slash')
544 if ($error !== null) {
545 $this->flash
->addMessage(
555 $this->router
->pathFor('password-recovery', ['hash' => $post['hash']])