Repository: urlaubsverwaltung/urlaubsverwaltung
Pull request #5145 (2025-02-10 22:43:32)

user locale: introduce AuthenticationSuccessEventListener
so maintaining the locale after a successfull authentication is extracted in this listener

<!--

Thanks for contributing to the Urlaubsverwaltung.
Please review the following notes before submitting you pull request.

Please look for other issues or pull requests which already work on this topic. Is somebody already on it? Do you need to synchronize?

# Security Vulnerabilities

🛑 STOP! 🛑 If your contribution fixes a security vulnerability, please do not submit it.
Instead, please open a report of a security vulnerability via
[Report a security vulnerability](https://github.com/urlaubsverwaltung/urlaubsverwaltung/security/advisories/new)


# Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please
provide a brief description of the proposed changes.

If they:
 🐞 fix a bug, please describe the broken behaviour and how the changes fix it.
    Please label with 'type: bug' and 'status: new'
    
 🎁 make an enhancement, please describe the new functionality and why you believe it's useful.
    Please label with 'type: enhancement' and 'status: new'
 
If your pull request relates to any existing issues,
please reference them by using the issue number prefixed with #.

-->


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [15 New issues](https://sonarcloud.io/project/issues?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [96.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [96.2% Coverage on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=urlaubsverwaltung_urlaubsverwaltung&pullRequest=5145)



Patch:
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListener.java b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListener.java
new file mode 100644
index 000000000..8417187c6
--- /dev/null
+++ b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListener.java
@@ -0,0 +1,72 @@
+package org.synyx.urlaubsverwaltung.user;
+
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.context.event.EventListener;
+import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.LocaleResolver;
+import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.person.PersonService;
+import org.synyx.urlaubsverwaltung.tenancy.configuration.single.ConditionalOnSingleTenantMode;
+
+import java.util.Locale;
+import java.util.Optional;
+
+/**
+ * Event listener that listens to successful authentication events of a person
+ * and maintains the locale of the person in the user settings as well as
+ * in the browser.
+ */
+@Service
+@ConditionalOnSingleTenantMode
+class UserSettingsEventListener {
+
+    private final LocaleResolver localeResolver;
+    private final PersonService personService;
+    private final UserSettingsService userSettingsService;
+
+    UserSettingsEventListener(
+        LocaleResolver localeResolver,
+        PersonService personService,
+        UserSettingsService userSettingsService
+    ) {
+        this.localeResolver = localeResolver;
+        this.personService = personService;
+        this.userSettingsService = userSettingsService;
+    }
+
+    @EventListener
+    public void handleAuthenticationSuccess(AuthenticationSuccessEvent event) {
+        final String userName = event.getAuthentication().getName();
+
+        personService.getPersonByUsername(userName).ifPresent(person -> {
+            updateUserSettingsWithLocaleBrowserSpecific(person);
+            userSettingsService.getLocale(person).ifPresent(this::setLocale);
+        });
+    }
+
+    private void updateUserSettingsWithLocaleBrowserSpecific(Person person) {
+        getRequest()
+            .map(ServletRequest::getLocale)
+            .ifPresent(locale -> userSettingsService.updateLocaleBrowserSpecific(person, locale));
+    }
+
+    private void setLocale(Locale locale) {
+        getRequest().ifPresent(request -> localeResolver.setLocale(request, null, locale));
+    }
+
+    private Optional<HttpServletRequest> getRequest() {
+        HttpServletRequest request = null;
+
+        final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+        if (requestAttributes != null) {
+            request = ((ServletRequestAttributes) requestAttributes).getRequest();
+        }
+
+        return Optional.ofNullable(request);
+    }
+}
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsService.java b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsService.java
index 32f784ac2..32fc0f3fe 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsService.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsService.java
@@ -5,9 +5,30 @@ import org.synyx.urlaubsverwaltung.person.Person;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 
 public interface UserSettingsService {
 
+    /**
+     * Returns the saved locale of the user
+     *
+     * @param person to retrieve the locale
+     * @return saved locale
+     */
+    Optional<Locale> getLocale(Person person);
+
+    /**
+     * Sets the browser specific locale from the request.
+     * <p>
+     * Only saves the browser specific locale if the saved 'locale' is null.
+     * If the saved 'locale' is null, that means, that the localization is based on the browser,
+     * and therefore we save it to use it in e-mail templates e.g.
+     *
+     * @param person                to save the browser specific locale
+     * @param localeBrowserSpecific browser specific locale
+     */
+    void updateLocaleBrowserSpecific(Person person, Locale localeBrowserSpecific);
+
     /**
      * Returns the effective locale of a list of persons.
      * <p>
@@ -19,5 +40,11 @@ public interface UserSettingsService {
      */
     Map<Person, Locale> getEffectiveLocale(List<Person> persons);
 
+    /**
+     * Returns the user settings for the given person
+     *
+     * @param person to retrieve user settings for
+     * @return user settings of the user
+     */
     UserSettings getUserSettingsForPerson(Person person);
 }
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceImpl.java b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceImpl.java
index a31c318e5..5b3d99ece 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceImpl.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceImpl.java
@@ -5,7 +5,6 @@ import jakarta.servlet.http.HttpServletRequest;
 import org.slf4j.Logger;
 import org.springframework.context.event.EventListener;
 import org.springframework.lang.Nullable;
-import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
@@ -13,7 +12,6 @@ import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.servlet.LocaleResolver;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonDeletedEvent;
-import org.synyx.urlaubsverwaltung.person.PersonService;
 
 import java.util.List;
 import java.util.Locale;
@@ -21,7 +19,6 @@ import java.util.Map;
 import java.util.Optional;
 
 import static java.lang.invoke.MethodHandles.lookup;
-import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toMap;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -32,13 +29,13 @@ class UserSettingsServiceImpl implements UserSettingsService {
 
     private final UserSettingsRepository userSettingsRepository;
     private final LocaleResolver localeResolver;
-    private final PersonService personService;
 
-    UserSettingsServiceImpl(UserSettingsRepository userSettingsRepository,
-                            LocaleResolver localeResolver, PersonService personService) {
+    UserSettingsServiceImpl(
+        UserSettingsRepository userSettingsRepository,
+        LocaleResolver localeResolver
+    ) {
         this.userSettingsRepository = userSettingsRepository;
         this.localeResolver = localeResolver;
-        this.personService = personService;
     }
 
     @EventListener
@@ -46,62 +43,17 @@ class UserSettingsServiceImpl implements UserSettingsService {
         userSettingsRepository.deleteByPerson(event.person());
     }
 
-    @EventListener
-    void handleAuthenticationSuccess(AuthenticationSuccessEvent event) {
-        final String userName = event.getAuthentication().getName();
-        final Optional<Person> maybePerson = personService.getPersonByUsername(userName);
-
-        getRequest()
-            .map(ServletRequest::getLocale)
-            .ifPresent(locale -> maybePerson.ifPresent(person -> updateLocaleBrowserSpecific(person, locale)));
-        maybePerson.flatMap(this::getLocale).ifPresent(this::setLocale);
-    }
-
     Optional<Theme> findThemeForUsername(String username) {
         return userSettingsRepository.findByPersonUsername(username).map(UserSettingsEntity::getTheme);
     }
 
-    Optional<Locale> getLocale(Person person) {
+    @Override
+    public Optional<Locale> getLocale(Person person) {
         return userSettingsRepository.findByPerson(person).map(UserSettingsEntity::getLocale);
     }
 
-    /**
-     * Updates the user settings of the person with the given attributes.
-     * <p>
-     * Also update the browser specific locale based on the given locale
-     * and if false with the locale from the request.
-     *
-     * @param person the person to update the {@link UserSettings} for.
-     * @param theme  the {@link Theme} for the person.
-     * @param locale the locale to set for the person. must be a {@link SupportedLocale} or {@code null} to use the user-agent as fallback.
-     * @return the updated {@link UserSettings}
-     */
-    UserSettings updateUserPreference(Person person, Theme theme, @Nullable Locale locale) {
-        final UserSettingsEntity entity = findForPersonOrGetDefault(person);
-        entity.setPersonId(person.getId());
-        entity.setTheme(theme);
-        entity.setLocale(locale);
-
-        final Locale localeFromRequest = locale == null ? getRequest().map(ServletRequest::getLocale).orElse(null) : null;
-        entity.setLocaleBrowserSpecific(localeFromRequest);
-
-        final UserSettingsEntity persistedEntity = userSettingsRepository.save(entity);
-        setLocale(persistedEntity.getLocale());
-
-        return toUserSettings(persistedEntity);
-    }
-
-    /**
-     * Sets the browser specific locale from the request.
-     * <p>
-     * Only saves the browser specific locale if the saved 'locale' is null.
-     * If the saved 'locale' is null, that means, that the localization is based on the browser,
-     * and therefore we save it to use it in e-mail templates e.g.
-     *
-     * @param person                to save the browser specific locale
-     * @param localeBrowserSpecific
-     */
-    void updateLocaleBrowserSpecific(Person person, Locale localeBrowserSpecific) {
+    @Override
+    public void updateLocaleBrowserSpecific(Person person, Locale localeBrowserSpecific) {
         userSettingsRepository.findByPerson(person)
             .ifPresentOrElse(userSettingsEntity -> {
                 if (userSettingsEntity.getLocale() == null) {
@@ -117,7 +69,7 @@ class UserSettingsServiceImpl implements UserSettingsService {
 
     @Override
     public Map<Person, Locale> getEffectiveLocale(List<Person> persons) {
-        final List<Long> personIds = persons.stream().map(Person::getId).collect(toList());
+        final List<Long> personIds = persons.stream().map(Person::getId).toList();
         final Map<Person, Locale> personLocale = userSettingsRepository.findByPersonIdIn(personIds).stream()
             .collect(toMap(
                 UserSettingsEntity::getPerson,
@@ -133,6 +85,32 @@ class UserSettingsServiceImpl implements UserSettingsService {
         return toUserSettings(entity);
     }
 
+    /**
+     * Updates the user settings of the person with the given attributes.
+     * <p>
+     * Also update the browser specific locale based on the given locale
+     * and if false with the locale from the request.
+     *
+     * @param person the person to update the {@link UserSettings} for.
+     * @param theme  the {@link Theme} for the person.
+     * @param locale the locale to set for the person. must be a {@link SupportedLocale} or {@code null} to use the user-agent as fallback.
+     * @return the updated {@link UserSettings}
+     */
+    UserSettings updateUserPreference(Person person, Theme theme, @Nullable Locale locale) {
+        final UserSettingsEntity entity = findForPersonOrGetDefault(person);
+        entity.setPersonId(person.getId());
+        entity.setTheme(theme);
+        entity.setLocale(locale);
+
+        final Locale localeFromRequest = locale == null ? getRequest().map(ServletRequest::getLocale).orElse(null) : null;
+        entity.setLocaleBrowserSpecific(localeFromRequest);
+
+        final UserSettingsEntity persistedEntity = userSettingsRepository.save(entity);
+        setLocale(persistedEntity.getLocale());
+
+        return toUserSettings(persistedEntity);
+    }
+
     private static Locale getEffectiveLocale(UserSettingsEntity userSettingsEntity) {
         return Optional.ofNullable(userSettingsEntity.getLocale())
             .or(() -> Optional.ofNullable(userSettingsEntity.getLocaleBrowserSpecific()))


Test patch:
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListenerTest.java b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListenerTest.java
new file mode 100644
index 000000000..af1e72db7
--- /dev/null
+++ b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsEventListenerTest.java
@@ -0,0 +1,115 @@
+package org.synyx.urlaubsverwaltung.user;
+
+
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
+import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.LocaleResolver;
+import org.synyx.urlaubsverwaltung.person.Person;
+import org.synyx.urlaubsverwaltung.person.PersonService;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.util.Locale.GERMAN;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class UserSettingsEventListenerTest {
+
+    @InjectMocks
+    private UserSettingsEventListener sut;
+
+    @Mock
+    private UserSettingsService userSettingsService;
+    @Mock
+    private LocaleResolver localeResolver;
+    @Mock
+    private PersonService personService;
+
+
+    @AfterEach
+    void tearDown() {
+        RequestContextHolder.resetRequestAttributes();
+    }
+
+    @Test
+    void ensuresBrowserLocalePresentWillDelegateToUpdateLocaleBrowserSpecific() {
+
+        final Locale locale = GERMAN;
+        final Authentication authentication = authToken("username");
+
+        final Person person = new Person();
+        person.setId(1L);
+        person.setUsername("username");
+        when(personService.getPersonByUsername("username")).thenReturn(Optional.of(person));
+
+        // locale is provided via http request -> will be delegated to updateLocaleBrowserSpecific
+        final MockHttpServletRequest request = new MockHttpServletRequest();
+        request.addPreferredLocale(locale);
+        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+
+        // already configured locale will be set in the locale resolver
+        when(userSettingsService.getLocale(any())).thenReturn(Optional.of(locale));
+
+        final AuthenticationSuccessEvent authenticationSuccessEvent = new AuthenticationSuccessEvent(authentication);
+        sut.handleAuthenticationSuccess(authenticationSuccessEvent);
+
+        verify(userSettingsService).getLocale(person);
+
+        verify(userSettingsService).updateLocaleBrowserSpecific(person, locale);
+
+        verify(localeResolver).setLocale(request, null, locale);
+    }
+
+
+    @Test
+    void ensureWithoutBrowserLocaleNoInteractionWithUpdateLocaleBrowserSpecific() {
+
+        final Locale locale = GERMAN;
+        final Authentication authentication = authToken("username");
+
+        final Person person = new Person();
+        person.setId(1L);
+        person.setUsername("username");
+        when(personService.getPersonByUsername("username")).thenReturn(Optional.of(person));
+
+        // locale is missing via http request -> no interaction with updateLocaleBrowserSpecific
+        final MockHttpServletRequest request = new MockHttpServletRequest();
+        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+
+        // already configured locale will be set in the locale resolver
+        when(userSettingsService.getLocale(any())).thenReturn(Optional.of(locale));
+
+        final AuthenticationSuccessEvent authenticationSuccessEvent = new AuthenticationSuccessEvent(authentication);
+        sut.handleAuthenticationSuccess(authenticationSuccessEvent);
+
+        verify(userSettingsService).getLocale(person);
+
+        verify(userSettingsService, never()).updateLocaleBrowserSpecific(person, locale);
+
+        verify(localeResolver).setLocale(request, null, locale);
+    }
+
+    private static @NotNull TestingAuthenticationToken authToken(String username) {
+        return new TestingAuthenticationToken(new DefaultOidcUser(List.of(), new OidcIdToken("tokenValue", Instant.parse("2020-12-01T00:00:00.00Z"), Instant.parse("2020-12-02T00:00:00.00Z"), Map.of("sub", username))), null);
+    }
+}
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceTest.java b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceTest.java
index dbcd0455d..116cfee92 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/user/UserSettingsServiceTest.java
@@ -4,31 +4,18 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.authentication.TestingAuthenticationToken;
-import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.core.oidc.OidcIdToken;
-import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.servlet.LocaleResolver;
 import org.synyx.urlaubsverwaltung.person.Person;
 import org.synyx.urlaubsverwaltung.person.PersonDeletedEvent;
-import org.synyx.urlaubsverwaltung.person.PersonService;
 
-import java.time.Instant;
-import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Optional;
-import java.util.stream.Stream;
 
 import static java.util.Locale.ENGLISH;
 import static java.util.Locale.GERMAN;
@@ -46,12 +33,10 @@ class UserSettingsServiceTest {
     private UserSettingsRepository userSettingsRepository;
     @Mock
     private LocaleResolver localeResolver;
-    @Mock
-    private PersonService personService;
 
     @BeforeEach
     void setUp() {
-        sut = new UserSettingsServiceImpl(userSettingsRepository, localeResolver, personService);
+        sut = new UserSettingsServiceImpl(userSettingsRepository, localeResolver);
     }
 
     @AfterEach
@@ -280,34 +265,4 @@ class UserSettingsServiceTest {
         verify(userSettingsRepository).deleteByPerson(person);
     }
 
-    static Stream<Arguments> authentications() {
-        return Stream.of(
-            Arguments.of(new TestingAuthenticationToken(new DefaultOidcUser(List.of(), new OidcIdToken("tokenValue", Instant.parse("2020-12-01T00:00:00.00Z"), Instant.parse("2020-12-02T00:00:00.00Z"), Map.of("sub", "username"))), null), GERMAN),
-            Arguments.of(new TestingAuthenticationToken(new DefaultOidcUser(List.of(), new OidcIdToken("tokenValue", Instant.parse("2020-12-01T00:00:00.00Z"), Instant.parse("2020-12-02T00:00:00.00Z"), Map.of("sub", "username"))), null), ENGLISH)
-        );
-    }
-
-    @ParameterizedTest
-    @MethodSource("authentications")
-    void ensureAuthenticationSuccessSetsLocaleForAuthentication(Authentication authentication, Locale locale) {
-
-        final Person person = new Person();
-        person.setId(1L);
-        person.setUsername("username");
-        when(personService.getPersonByUsername("username")).thenReturn(Optional.of(person));
-
-        final MockHttpServletRequest request = new MockHttpServletRequest();
-        request.addPreferredLocale(locale);
-        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
-
-        final UserSettingsEntity userSettingsEntity = new UserSettingsEntity();
-        userSettingsEntity.setLocale(locale);
-
-        when(userSettingsRepository.findByPerson(person)).thenReturn(Optional.of(userSettingsEntity));
-
-        final AuthenticationSuccessEvent authenticationSuccessEvent = new AuthenticationSuccessEvent(authentication);
-        sut.handleAuthenticationSuccess(authenticationSuccessEvent);
-
-        verify(localeResolver).setLocale(request, null, locale);
-    }
 }