Skip to content

Commit 614f100

Browse files
committed
refactor: migrated logout (#3834)
1 parent 3fcb39e commit 614f100

File tree

7 files changed

+90
-31
lines changed

7 files changed

+90
-31
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Notification exports for template usage
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public License,
5+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
6+
* obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* @package phpMyFAQ
9+
* @author Thorsten Rinne
10+
* @copyright 2026 phpMyFAQ Team
11+
* @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
12+
* @link https://www.phpmyfaq.de
13+
* @since 2026-01-02
14+
*/
15+
16+
export { pushNotification, pushErrorNotification } from './utils/notifications';

phpmyfaq/assets/templates/default/index.twig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,5 +231,16 @@
231231
{% endfor %}
232232
{% endif %}
233233
<script type="module" src="./assets/public/frontend.js"></script>
234+
{% if successMessage or errorMessage %}
235+
<script type="module">
236+
import { pushNotification, pushErrorNotification } from './assets/public/notifications.js';
237+
{% if successMessage %}
238+
pushNotification('{{ successMessage|e('js') }}');
239+
{% endif %}
240+
{% if errorMessage %}
241+
pushErrorNotification('{{ errorMessage|e('js') }}');
242+
{% endif %}
243+
</script>
244+
{% endif %}
234245
</body>
235246
</html>

phpmyfaq/index.php

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -211,27 +211,6 @@
211211
$action = 'twofactor';
212212
}
213213

214-
//
215-
// Logout
216-
//
217-
if ($csrfChecked && 'logout' === $action && $user->isLoggedIn()) {
218-
$user->deleteFromSession(true);
219-
$action = 'main';
220-
$ssoLogout = $faqConfig->get('security.ssoLogoutRedirect');
221-
222-
if ($faqConfig->get('security.ssoSupport') && !empty($ssoLogout)) {
223-
$redirect = new RedirectResponse($ssoLogout);
224-
$redirect->send();
225-
}
226-
227-
if ($faqConfig->isSignInWithMicrosoftActive() && $user->getUserAuthSource() === 'azure') {
228-
$redirect = new RedirectResponse($faqConfig->getDefaultUrl() . 'services/azure/logout.php');
229-
$redirect->send();
230-
}
231-
232-
$redirect = new RedirectResponse($faqConfig->getDefaultUrl());
233-
$redirect->send();
234-
}
235214

236215
//
237216
// Get current user and group id - default: -1
@@ -701,10 +680,6 @@
701680

702681
$response->setContent($twigTemplate->render($templateVars));
703682

704-
if ('logout' === $action) {
705-
$response->headers->set('Cache-Control', 'no-cache, no-store, private');
706-
$response->headers->set('Vary', 'Accept-Language, Accept-Encoding, Cookie');
707-
}
708683

709684
$response->setCache([
710685
'must_revalidate' => false,

phpmyfaq/src/phpMyFAQ/Controller/Frontend/AbstractFrontController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,15 @@ protected function getHeader(Request $request): array
4848
PermissionType::VIEW_ADMIN_LINK->value,
4949
);
5050

51+
// Get flash messages
52+
$session = $this->container->get('session');
53+
$successMessages = $session->getFlashBag()->get('success');
54+
$errorMessages = $session->getFlashBag()->get('error');
55+
5156
return [
5257
...$this->getUserDropdown(),
58+
'successMessage' => !empty($successMessages) ? $successMessages[0] : null,
59+
'errorMessage' => !empty($errorMessages) ? $errorMessages[0] : null,
5360
'isMaintenanceMode' => $this->configuration->get('main.maintenanceMode'),
5461
'isCompletelySecured' => $this->configuration->get('security.enableLoginOnly'),
5562
'isDebugEnabled' => Environment::isDebugMode(),

phpmyfaq/src/phpMyFAQ/Controller/Frontend/LoginController.php renamed to phpmyfaq/src/phpMyFAQ/Controller/Frontend/AuthenticationController.php

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
/**
4-
* Login Controller
4+
* Authentication Controller to handle login, logout, and password reset
55
*
66
* This Source Code Form is subject to the terms of the Mozilla Public License,
77
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -18,20 +18,24 @@
1818
namespace phpMyFAQ\Controller\Frontend;
1919

2020
use phpMyFAQ\Core\Exception;
21+
use phpMyFAQ\Filter;
22+
use phpMyFAQ\Session\Token;
2123
use phpMyFAQ\Translation;
24+
use phpMyFAQ\User\CurrentUser;
25+
use Symfony\Component\HttpFoundation\RedirectResponse;
2226
use Symfony\Component\HttpFoundation\Request;
2327
use Symfony\Component\HttpFoundation\Response;
2428
use Symfony\Component\Routing\Attribute\Route;
2529
use Twig\Error\LoaderError;
2630

27-
final class LoginController extends AbstractFrontController
31+
final class AuthenticationController extends AbstractFrontController
2832
{
2933
/**
3034
* @throws Exception
3135
* @throws LoaderError
3236
* @throws \Exception
3337
*/ #[Route(path: '/login', name: 'public.login')]
34-
public function index(Request $request): Response
38+
public function login(Request $request): Response
3539
{
3640
$faqSession = $this->container->get('phpmyfaq.user.session');
3741
$faqSession->setCurrentUser($this->currentUser);
@@ -83,4 +87,41 @@ public function forgotPassword(Request $request): Response
8387
'password' => Translation::get(key: 'ad_auth_passwd'),
8488
]);
8589
}
90+
91+
/**
92+
* @throws \Exception
93+
*/
94+
#[Route(path: '/logout', name: 'public.logout')]
95+
public function logout(Request $request): Response
96+
{
97+
$user = CurrentUser::getCurrentUser($this->configuration);
98+
$csrfToken = Filter::filterVar($request->query->get('csrf'), FILTER_SANITIZE_SPECIAL_CHARS);
99+
100+
if (!Token::getInstance($this->container->get('session'))->verifyToken('logout', $csrfToken)) {
101+
return new RedirectResponse($this->configuration->getDefaultUrl());
102+
}
103+
104+
if (!$user->isLoggedIn()) {
105+
return new RedirectResponse($this->configuration->getDefaultUrl());
106+
}
107+
108+
$user->deleteFromSession(true);
109+
110+
// Add a success message
111+
$session = $this->container->get('session');
112+
$session->getFlashBag()->add('success', Translation::get('ad_logout'));
113+
114+
// SSO Logout
115+
$ssoLogout = $this->configuration->get('security.ssoLogoutRedirect');
116+
if ($this->configuration->get('security.ssoSupport') && !empty($ssoLogout)) {
117+
return new RedirectResponse($ssoLogout);
118+
}
119+
120+
// Microsoft Azure Logout
121+
if ($this->configuration->isSignInWithMicrosoftActive() && $user->getUserAuthSource() === 'azure') {
122+
return new RedirectResponse($this->configuration->getDefaultUrl() . 'services/azure/logout.php');
123+
}
124+
125+
return new RedirectResponse($this->configuration->getDefaultUrl());
126+
}
86127
}

phpmyfaq/src/public-routes.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
use phpMyFAQ\Controller\Frontend\ContactController;
2424
use phpMyFAQ\Controller\Frontend\FaqController;
2525
use phpMyFAQ\Controller\Frontend\GlossaryController;
26-
use phpMyFAQ\Controller\Frontend\LoginController;
26+
use phpMyFAQ\Controller\Frontend\AuthenticationController;
2727
use phpMyFAQ\Controller\Frontend\NewsController;
2828
use phpMyFAQ\Controller\Frontend\QuestionsController;
2929
use phpMyFAQ\Controller\Frontend\OverviewController;
@@ -81,7 +81,7 @@
8181
],
8282
'public.forgot-password' => [
8383
'path' => '/forgot-password',
84-
'controller' => [LoginController::class, 'forgotPassword'],
84+
'controller' => [AuthenticationController::class, 'forgotPassword'],
8585
'methods' => 'GET|POST',
8686
],
8787
'public.glossary' => [
@@ -91,9 +91,14 @@
9191
],
9292
'public.login' => [
9393
'path' => '/login',
94-
'controller' => [LoginController::class, 'index'],
94+
'controller' => [AuthenticationController::class, 'login'],
9595
'methods' => 'GET|POST',
9696
],
97+
'public.logout' => [
98+
'path' => '/user/logout',
99+
'controller' => [AuthenticationController::class, 'logout'],
100+
'methods' => 'GET',
101+
],
97102
'public.news' => [
98103
'path' => '/news/{newsId}/{newsLang}/{slug}.html',
99104
'controller' => [NewsController::class, 'index'],

vite.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default defineConfig({
1212
input: {
1313
backend: path.resolve(__dirname, 'phpmyfaq/admin/assets/src/index.ts'),
1414
frontend: path.resolve(__dirname, 'phpmyfaq/assets/src/frontend.ts'),
15+
notifications: path.resolve(__dirname, 'phpmyfaq/assets/src/notifications-export.ts'),
1516
cookieConsent: path.resolve(__dirname, 'phpmyfaq/assets/src/cookie-consent.ts'),
1617
setup: path.resolve(__dirname, 'phpmyfaq/assets/src/setup.ts'),
1718
update: path.resolve(__dirname, 'phpmyfaq/assets/src/update.ts'),
@@ -24,12 +25,15 @@ export default defineConfig({
2425
format: 'es',
2526
entryFileNames: '[name].js',
2627
assetFileNames: '[name].[ext]',
28+
preserveModules: false,
29+
exports: 'named',
2730
manualChunks: {
2831
bootstrap: ['bootstrap'],
2932
chart: ['chart.js'],
3033
jodit: ['jodit'],
3134
},
3235
},
36+
preserveEntrySignatures: 'exports-only',
3337
},
3438
sourcemap: true,
3539
minify: 'terser',

0 commit comments

Comments
 (0)