]> git.agnieray.net Git - galette.git/commitdiff
Migrate authentication routes to a controller class
authorJohan Cwiklinski <johan@x-tnd.be>
Fri, 1 May 2020 20:21:07 +0000 (22:21 +0200)
committerJohan Cwiklinski <johan@x-tnd.be>
Fri, 1 May 2020 21:08:50 +0000 (23:08 +0200)
Add abstract controller to rule them all
refs #1354

galette/includes/routes/authentication.routes.php
galette/includes/routes/main.routes.php
galette/lib/Galette/Controllers/AbstractController.php [new file with mode: 0644]
galette/lib/Galette/Controllers/AuthController.php [new file with mode: 0644]

index 0900f2083d0ef0976ccb323b83d7864af2d9a724..e7658ec4ac9cadc8d9a8f082b3b8f47a03ef1ca5 100644 (file)
@@ -35,6 +35,8 @@
  * @since     0.8.2dev 2014-11-11
  */
 
+use Galette\Controllers\AuthController;
+
 use Galette\Core\GaletteMail;
 use Galette\Core\Password;
 use Galette\Entity\Adherent;
@@ -42,100 +44,33 @@ use Galette\Entity\Texts;
 
 //login page
 $app->get(
-    '/login',
-    function ($request, $response, $args = []) use ($baseRedirect) {
-        //store redirect path if any
-        if (isset($args['r'])
-            && $args['r'] != '/logout'
-            && $args['r'] != '/login'
-        ) {
-            $this->session->urlRedirect = $args['r'];
-        }
-
-        if (!$this->login->isLogged()) {
-            // display page
-            $this->view->render(
-                $response,
-                'index.tpl',
-                array(
-                    'page_title'    => _T("Login"),
-                )
-            );
-            return $response;
-        } else {
-            return $baseRedirect($request, $response, $args);
-        }
-    }
+    '/login[/{r:.+}]',
+    AuthController::class . ':login'
 )->setName('login');
 
 //Authentication procedure
 $app->post(
     '/login',
-    function ($request, $response) use ($app, $baseRedirect) {
-        $nick = $request->getParsedBody()['login'];
-        $password = $request->getParsedBody()['password'];
-        $checkpass = new Galette\Util\Password($this->preferences);
-
-        if (trim($nick) == '' || trim($password) == '') {
-            $this->flash->addMessage(
-                'loginfault',
-                _T("You must provide both login and password.")
-            );
-            return $response
-                ->withStatus(301)
-                ->withHeader('Location', $this->router->pathFor('login'));
-        }
-
-        if ($nick === $this->preferences->pref_admin_login) {
-            $pw_superadmin = password_verify(
-                $password,
-                $this->preferences->pref_admin_pass
-            );
-            if (!$pw_superadmin) {
-                $pw_superadmin = (
-                    md5($password) === $this->preferences->pref_admin_pass
-                );
-            }
-            if ($pw_superadmin) {
-                $this->login->logAdmin($nick, $this->preferences);
-            }
-        } else {
-            $this->login->logIn($nick, $password);
-        }
-
-        if ($this->login->isLogged()) {
-            if (!$checkpass->isValid($password)) {
-                //password is no longer valid with current rules, must be changed
-                $this->flash->addMessage(
-                    'warning_detected',
-                    _T("Your password is too weak! Please consider updating it.") .
-                    '<br/> -' . implode('<br/>', $checkpass->getErrors())
-                );
-            }
-            $this->session->login = $this->login;
-            $this->history->add(_T("Login"));
-            return $baseRedirect($request, $response, []);
-        } else {
-            $this->flash->addMessage('error_detected', _T("Login failed."));
-            $this->history->add(_T("Authentication failed"), $nick);
-            return $response->withStatus(301)->withHeader('Location', $this->router->pathFor('login'));
-        }
-    }
+    AuthController::class . ':dologin'
 )->setName('dologin');
 
 //logout procedure
 $app->get(
     '/logout',
-    function ($request, $response) {
-        $this->login->logOut();
-        $this->history->add(_("Log off"));
-        \RKA\Session::destroy();
-        return $response
-            ->withStatus(301)
-            ->withHeader('Location', $this->router->pathFor('slash'));
-    }
+    AuthController::class . ':logout'
 )->setName('logout');
 
+//impersonating
+$app->get(
+    '/impersonate/{id:\d+}',
+    AuthController::class . ':impersonate'
+)->setName('impersonate')->add($authenticate);
+
+$app->get(
+    '/unimpersonate',
+    AuthController::class . ':unimpersonate'
+)->setName('unimpersonate')->add($authenticate);
+
 //password lost page
 $app->get(
     '/password-lost',
index 613ec5e6f8738c868028b19621d43bfeb66992fc..62e0b40d1ebaca15c55677b944248515f569f2af 100644 (file)
@@ -134,60 +134,3 @@ $app->get(
         return $response;
     }
 )->setName('sysinfos')->add($authenticate);
-
-//impersonating
-$app->get(
-    '/impersonate/{id:\d+}',
-    function ($request, $response, $args) {
-        $original_login = $this->login->login;
-        $success = $this->login->impersonate($args['id']);
-
-        if ($success === true) {
-            $this->session->login = $this->login;
-            $msg = str_replace(
-                '%login',
-                $this->login->login,
-                _T("Impersonating as %login")
-            );
-
-            $this->history->add($msg);
-            $this->flash->addMessage(
-                'success_detected',
-                $msg
-            );
-        } else {
-            $msg = str_replace(
-                '%id',
-                $id,
-                _T("Unable to impersonate as %id")
-            );
-            $this->flash->addMessage(
-                'error_detected',
-                $msg
-            );
-            $this->history->add($msg);
-        }
-
-        return $response
-            ->withStatus(301)
-            ->withHeader('Location', $this->router->pathFor('slash'));
-    }
-)->setName('impersonate')->add($authenticate);
-
-$app->get(
-    '/unimpersonate',
-    function ($request, $response, $args) {
-        $login = new \Galette\Core\Login($this->zdb, $this->i18n, $this->session);
-        $login->logAdmin($this->preferences->pref_admin_login, $this->preferences);
-        $this->history->add(_T("Impersonating ended"));
-        $this->session->login = $login;
-        $this->login = $login;
-        $this->flash->addMessage(
-            'success_detected',
-            _T("Impersonating ended")
-        );
-        return $response
-            ->withStatus(301)
-            ->withHeader('Location', $this->router->pathFor('slash'));
-    }
-)->setName('unimpersonate')->add($authenticate);
diff --git a/galette/lib/Galette/Controllers/AbstractController.php b/galette/lib/Galette/Controllers/AbstractController.php
new file mode 100644 (file)
index 0000000..e83ea5d
--- /dev/null
@@ -0,0 +1,234 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Galette abstract controller
+ *
+ * PHP version 5
+ *
+ * Copyright © 2019-2020 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Entity
+ * @package   Galette
+ *
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2019-2020 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version   SVN: $Id$
+ * @link      http://galette.tuxfamily.org
+ * @since     Available since 0.9.4dev - 2019-12-02
+ */
+
+namespace Galette\Controllers;
+
+use Psr\Container\ContainerInterface;
+use Slim\Http\Request;
+use Slim\Http\Response;
+
+/**
+ * Galette abstract controller
+ *
+ * @category  Controllers
+ * @name      AbstractController
+ * @package   Galette
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2019-2020 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @link      http://galette.tuxfamily.org
+ * @since     Available since 0.9.4dev - 2019-12-02
+ */
+
+abstract class AbstractController
+{
+    private $container;
+    /**
+     * @Inject
+     * @var Galette\Core\Db
+     */
+    protected $zdb;
+    /**
+     * @Inject
+     * @var Galette\Core\Login
+     */
+    protected $login;
+    /**
+     * @Inject
+     * @var Galette\Core\Preferences
+     */
+    protected $preferences;
+    /**
+     * @Inject
+     * @var Slim\Views\Smarty
+     */
+    protected $view;
+    /**
+     * @Inject
+     * @var Galette\Core\Plugins
+     */
+    protected $plugins;
+    /**
+     * @Inject
+     * @var Slim\Router
+     */
+    protected $router;
+    /**
+     * @Inject
+     * @var Galette\Core\History
+     */
+    protected $history;
+    /**
+     * @Inject
+     * @var Galette\Core\I18n
+     */
+    protected $i18n;
+    /**
+     * @Inject("session")
+     */
+    protected $session;
+    /**
+     * @Inject
+     * @var Slim\Flash\Messages
+     */
+    protected $flash;
+    /**
+     * @Inject
+     * @var Galette\Entity\FieldsConfig
+     */
+    protected $fields_config;
+
+    /**
+     * @Inject
+     * @var Galette\Handlers\NotFound
+     */
+    protected $notFoundHandler;
+
+    /**
+     * Constructor
+     *
+     * @param ContainerInterface $container COntainer instance
+     */
+    public function __construct(ContainerInterface $container)
+    {
+        $this->container = $container;
+        //set variosu services we need
+        $this->zdb = $container->get('zdb');
+        $this->login = $container->get('login');
+        $this->preferences = $container->get('preferences');
+        $this->view = $container->get('view');
+        $this->plugins = $container->get('plugins');
+        $this->router = $container->get('router');
+        $this->history = $container->get('history');
+        $this->i18n = $container->get('i18n');
+        $this->session = $container->get('session');
+        $this->flash = $container->get('flash');
+        $this->fields_config = $container->get('fields_config');
+        $this->notFoundHandler = $container->get('notFoundHandler');
+    }
+
+    /**
+     * Galette redirection workflow
+     * Each user have a default homepage depending on it status (logged in or not, its credentials, etc.
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     * @param array    $args     Request arguments ['r']
+     *
+     * @return void
+     */
+    protected function galetteRedirect(Request $request, Response $response, array $args = [])
+    {
+        //reinject flash messages so they're not lost
+        $flashes = $this->flash->getMessages();
+        foreach ($flashes as $type => $messages) {
+            foreach ($messages as $message) {
+                $this->container->get('flash')->addMessage($type, $message);
+            }
+        }
+
+        if ($this->login->isLogged()) {
+            $urlRedirect = null;
+            if ($this->session->urlRedirect !== null) {
+                $urlRedirect = $this->getGaletteBaseUrl($request) . $this->session->urlRedirect;
+                $this->session->urlRedirect = null;
+            }
+
+            if ($urlRedirect !== null) {
+                return $response
+                    ->withStatus(301)
+                    ->withHeader('Location', $urlRedirect);
+            } else {
+                if ($this->login->isSuperAdmin()
+                    || $this->login->isAdmin()
+                    || $this->login->isStaff()
+                ) {
+                    if (!isset($_COOKIE['show_galette_dashboard'])
+                        || $_COOKIE['show_galette_dashboard'] == 1
+                    ) {
+                        return $response
+                            ->withStatus(301)
+                            //Do not use "$this->router->pathFor('dashboard'))" to prevent translation issues when login
+                            //FIXME: maybe no longer relevant
+                            ->withHeader('Location', $this->getGaletteBaseUrl($request) . '/dashboard');
+                    } else {
+                        return $response
+                            ->withStatus(301)
+                            //Do not use "$this->router->pathFor('members'))" to prevent translation issues when login
+                            //FIXME: maybe no longer relevant
+                            ->withHeader('Location', $this->getGaletteBaseUrl($request) . '/members');
+                    }
+                } else {
+                    return $response
+                        ->withStatus(301)
+                        //Do not use "$this->router->pathFor('me'))" to prevent translation issues when login
+                        //FIXME: maybe no longer relevant
+                        ->withHeader('Location', $this->getGaletteBaseUrl($request) . '/dashboard');
+                }
+            }
+        } else {
+            return $response
+                ->withStatus(301)
+                //Do not use "$this->router->pathFor('login'))" to prevent translation issues when login
+                //FIXME: maybe no longer relevant
+                ->withHeader('Location', $this->getGaletteBaseUrl($request) . '/login');
+        }
+    }
+
+    /**
+     * Get base URL fixed for proxies
+     *
+     * @param Request $request PSR Request
+     *
+     * @return string
+     */
+    private function getGaletteBaseUrl(Request $request)
+    {
+        $url = preg_replace(
+            [
+                '|index\.php|',
+                '|https?://' . $_SERVER['HTTP_HOST'] . '(:\d+)?' . '|'
+            ],
+            ['', ''],
+            $request->getUri()->getBaseUrl()
+        );
+        if (strlen($url) && substr($url, -1) !== '/') {
+            $url .= '/';
+        }
+        return $url;
+    }
+}
diff --git a/galette/lib/Galette/Controllers/AuthController.php b/galette/lib/Galette/Controllers/AuthController.php
new file mode 100644 (file)
index 0000000..1fc760f
--- /dev/null
@@ -0,0 +1,240 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Galette authentication controller
+ *
+ * PHP version 5
+ *
+ * Copyright © 2019-2020 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Entity
+ * @package   Galette
+ *
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2019-2020 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version   SVN: $Id$
+ * @link      http://galette.tuxfamily.org
+ * @since     Available since 0.9.4dev - 2019-12-02
+ */
+
+namespace Galette\Controllers;
+
+use Slim\Http\Request;
+use Slim\Http\Response;
+use Galette\Core\SysInfos;
+use Galette\Core\Login;
+use Analog\Analog;
+
+/**
+ * Galette authentication controller
+ *
+ * @category  Controllers
+ * @name      AuthController
+ * @package   Galette
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2019-2020 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @link      http://galette.tuxfamily.org
+ * @since     Available since 0.9.4dev - 2019-12-02
+ */
+
+class AuthController extends AbstractController
+{
+    /**
+     * Log in
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     * @param array    $args     Request arguments ['r']
+     *
+     * @return void
+     */
+    public function login(Request $request, Response $response, array $args = [])
+    {
+        //store redirect path if any
+        if (isset($args['r'])
+            && $args['r'] != '/logout'
+            && $args['r'] != '/login'
+        ) {
+            $this->session->urlRedirect = $args['r'];
+        }
+
+        if (!$this->login->isLogged()) {
+            // display page
+            $this->view->render(
+                $response,
+                'index.tpl',
+                array(
+                    'page_title'    => _T("Login"),
+                )
+            );
+            return $response;
+        } else {
+            return $this->galetteRedirect($request, $response, $args);
+        }
+    }
+
+    /**
+     * Do login
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     *
+     * @return void
+     */
+    public function doLogin(Request $request, Response $response)
+    {
+        $nick = $request->getParsedBody()['login'];
+        $password = $request->getParsedBody()['password'];
+        $checkpass = new \Galette\Util\Password($this->preferences);
+
+        if (trim($nick) == '' || trim($password) == '') {
+            $this->flash->addMessage(
+                'loginfault',
+                _T("You must provide both login and password.")
+            );
+            return $response
+                ->withStatus(301)
+                ->withHeader('Location', $this->router->pathFor('login'));
+        }
+
+        if ($nick === $this->preferences->pref_admin_login) {
+            $pw_superadmin = password_verify(
+                $password,
+                $this->preferences->pref_admin_pass
+            );
+            if (!$pw_superadmin) {
+                $pw_superadmin = (
+                    md5($password) === $this->preferences->pref_admin_pass
+                );
+            }
+            if ($pw_superadmin) {
+                $this->login->logAdmin($nick, $this->preferences);
+            }
+        } else {
+            $this->login->logIn($nick, $password);
+        }
+
+        if ($this->login->isLogged()) {
+            if (!$checkpass->isValid($password)) {
+                //password is no longer valid with current rules, must be changed
+                $this->flash->addMessage(
+                    'warning_detected',
+                    _T("Your password is too weak! Please consider updating it.") .
+                    '<br/> -' . implode('<br/>', $checkpass->getErrors())
+                );
+            }
+            $this->session->login = $this->login;
+            $this->history->add(_T("Login"));
+            return $this->galetteRedirect($request, $response, []);
+        } else {
+            $this->flash->addMessage('error_detected', _T("Login failed."));
+            $this->history->add(_T("Authentication failed"), $nick);
+            return $response->withStatus(301)->withHeader('Location', $this->router->pathFor('login'));
+        }
+    }
+
+    /**
+     * Log out
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     *
+     * @return void
+     */
+    public function logout(Request $request, Response $response)
+    {
+        $this->login->logOut();
+        $this->history->add(_T("Log off"));
+        \RKA\Session::destroy();
+        return $response
+            ->withStatus(301)
+            ->withHeader('Location', $this->router->pathFor('slash'));
+    }
+
+    /**
+     * Impersonate
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     * @param array    $args     Request arguments ['id']
+     *
+     * @return void
+     */
+    public function impersonate(Request $request, Response $response, array $args)
+    {
+        $success = $this->login->impersonate((int)$args['id']);
+
+        if ($success === true) {
+            $this->session->login = $this->login;
+            $msg = str_replace(
+                '%login',
+                $this->login->login,
+                _T("Impersonating as %login")
+            );
+
+            $this->history->add($msg);
+            $this->flash->addMessage(
+                'success_detected',
+                $msg
+            );
+        } else {
+            $msg = str_replace(
+                '%id',
+                $id,
+                _T("Unable to impersonate as %id")
+            );
+            $this->flash->addMessage(
+                'error_detected',
+                $msg
+            );
+            $this->history->add($msg);
+        }
+
+        return $response
+            ->withStatus(301)
+            ->withHeader('Location', $this->router->pathFor('slash'));
+    }
+
+    /**
+     * End impersonate
+     *
+     * @param Request  $request  PSR Request
+     * @param Response $response PSR Response
+     *
+     * @return void
+     */
+    public function unimpersonate(Request $request, Response $response)
+    {
+        $login = new Login($this->zdb, $this->i18n, $this->session);
+        $login->logAdmin($this->preferences->pref_admin_login, $this->preferences);
+        $this->history->add(_T("Impersonating ended"));
+        $this->session->login = $login;
+        $this->login = $login;
+        $this->flash->addMessage(
+            'success_detected',
+            _T("Impersonating ended")
+        );
+        return $response
+            ->withStatus(301)
+            ->withHeader('Location', $this->router->pathFor('slash'));
+    }
+}