]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - application/front/controller/visitor/LoginController.php
f5038fe391137720448a6aa0be6a87c8bed7ea50
[github/shaarli/Shaarli.git] / application / front / controller / visitor / LoginController.php
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Shaarli\Front\Controller\Visitor;
6
7 use Shaarli\Front\Exception\CantLoginException;
8 use Shaarli\Front\Exception\LoginBannedException;
9 use Shaarli\Front\Exception\WrongTokenException;
10 use Shaarli\Render\TemplatePage;
11 use Shaarli\Security\CookieManager;
12 use Shaarli\Security\SessionManager;
13 use Slim\Http\Request;
14 use Slim\Http\Response;
15
16 /**
17 * Class LoginController
18 *
19 * Slim controller used to render the login page.
20 *
21 * The login page is not available if the user is banned
22 * or if open shaarli setting is enabled.
23 */
24 class LoginController extends ShaarliVisitorController
25 {
26 /**
27 * GET /login - Display the login page.
28 */
29 public function index(Request $request, Response $response): Response
30 {
31 try {
32 $this->checkLoginState();
33 } catch (CantLoginException $e) {
34 return $this->redirect($response, '/');
35 }
36
37 if ($request->getParam('login') !== null) {
38 $this->assignView('username', escape($request->getParam('login')));
39 }
40
41 $returnUrl = $request->getParam('returnurl') ?? $this->container->environment['HTTP_REFERER'] ?? null;
42
43 $this
44 ->assignView('returnurl', escape($returnUrl))
45 ->assignView('remember_user_default', $this->container->conf->get('privacy.remember_user_default', true))
46 ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli'))
47 ;
48
49 return $response->write($this->render(TemplatePage::LOGIN));
50 }
51
52 /**
53 * POST /login - Process login
54 */
55 public function login(Request $request, Response $response): Response
56 {
57 if (!$this->container->sessionManager->checkToken($request->getParam('token'))) {
58 throw new WrongTokenException();
59 }
60
61 try {
62 $this->checkLoginState();
63 } catch (CantLoginException $e) {
64 return $this->redirect($response, '/');
65 }
66
67 if (!$this->container->loginManager->checkCredentials(
68 client_ip_id($this->container->environment),
69 $request->getParam('login'),
70 $request->getParam('password')
71 )
72 ) {
73 $this->container->loginManager->handleFailedLogin($this->container->environment);
74
75 $this->container->sessionManager->setSessionParameter(
76 SessionManager::KEY_ERROR_MESSAGES,
77 [t('Wrong login/password.')]
78 );
79
80 // Call controller directly instead of unnecessary redirection
81 return $this->index($request, $response);
82 }
83
84 $this->container->loginManager->handleSuccessfulLogin($this->container->environment);
85
86 $cookiePath = $this->container->basePath . '/';
87 $expirationTime = $this->saveLongLastingSession($request, $cookiePath);
88 $this->renewUserSession($cookiePath, $expirationTime);
89
90 // Force referer from given return URL
91 $this->container->environment['HTTP_REFERER'] = $request->getParam('returnurl');
92
93 return $this->redirectFromReferer($request, $response, ['login', 'install']);
94 }
95
96 /**
97 * Make sure that the user is allowed to login and/or displaying the login page:
98 * - not already logged in
99 * - not open shaarli
100 * - not banned
101 */
102 protected function checkLoginState(): bool
103 {
104 if ($this->container->loginManager->isLoggedIn()
105 || $this->container->conf->get('security.open_shaarli', false)
106 ) {
107 throw new CantLoginException();
108 }
109
110 if (true !== $this->container->loginManager->canLogin($this->container->environment)) {
111 throw new LoginBannedException();
112 }
113
114 return true;
115 }
116
117 /**
118 * @return int Session duration in seconds
119 */
120 protected function saveLongLastingSession(Request $request, string $cookiePath): int
121 {
122 if (empty($request->getParam('longlastingsession'))) {
123 // Standard session expiration (=when browser closes)
124 $expirationTime = 0;
125 } else {
126 // Keep the session cookie even after the browser closes
127 $this->container->sessionManager->setStaySignedIn(true);
128 $expirationTime = $this->container->sessionManager->extendSession();
129 }
130
131 $this->container->cookieManager->setCookieParameter(
132 CookieManager::STAY_SIGNED_IN,
133 $this->container->loginManager->getStaySignedInToken(),
134 $expirationTime,
135 $cookiePath
136 );
137
138 return $expirationTime;
139 }
140
141 protected function renewUserSession(string $cookiePath, int $expirationTime): void
142 {
143 // Send cookie with the new expiration date to the browser
144 $this->container->sessionManager->destroy();
145 $this->container->sessionManager->cookieParameters(
146 $expirationTime,
147 $cookiePath,
148 $this->container->environment['SERVER_NAME']
149 );
150 $this->container->sessionManager->start();
151 $this->container->sessionManager->regenerateId(true);
152 }
153 }