You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/12/13 17:11:29 UTC

[isis] branch master updated: ISIS-2918: plug user preferred Locale into framework interactions

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 87440ba  ISIS-2918: plug user preferred Locale into framework interactions
87440ba is described below

commit 87440bae5255a2955560189033ee5d78e6f96b8d
Author: andi-huber <ah...@apache.org>
AuthorDate: Mon Dec 13 18:11:19 2021 +0100

    ISIS-2918: plug user preferred Locale into framework interactions
---
 .../applib/services/iactnlayer/InteractionContext.java  | 13 ++++++++++---
 .../apache/isis/applib/services/user/UserMemento.java   | 17 ++++++++++++-----
 .../runtimeservices/wrapper/WrapperFactoryDefault.java  |  2 +-
 .../UserMementoRefinerFromApplicationUser.java          | 12 ++++++++----
 4 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
index d6eace9..ddda757 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
@@ -21,6 +21,7 @@ package org.apache.isis.applib.services.iactnlayer;
 import java.io.Serializable;
 import java.time.ZoneId;
 import java.util.Locale;
+import java.util.Optional;
 import java.util.function.UnaryOperator;
 import java.util.stream.Stream;
 
@@ -61,7 +62,6 @@ public class InteractionContext implements Serializable {
         return InteractionContext.builder()
                 .user(user)
                 .clock(VirtualClock.system())
-                .locale(Locale.getDefault())
                 .timeZone(ZoneId.systemDefault())
                 .build();
     }
@@ -87,8 +87,15 @@ public class InteractionContext implements Serializable {
     @With @Getter @Builder.Default
     final @NonNull VirtualClock clock = VirtualClock.system();
 
-    @With @Getter @Builder.Default
-    final @NonNull Locale locale = Locale.getDefault();
+    @With Locale locale;
+    public Locale getLocale(){
+        if(locale!=null) {
+            return locale; // if set, overrides any user preferences
+        }
+        return Optional.ofNullable(getUser())
+                .map(UserMemento::getLocale)
+                .orElseGet(Locale::getDefault);
+    }
 
     @With @Getter @Builder.Default
     final @NonNull ZoneId timeZone = ZoneId.systemDefault();
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.java
index 5a2bf1b..b581068 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.java
@@ -23,12 +23,12 @@ import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.net.URL;
 import java.util.List;
+import java.util.Locale;
 import java.util.stream.Stream;
 
-import org.springframework.lang.Nullable;
-
 import org.springframework.context.event.EventListener;
 import org.springframework.core.annotation.Order;
+import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.IsisModuleApplib;
 import org.apache.isis.applib.annotation.Collection;
@@ -69,7 +69,7 @@ public class UserMemento implements Serializable {
 
     public static class TitleUiEvent extends IsisModuleApplib.TitleUiEvent<UserMemento> {}
 
-    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+    private void readObject(final ObjectInputStream ois) throws ClassNotFoundException, IOException {
         ois.defaultReadObject();
     }
 
@@ -147,7 +147,7 @@ public class UserMemento implements Serializable {
     public static class UiSubscriber {
         @Order(PriorityPrecedence.LATE)
         @EventListener(UserMemento.TitleUiEvent.class)
-        public void on(UserMemento.TitleUiEvent ev) {
+        public void on(final UserMemento.TitleUiEvent ev) {
             val userMemento = ev.getSource();
             assert userMemento != null;
             val title = String.format("%s %s", userMemento.getName(), userMemento.isImpersonating() ? " (impersonating)" : "");
@@ -178,6 +178,12 @@ public class UserMemento implements Serializable {
     @Nullable
     URL avatarUrl;
 
+    @Property(optionality = Optionality.OPTIONAL)
+    @PropertyLayout(fieldSetId = "details", sequence = "3")
+    @Getter @With(onMethod_ = {@Programmatic})
+    @Nullable
+    Locale locale;
+
     /**
      * To support external security mechanisms such as keycloak,
      * where the validity of the session is defined by headers in the request.
@@ -253,7 +259,7 @@ public class UserMemento implements Serializable {
 
 
     @Programmatic
-    public UserMemento withRoleAdded(String role) {
+    public UserMemento withRoleAdded(final String role) {
         return asBuilder()
         .roles(roles.add(new RoleMemento(role)))
         .build();
@@ -294,6 +300,7 @@ public class UserMemento implements Serializable {
                 .authenticationCode(authenticationCode)
                 .authenticationSource(authenticationSource)
                 .avatarUrl(avatarUrl)
+                .locale(locale)
                 .impersonating(impersonating)
                 .realName(realName)
                 .multiTenancyToken(multiTenancyToken)
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
index e4c91a4..6adc11b 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
@@ -454,7 +454,7 @@ public class WrapperFactoryDefault implements WrapperFactory {
 
         return InteractionContext.builder()
             .clock(Optional.ofNullable(asyncControl.getClock()).orElseGet(interactionContext::getClock))
-            .locale(Optional.ofNullable(asyncControl.getLocale()).orElseGet(interactionContext::getLocale))
+            .locale(Optional.ofNullable(asyncControl.getLocale()).orElse(null)) // if not set in asyncControl use defaults (set override to null)
             .timeZone(Optional.ofNullable(asyncControl.getTimeZone()).orElseGet(interactionContext::getTimeZone))
             .user(Optional.ofNullable(asyncControl.getUser()).orElseGet(interactionContext::getUser))
             .build();
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/usermementorefiner/UserMementoRefinerFromApplicationUser.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/usermementorefiner/UserMementoRefinerFromApplicationUser.java
index f4da58c..1b72721 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/usermementorefiner/UserMementoRefinerFromApplicationUser.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/usermementorefiner/UserMementoRefinerFromApplicationUser.java
@@ -28,19 +28,23 @@ import org.apache.isis.core.security.authentication.manager.UserMementoRefiner;
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
-import lombok.extern.log4j.Log4j2;
 
 @Service
-@Log4j2
+//@Log4j2
 @RequiredArgsConstructor(onConstructor_ = {@Inject})
 public class UserMementoRefinerFromApplicationUser implements UserMementoRefiner {
 
     final Provider<ApplicationUserRepository> applicationUserRepositoryProvider;
 
     @Override
-    public UserMemento refine(UserMemento userMemento) {
+    public UserMemento refine(final UserMemento userMemento) {
         return applicationUserRepositoryProvider.get().findByUsername(userMemento.getName())
-                .map(applicationUser -> userMemento.withMultiTenancyToken(applicationUser.getAtPath()))
+                .map(applicationUser ->
+                    userMemento.asBuilder()
+                    .multiTenancyToken(applicationUser.getAtPath())
+                    .locale(applicationUser.getLocale())
+                    .build()
+                )
                 .orElse(userMemento);
     }
 }