namespace Shaarli\Front\Controller\Visitor;
+use Shaarli\Front\Exception\CantLoginException;
use Shaarli\Front\Exception\LoginBannedException;
+use Shaarli\Front\Exception\WrongTokenException;
+use Shaarli\Render\TemplatePage;
+use Shaarli\Security\CookieManager;
+use Shaarli\Security\SessionManager;
use Slim\Http\Request;
use Slim\Http\Response;
*/
class LoginController extends ShaarliVisitorController
{
+ /**
+ * GET /login - Display the login page.
+ */
public function index(Request $request, Response $response): Response
{
- if ($this->container->loginManager->isLoggedIn()
- || $this->container->conf->get('security.open_shaarli', false)
- ) {
+ try {
+ $this->checkLoginState();
+ } catch (CantLoginException $e) {
return $this->redirect($response, '/');
}
- $userCanLogin = $this->container->loginManager->canLogin($request->getServerParams());
- if ($userCanLogin !== true) {
- throw new LoginBannedException();
+ if ($request->getParam('login') !== null) {
+ $this->assignView('username', escape($request->getParam('login')));
}
- if ($request->getParam('username') !== null) {
- $this->assignView('username', escape($request->getParam('username')));
- }
+ $returnUrl = $request->getParam('returnurl') ?? $this->container->environment['HTTP_REFERER'] ?? null;
$this
- ->assignView('returnurl', escape($request->getServerParam('HTTP_REFERER')))
+ ->assignView('returnurl', escape($returnUrl))
->assignView('remember_user_default', $this->container->conf->get('privacy.remember_user_default', true))
->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli'))
;
- return $response->write($this->render('loginform'));
+ return $response->write($this->render(TemplatePage::LOGIN));
+ }
+
+ /**
+ * POST /login - Process login
+ */
+ public function login(Request $request, Response $response): Response
+ {
+ if (!$this->container->sessionManager->checkToken($request->getParam('token'))) {
+ throw new WrongTokenException();
+ }
+
+ try {
+ $this->checkLoginState();
+ } catch (CantLoginException $e) {
+ return $this->redirect($response, '/');
+ }
+
+ if (!$this->container->loginManager->checkCredentials(
+ client_ip_id($this->container->environment),
+ $request->getParam('login'),
+ $request->getParam('password')
+ )
+ ) {
+ $this->container->loginManager->handleFailedLogin($this->container->environment);
+
+ $this->container->sessionManager->setSessionParameter(
+ SessionManager::KEY_ERROR_MESSAGES,
+ [t('Wrong login/password.')]
+ );
+
+ // Call controller directly instead of unnecessary redirection
+ return $this->index($request, $response);
+ }
+
+ $this->container->loginManager->handleSuccessfulLogin($this->container->environment);
+
+ $cookiePath = $this->container->basePath . '/';
+ $expirationTime = $this->saveLongLastingSession($request, $cookiePath);
+ $this->renewUserSession($cookiePath, $expirationTime);
+
+ // Force referer from given return URL
+ $this->container->environment['HTTP_REFERER'] = $request->getParam('returnurl');
+
+ return $this->redirectFromReferer($request, $response, ['login', 'install']);
+ }
+
+ /**
+ * Make sure that the user is allowed to login and/or displaying the login page:
+ * - not already logged in
+ * - not open shaarli
+ * - not banned
+ */
+ protected function checkLoginState(): bool
+ {
+ if ($this->container->loginManager->isLoggedIn()
+ || $this->container->conf->get('security.open_shaarli', false)
+ ) {
+ throw new CantLoginException();
+ }
+
+ if (true !== $this->container->loginManager->canLogin($this->container->environment)) {
+ throw new LoginBannedException();
+ }
+
+ return true;
+ }
+
+ /**
+ * @return int Session duration in seconds
+ */
+ protected function saveLongLastingSession(Request $request, string $cookiePath): int
+ {
+ if (empty($request->getParam('longlastingsession'))) {
+ // Standard session expiration (=when browser closes)
+ $expirationTime = 0;
+ } else {
+ // Keep the session cookie even after the browser closes
+ $this->container->sessionManager->setStaySignedIn(true);
+ $expirationTime = $this->container->sessionManager->extendSession();
+ }
+
+ $this->container->cookieManager->setCookieParameter(
+ CookieManager::STAY_SIGNED_IN,
+ $this->container->loginManager->getStaySignedInToken(),
+ $expirationTime,
+ $cookiePath
+ );
+
+ return $expirationTime;
+ }
+
+ protected function renewUserSession(string $cookiePath, int $expirationTime): void
+ {
+ // Send cookie with the new expiration date to the browser
+ $this->container->sessionManager->destroy();
+ $this->container->sessionManager->cookieParameters(
+ $expirationTime,
+ $cookiePath,
+ $this->container->environment['SERVER_NAME']
+ );
+ $this->container->sessionManager->start();
+ $this->container->sessionManager->regenerateId(true);
}
}