diff --git a/webapp/src/Controller/User/LoginController.php b/webapp/src/Controller/User/LoginController.php index 22d015238a8b727d8d899a2f47f715033cdc14ae..1f99b03a706ef5e7e9d2d73d91cde92d96affb7a 100644 --- a/webapp/src/Controller/User/LoginController.php +++ b/webapp/src/Controller/User/LoginController.php @@ -34,6 +34,7 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; use Symfony\Contracts\Translation\TranslatorInterface; @@ -50,8 +51,14 @@ class LoginController extends AbstractController name: 'app_account_login', methods: ['GET', 'POST'] )] - public function login(AuthenticationUtils $authenticationUtils): Response - { + public function login( + AuthenticationUtils $authenticationUtils, + AuthorizationCheckerInterface $authChecker, + ): Response { + if (true === $authChecker->isGranted('ROLE_USER')) { + return $this->redirectToRoute(route: 'app_user_account', status: Response::HTTP_SEE_OTHER); + } + // get the login error if there is one $error = $authenticationUtils->getLastAuthenticationError(); @@ -86,7 +93,12 @@ public function forgotPassword( UserTokenRepository $userTokenRepository, TokenGeneratorInterface $tokenGenerator, MailerPasswordResetLink $mailer, + AuthorizationCheckerInterface $authChecker, ): Response { + if (true === $authChecker->isGranted('ROLE_USER')) { + return $this->redirectToRoute(route: 'app_user_account', status: Response::HTTP_SEE_OTHER); + } + $tokenLifetime = $this->getParameter('app.user_config.reset_password_token_lifetime'); $form = $this->createForm(ResetPasswordRequestFormType::class); $form->handleRequest($request); @@ -155,7 +167,12 @@ public function forgotPasswordCheckToken( UserTokenRepository $tokenRepository, UserPasswordHasherInterface $userPasswordHasher, TranslatorInterface $translator, + AuthorizationCheckerInterface $authChecker, ): Response { + if (true === $authChecker->isGranted('ROLE_USER')) { + return $this->redirectToRoute(route: 'app_user_account', status: Response::HTTP_SEE_OTHER); + } + $minPasswordLength = $this->getParameter('app.user_config.min_password_length'); $form = $this->createForm( type: ResetPasswordFormType::class, diff --git a/webapp/tests/Functional/User/FunctionalTestConnectedUserCanNotDisplayAnonymousPagesTest.php b/webapp/tests/Functional/User/FunctionalTestConnectedUserCanNotDisplayAnonymousPagesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7a3eb0655d528c2280db09c3974d1aab7a8eb9c1 --- /dev/null +++ b/webapp/tests/Functional/User/FunctionalTestConnectedUserCanNotDisplayAnonymousPagesTest.php @@ -0,0 +1,137 @@ +<?php + +/* + * This file is part of the Comptoir-du-Libre software. + * <https://gitlab.adullact.net/Comptoir/comptoir-du-libre> + * + * Copyright (c) ADULLACT <https://adullact.org> + * Association des Développeurs et Utilisateurs de Logiciels Libres + * pour les Administrations et les Collectivités Territoriales + * + * Comptoir-du-Libre is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * You should have received a copy of the GNU Affero General Public License + * along with this software. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>. + */ + +declare(strict_types=1); + +namespace App\Tests\Functional\User; + +use App\DataFixtures\AppUserFixtures; +use App\Tests\Functional\TestHelperTrait; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\HttpFoundation\Response; + +class FunctionalTestConnectedUserCanNotDisplayAnonymousPagesTest extends WebTestCase +{ + use TestHelperTrait; + + private string $user1Email; + + protected function setUp(): void + { + $this->user1Email = AppUserFixtures::USER_REFERENCE_1; + } + + /** + * @param string $connectedUserEmail + * @param string $testedUrl + * @param string $expectedNewUrl + * @param int $expectedHttpCode by default: Response::HTTP_SEE_OTHER = 303 + * @param KernelBrowser|null $kernelBrowser + * @return KernelBrowser + */ + private function commonCheckerConnectedUserIsRedirectedToExpectedUrl( + string $connectedUserEmail, + string $testedUrl, + string $expectedNewUrl, + int $expectedHttpCode = Response::HTTP_SEE_OTHER, + KernelBrowser|null $kernelBrowser = null, + ): KernelBrowser { + if (\is_null($kernelBrowser)) { + $kernelBrowser = $this->getKernelBrowserWithConnectedUser($connectedUserEmail); + } else { + $kernelBrowser = $this->getKernelBrowserWithConnectedUser($connectedUserEmail, $kernelBrowser); + } + $kernelBrowser->request('GET', "$testedUrl"); + $this->assertResponseStatusCodeSame(expectedCode: $expectedHttpCode, message: 'Bad HTTP code response'); + $this->assertResponseHeaderSame( + headerName: "Location", + expectedValue: "$expectedNewUrl", + message: "Bad redirect location. Tested URL: $testedUrl" + ); + return $kernelBrowser; + } + + /** + * @group ConnectedUser + * @group ConnectedUser_canNotDisplayAnonymousPages + * @group CreateAccount + */ + public function testConnectedUserCanNotDisplaySignupPage(): void + { + $kernelBrowser = $this->commonCheckerConnectedUserIsRedirectedToExpectedUrl( + connectedUserEmail: $this->user1Email, + testedUrl: "/en/account/signup", + expectedNewUrl: "/en/user/account", + expectedHttpCode: Response::HTTP_SEE_OTHER, + ); + $this->commonCheckerConnectedUserIsRedirectedToExpectedUrl( + connectedUserEmail: $this->user1Email, + testedUrl: "/en/account/signup/t/nQfHAZtxFXh-B6TqIBV_vMpwZPshOVkfHt_LSilcZXI", + expectedNewUrl: "/en/user/account", + expectedHttpCode: Response::HTTP_SEE_OTHER, + kernelBrowser: $kernelBrowser, + ); + } + + /** + * @group ConnectedUser + * @group ConnectedUser_canNotDisplayAnonymousPages + * @group LoginPage + */ + public function testConnectedUserCanNotDisplayLoginPage(): void + { + $this->commonCheckerConnectedUserIsRedirectedToExpectedUrl( + connectedUserEmail: $this->user1Email, + testedUrl: "/en/account/login", + expectedNewUrl: "/en/user/account", + expectedHttpCode: Response::HTTP_SEE_OTHER, + ); + } + + /** + * @group ConnectedUser + * @group ConnectedUser_canNotDisplayAnonymousPages + * @group ForgotPasswordPage + */ + public function testConnectedUserCanNotDisplayForgotPasswordFormPage(): void + { + $this->commonCheckerConnectedUserIsRedirectedToExpectedUrl( + connectedUserEmail: $this->user1Email, + testedUrl: "/en/account/forgot-password", + expectedNewUrl: "/en/user/account", + expectedHttpCode: Response::HTTP_SEE_OTHER, + ); + } + + /** + * @group ConnectedUser + * @group ConnectedUser_canNotDisplayAnonymousPages + * @group ForgotPasswordPage + */ + public function testConnectedUserCanNotDisplayForgotPasswordResetLinkPage(): void + { + $this->commonCheckerConnectedUserIsRedirectedToExpectedUrl( + connectedUserEmail: $this->user1Email, + testedUrl: "/en/account/forgot-password/t/tU8zGN2dHB3XH7LYCN0ZzEMTlsr7XaGvgWLHP1pDNzM", + expectedNewUrl: "/en/user/account", + expectedHttpCode: Response::HTTP_SEE_OTHER, + ); + } +}