From 257917ea38836aa2cdd52f76bbcdae0da629e905 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Fri, 4 Aug 2023 17:04:04 +0200 Subject: [PATCH] Disallow the edition of profiles managed by LDAP --- src/Controller/ProfileController.php | 24 ++- templates/profile/edit.html.twig | 175 +++++++++++---------- tests/Controller/ProfileControllerTest.php | 29 ++++ translations/errors+intl-icu.en_GB.yaml | 1 + translations/errors+intl-icu.fr_FR.yaml | 1 + translations/messages+intl-icu.en_GB.yaml | 2 + translations/messages+intl-icu.fr_FR.yaml | 2 + 7 files changed, 153 insertions(+), 81 deletions(-) diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index 64c7389b..0d40beb9 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -8,6 +8,7 @@ use App\Repository\UserRepository; use App\Utils\ConstraintErrorsFormatter; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -20,13 +21,16 @@ class ProfileController extends BaseController { #[Route('/profile', name: 'profile', methods: ['GET', 'HEAD'])] - public function edit(): Response - { + public function edit( + #[Autowire(env: 'bool:LDAP_ENABLED')] + string $ldapEnabled, + ): Response { /** @var \App\Entity\User $user */ $user = $this->getUser(); return $this->render('profile/edit.html.twig', [ 'name' => $user->getName(), 'email' => $user->getEmail(), + 'managedByLdap' => $ldapEnabled && $user->getAuthType() === 'ldap', ]); } @@ -38,6 +42,8 @@ public function update( ValidatorInterface $validator, RequestStack $requestStack, TranslatorInterface $translator, + #[Autowire(env: 'bool:LDAP_ENABLED')] + string $ldapEnabled, ): Response { /** @var \App\Entity\User $user */ $user = $this->getUser(); @@ -60,10 +66,22 @@ public function update( /** @var string $csrfToken */ $csrfToken = $request->request->get('_csrf_token', ''); + $managedByLdap = $ldapEnabled && $user->getAuthType() === 'ldap'; + + if ($managedByLdap) { + return $this->renderBadRequest('profile/edit.html.twig', [ + 'name' => $name, + 'email' => $email, + 'managedByLdap' => $managedByLdap, + 'error' => $translator->trans('user.ldap.cannot_update_profile', [], 'errors'), + ]); + } + if (!$this->isCsrfTokenValid('update profile', $csrfToken)) { return $this->renderBadRequest('profile/edit.html.twig', [ 'name' => $name, 'email' => $email, + 'managedByLdap' => $managedByLdap, 'error' => $translator->trans('csrf.invalid', [], 'errors'), ]); } @@ -73,6 +91,7 @@ public function update( return $this->renderBadRequest('profile/edit.html.twig', [ 'name' => $name, 'email' => $email, + 'managedByLdap' => $managedByLdap, 'errors' => [ 'password' => $translator->trans('user.password.dont_match', [], 'errors'), ], @@ -92,6 +111,7 @@ public function update( return $this->renderBadRequest('profile/edit.html.twig', [ 'name' => $name, 'email' => $email, + 'managedByLdap' => $managedByLdap, 'errors' => ConstraintErrorsFormatter::format($errors), ]); } diff --git a/templates/profile/edit.html.twig b/templates/profile/edit.html.twig index db82f16e..2dcf7f1a 100644 --- a/templates/profile/edit.html.twig +++ b/templates/profile/edit.html.twig @@ -29,12 +29,21 @@ {{ 'profile.note' | trans }}

+ {{ include('alerts/_alert.html.twig', { + type: 'info', + title: 'profile.ldap.information' | trans, + message: 'profile.ldap.managed' | trans, + }, with_context = false) }} +
{% if errors.name is defined %} @@ -55,6 +64,7 @@ aria-invalid="true" aria-errormessage="name-error" {% endif %} + {{ managedByLdap ? 'disabled' }} />
@@ -81,91 +91,98 @@ aria-invalid="true" aria-errormessage="email-error" {% endif %} + {{ managedByLdap ? 'disabled' }} /> -
- {{ 'users.password' | trans }} + {% if not managedByLdap %} +
+ {{ 'users.password' | trans }} -

- {{ 'profile.leave_password' | trans }} -

- -
- - - {% if errors.password is defined %} - - {% endif %} +

+ {{ 'profile.leave_password' | trans }} +

-
- - - +
+ + + {% if errors.password is defined %} + + {% endif %} + +
+ + + +
-
-
- - -
- - - +
+ + +
+ + + +
+
+ +
+
-
- -
- -
+ {% endif %} {% endblock %} diff --git a/tests/Controller/ProfileControllerTest.php b/tests/Controller/ProfileControllerTest.php index 1e6b22e1..cfc802c4 100644 --- a/tests/Controller/ProfileControllerTest.php +++ b/tests/Controller/ProfileControllerTest.php @@ -167,6 +167,35 @@ public function testPostUpdateFailsIfCurrentPasswordIsInvalid(): void $this->assertFalse($passwordHasher->isPasswordValid($user->object(), $newPassword)); } + public function testPostUpdateFailsIfManagedByLdap(): void + { + $client = static::createClient(); + $initialName = Factory::faker()->unique()->userName(); + $newName = Factory::faker()->unique()->userName(); + $initialEmail = Factory::faker()->unique()->email(); + $newEmail = Factory::faker()->unique()->email(); + $user = UserFactory::createOne([ + 'name' => $initialName, + 'email' => $initialEmail, + 'ldapIdentifier' => 'charlie', + ]); + $client->loginUser($user->object()); + + $client->request('POST', '/profile', [ + '_csrf_token' => $this->generateCsrfToken($client, 'update profile'), + 'name' => $newName, + 'email' => $newEmail, + ]); + + $this->assertSelectorTextContains( + '[data-test="alert-error"]', + 'You can’t update your profile because it’s managed by LDAP.', + ); + $user->refresh(); + $this->assertSame($initialName, $user->getName()); + $this->assertSame($initialEmail, $user->getEmail()); + } + public function testPostUpdateFailsIfCsrfTokenIsInvalid(): void { $client = static::createClient(); diff --git a/translations/errors+intl-icu.en_GB.yaml b/translations/errors+intl-icu.en_GB.yaml index 9f35847f..08c0b684 100644 --- a/translations/errors+intl-icu.en_GB.yaml +++ b/translations/errors+intl-icu.en_GB.yaml @@ -39,5 +39,6 @@ user.email.invalid: 'Enter a valid email address.' user.email.required: 'Enter an email address.' user.language.invalid: 'Select a language from the list.' user.language.required: 'Select a language.' +user.ldap.cannot_update_profile: 'You can’t update your profile because it’s managed by LDAP.' user.name.max_chars: 'Enter a name of less than {limit} characters.' user.password.dont_match: 'The password does not match, please try with a different one.' diff --git a/translations/errors+intl-icu.fr_FR.yaml b/translations/errors+intl-icu.fr_FR.yaml index 2b332d33..5cae72b6 100644 --- a/translations/errors+intl-icu.fr_FR.yaml +++ b/translations/errors+intl-icu.fr_FR.yaml @@ -39,5 +39,6 @@ user.email.invalid: 'Saisissez une adresse email valide.' user.email.required: 'Saisissez une adresse email.' user.language.invalid: 'Sélectionnez une langue de la liste.' user.language.required: 'Sélectionnez une langue.' +user.ldap.cannot_update_profile: 'Vous ne pouvez pas modifier votre profil car il est géré avec LDAP.' user.name.max_chars: 'Saisissez un nom de moins de {limit} caractères.' user.password.dont_match: 'Le mot de passe ne correspond pas, veuillez essayer avec un différent.' diff --git a/translations/messages+intl-icu.en_GB.yaml b/translations/messages+intl-icu.en_GB.yaml index a54c4b96..585e23b9 100644 --- a/translations/messages+intl-icu.en_GB.yaml +++ b/translations/messages+intl-icu.en_GB.yaml @@ -124,6 +124,8 @@ organizations.new.title: 'New organization' organizations.parent_orga: 'Parent organization' preferences.title: Preferences profile.current_password: 'Current password' +profile.ldap.information: Information +profile.ldap.managed: 'You can’t change your profile because your account is managed by LDAP.' profile.leave_password: 'Leave these fields blank to keep your current password.' profile.new_password: 'New password' profile.note: 'Note: the information of your profile can be visible to the other users.' diff --git a/translations/messages+intl-icu.fr_FR.yaml b/translations/messages+intl-icu.fr_FR.yaml index 8d5080fd..e28fdce6 100644 --- a/translations/messages+intl-icu.fr_FR.yaml +++ b/translations/messages+intl-icu.fr_FR.yaml @@ -124,6 +124,8 @@ organizations.new.title: 'Nouvelle organisation' organizations.parent_orga: 'Organisation parente' preferences.title: Préférences profile.current_password: 'Mot de passe actuel' +profile.ldap.information: Information +profile.ldap.managed: 'Vous ne pouvez pas modifier votre profil car votre compte est géré avec LDAP.' profile.leave_password: 'Laissez ces champs vides pour conserver votre mot de passe actuel.' profile.new_password: 'Nouveau mot de passe' profile.note: "Note\_: les informations de votre profil peuvent être visibles par les autres utilisateurs."