You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/08/05 22:55:50 UTC

[isis] 05/05: ISIS-2728: extends the ImpersonateMenuAdvisor SPI to also advise on the multiTokenTenancy

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

danhaywood pushed a commit to branch ISIS-2728
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 4d23cc85002025958d40676793c3df66070f998c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Aug 5 23:46:53 2021 +0100

    ISIS-2728: extends the ImpersonateMenuAdvisor SPI to also advise on the multiTokenTenancy
    
    (cherry picked from commit 53cb34831d0b1d6088a591cfbe052f311504ea71)
---
 .../isis/applib/services/user/ImpersonateMenu.java | 20 +++++++++-------
 .../services/user/ImpersonateMenuAdvisor.java      | 19 +++++++++++----
 .../isis/applib/services/user/UserService.java     | 27 ++++++++++++----------
 .../user/ImpersonateMenuAdvisorDefault.java        | 10 +++++---
 .../dom/ApplicationPermissionRepository.java       |  2 +-
 .../IsisModuleExtSecmanIntegration.java            |  3 +++
 .../spiimpl/ImpersonateMenuAdvisorForSecman.java   | 13 ++++++++++-
 .../applib/mixins/Object_impersonateWithRoles.java | 17 ++++++++------
 8 files changed, 75 insertions(+), 36 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
index f6fc227..fbf6d27 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
@@ -81,7 +81,7 @@ public class ImpersonateMenu {
             final String userName) {
 
         // TODO: should use an SPI for each configured viewer to add in its own role if necessary.
-        this.userService.impersonateUser(userName, Collections.singletonList("org.apache.isis.viewer.wicket.roles.USER"));
+        this.userService.impersonateUser(userName, Collections.singletonList("org.apache.isis.viewer.wicket.roles.USER"), null);
         this.messageService.informUser("Now impersonating " + userName);
     }
     @MemberSupport public boolean hideImpersonate() {
@@ -106,9 +106,9 @@ public class ImpersonateMenu {
      * an {@link ImpersonateMenuAdvisor} implementation to provide the
      * choices.
      * </p>
-     *
-     * @param userName
+     *  @param userName
      * @param roleNames
+     * @param multiTenancyToken
      */
     @Action(
             domainEvent = ImpersonateWithRolesDomainEvent.class,
@@ -120,14 +120,15 @@ public class ImpersonateMenu {
     @ActionLayout(sequence = "100.2", cssClassFa = "fa-mask")
     public void impersonateWithRoles(
             final String userName,
-            final List<String> roleNames) {
+            final List<String> roleNames,
+            final String multiTenancyToken) {
 
         // TODO: should use an SPI for each configured viewer to add in its own role if necessary.
-        val roleNames2 = new ArrayList<>(roleNames);
-        if(!roleNames2.contains("org.apache.isis.viewer.wicket.roles.USER")) {
-            roleNames2.add("org.apache.isis.viewer.wicket.roles.USER");
+        val roleNamesCopy = new ArrayList<>(roleNames);
+        if(!roleNamesCopy.contains("org.apache.isis.viewer.wicket.roles.USER")) {
+            roleNamesCopy.add("org.apache.isis.viewer.wicket.roles.USER");
         }
-        this.userService.impersonateUser(userName, roleNames2);
+        this.userService.impersonateUser(userName, roleNamesCopy, multiTenancyToken);
         this.messageService.informUser("Now impersonating " + userName);
     }
     @MemberSupport public boolean hideImpersonateWithRoles() {
@@ -145,6 +146,9 @@ public class ImpersonateMenu {
     @MemberSupport public List<String> default1ImpersonateWithRoles(final String userName) {
         return impersonateMenuAdvisor().roleNamesFor(userName);
     }
+    @MemberSupport public String default2ImpersonateWithRoles(final String userName, final List<String> roleNames) {
+        return impersonateMenuAdvisor().multiTenancyTokenFor(userName);
+    }
 
     private ImpersonateMenuAdvisor impersonateMenuAdvisor() {
         // this is safe because there will always be at least one implementation.
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenuAdvisor.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenuAdvisor.java
index f5c1351..8922044 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenuAdvisor.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenuAdvisor.java
@@ -3,7 +3,7 @@ package org.apache.isis.applib.services.user;
 import java.util.List;
 
 /**
- * Enables {@link ImpersonateMenu#impersonateWithRoles(String, List)}, to provides choices for user and roles.
+ * Enables {@link ImpersonateMenu#impersonateWithRoles(String, List, String)}, to provides choices for user and roles.
  *
  * <p>
  *     This will result in the simpler {@link ImpersonateMenu#impersonate(String)} (which simply allows a
@@ -20,7 +20,7 @@ public interface ImpersonateMenuAdvisor {
      * <p>
      *     The {@link ImpersonateMenu} uses this to provide a choices
      *     (drop-down) for the username (string) argument of
-     *     {@link ImpersonateMenu#impersonateWithRoles(String, List)}.
+     *     {@link ImpersonateMenu#impersonateWithRoles(String, List, String)}.
      * </p>
      */
     List<String> allUserNames();
@@ -31,7 +31,7 @@ public interface ImpersonateMenuAdvisor {
      * <p>
      *     The {@link ImpersonateMenu} uses this to provide a choices
      *     (drop-down) for the rolenames (list) argument of
-     *     {@link ImpersonateMenu#impersonateWithRoles(String, List)}.
+     *     {@link ImpersonateMenu#impersonateWithRoles(String, List, String)}.
      * </p>
      */
     List<String> allRoleNames();
@@ -42,9 +42,20 @@ public interface ImpersonateMenuAdvisor {
      * <p>
      *     The {@link ImpersonateMenu} uses this to select the defaults
      *     for the rolenames (list) argument of
-     *     {@link ImpersonateMenu#impersonateWithRoles(String, List)}.
+     *     {@link ImpersonateMenu#impersonateWithRoles(String, List, String)}.
      * </p>
      */
     List<String> roleNamesFor(final String username);
 
+    /**
+     * Returns the multi-tenancy token of the specified username.
+     *
+     * <p>
+     *     The {@link ImpersonateMenu} uses this to select the defaults
+     *     for the rolenames (list) argument of
+     *     {@link ImpersonateMenu#impersonateWithRoles(String, List, String)}.
+     * </p>
+     */
+    String multiTenancyTokenFor(final String username);
+
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserService.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserService.java
index e031623..f5437b9 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserService.java
@@ -83,7 +83,7 @@ public class UserService {
 
     /**
      * Returns the details about the current user, either the &quot;effective&quot; user (if being
-     * {@link #impersonateUser(String, List) impersonated}) otherwise the &quot;real&quot; user (as obtained from
+     * {@link #impersonateUser(String, List, String) impersonated}) otherwise the &quot;real&quot; user (as obtained from
      * the {@link InteractionContext} of the current thread).
      */
     public Optional<UserMemento> currentUser() {
@@ -138,7 +138,7 @@ public class UserService {
      *
      * @see #currentUser()
      * @see #supportsImpersonation()
-     * @see #impersonateUser(String, List)
+     * @see #impersonateUser(String, List, String)
      * @see #stopImpersonating()
      */
     public boolean isImpersonating() {
@@ -157,7 +157,7 @@ public class UserService {
      *     This means that the result of this call varies on a request-by-request basis.
      * </p>
      *
-     * @see #impersonateUser(String, List)
+     * @see #impersonateUser(String, List, String)
      * @see #isImpersonating()
      * @see #stopImpersonating()
      *
@@ -199,17 +199,20 @@ public class UserService {
      * @see #supportsImpersonation()
      * @see #isImpersonating()
      * @see #stopImpersonating()
-     *
      * @param userName - the name of the user to be impersonated
      * @param roles - the collection of roles for the impersonated user to have.
+     * @param multiTenancyToken
      */
-    public void impersonateUser(final String userName, final List<String> roles) {
+    public void impersonateUser(
+            final String userName,
+            final List<String> roles,
+            final String multiTenancyToken) {
         impersonatingHolder().ifPresent(x ->
-                {
-                    val userMemento = UserMemento.ofNameAndRoleNames(userName, roles)
-                            .withImpersonating(true);
-                    x.setUserMemento(userMemento);
-                }
+                x.setUserMemento(
+                    UserMemento.ofNameAndRoleNames(userName, roles)
+                        .withImpersonating(true)
+                        .withMultiTenancyToken(multiTenancyToken)
+                )
         );
     }
 
@@ -225,11 +228,11 @@ public class UserService {
      *
      * <p>
      *     Intended to be called at some point after
-     *     {@link #impersonateUser(String, List)} would have been called.
+     *     {@link #impersonateUser(String, List, String)} would have been called.
      * </p>
      *
      * @see #supportsImpersonation()
-     * @see #impersonateUser(String, List)
+     * @see #impersonateUser(String, List, String)
      * @see #isImpersonating()
      */
     public void stopImpersonating() {
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/ImpersonateMenuAdvisorDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/ImpersonateMenuAdvisorDefault.java
index e83e021..11ef312 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/ImpersonateMenuAdvisorDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/ImpersonateMenuAdvisorDefault.java
@@ -17,7 +17,7 @@ import org.apache.isis.applib.services.user.ImpersonateMenuAdvisor;
  * <p>
  *  This has the effect that the
  *  {@link org.apache.isis.applib.services.user.ImpersonateMenu}'s
- *  {@link org.apache.isis.applib.services.user.ImpersonateMenu#impersonateWithRoles(String, List) impersonateWithRoles}
+ *  {@link org.apache.isis.applib.services.user.ImpersonateMenu#impersonateWithRoles(String, List, String) impersonateWithRoles}
  *  action will be hidden.
  * </p>
  */
@@ -38,9 +38,13 @@ public class ImpersonateMenuAdvisorDefault implements ImpersonateMenuAdvisor {
     }
 
     @Override
-    public List<String> roleNamesFor(
-            final String username) {
+    public List<String> roleNamesFor(final String username) {
         return Collections.emptyList();
     }
 
+    @Override
+    public String multiTenancyTokenFor(String username) {
+        return null;
+    }
+
 }
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/dom/ApplicationPermissionRepository.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/dom/ApplicationPermissionRepository.java
index 1ddfdd9..5ef5383 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/dom/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/dom/ApplicationPermissionRepository.java
@@ -98,7 +98,7 @@ public interface ApplicationPermissionRepository {
      * Uses the {@link UserMemento#getRoles() roles} held within the provided {@link UserMemento}.
      *
      * <p>
-     * Added to support {@link org.apache.isis.applib.services.user.ImpersonateMenu#impersonateWithRoles(String, List) impersonation by role}.
+     * Added to support {@link org.apache.isis.applib.services.user.ImpersonateMenu#impersonateWithRoles(String, List, String) impersonation by role}.
      * </p>
      *
      * @see #findByRoleNames(List)
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
index 23eb2a8..ff1c766 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
@@ -26,6 +26,7 @@ import org.apache.isis.extensions.secman.integration.authorizor.AuthorizorSecman
 import org.apache.isis.extensions.secman.integration.facets.TenantedAuthorizationPostProcessor;
 import org.apache.isis.extensions.secman.integration.spiimpl.ImpersonateMenuAdvisorForSecman;
 import org.apache.isis.extensions.secman.integration.spiimpl.TableColumnVisibilityServiceForSecman;
+import org.apache.isis.extensions.secman.integration.usermementorefiner.UserMementoRefinerFromApplicationUser;
 import org.apache.isis.extensions.secman.integration.userreg.UserRegistrationServiceForSecman;
 
 /**
@@ -43,6 +44,8 @@ import org.apache.isis.extensions.secman.integration.userreg.UserRegistrationSer
         ImpersonateMenuAdvisorForSecman.class, //not activated by default yet
         UserRegistrationServiceForSecman.class,
 
+        UserMementoRefinerFromApplicationUser.class,
+
 })
 public class IsisModuleExtSecmanIntegration {
 
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/spiimpl/ImpersonateMenuAdvisorForSecman.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/spiimpl/ImpersonateMenuAdvisorForSecman.java
index 8e293f2..142a19f 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/spiimpl/ImpersonateMenuAdvisorForSecman.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/spiimpl/ImpersonateMenuAdvisorForSecman.java
@@ -7,10 +7,10 @@ import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.inject.Named;
 
-import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.applib.services.user.ImpersonateMenuAdvisor;
 import org.apache.isis.applib.services.user.UserService;
@@ -68,4 +68,15 @@ public class ImpersonateMenuAdvisorForSecman implements ImpersonateMenuAdvisor {
                 .collect(Collectors.toList());
     }
 
+    @Override
+    public String multiTenancyTokenFor(String username) {
+        if(username == null) {
+            return null;
+        }
+        val applicationUser =
+                applicationUserRepository.findByUsername(username)
+                        .orElseThrow(RuntimeException::new);
+        return applicationUser.getAtPath();
+    }
+
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/applib/mixins/Object_impersonateWithRoles.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/applib/mixins/Object_impersonateWithRoles.java
index f326abf..2bc0da9 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/applib/mixins/Object_impersonateWithRoles.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/applib/mixins/Object_impersonateWithRoles.java
@@ -37,7 +37,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 /**
- * Same as {@link ImpersonateMenu#impersonateWithRoles(String, List)},
+ * Same as {@link ImpersonateMenu#impersonateWithRoles(String, List, String)},
  * but implemented as a mixin so that can be invoked while accessing an object.
  *
  * @since 2.0 {@index}
@@ -67,8 +67,9 @@ public class Object_impersonateWithRoles {
 
     public Object act(
             final String userName,
-            final List<String> roleNames) {
-        impersonateMenu.impersonateWithRoles(userName, roleNames);
+            final List<String> roleNames,
+            final String multiTenancyToken) {
+        impersonateMenu.impersonateWithRoles(userName, roleNames, multiTenancyToken);
         return holder;
     }
 
@@ -94,16 +95,18 @@ public class Object_impersonateWithRoles {
         return null;
     }
 
-    @MemberSupport public List<String> choices1Act(
-            final String userName) {
+    @MemberSupport public List<String> choices1Act(final String userName) {
         return impersonateMenu.choices1ImpersonateWithRoles(userName);
     }
 
-    @MemberSupport public List<String> default1Act(
-            final String userName) {
+    @MemberSupport public List<String> default1Act(final String userName) {
         return impersonateMenu.default1ImpersonateWithRoles(userName);
     }
 
+    @MemberSupport public String default2Act(final String userName, final List<String> roleNames) {
+        return impersonateMenu.default2ImpersonateWithRoles(userName, roleNames);
+    }
+
     @Inject ImpersonateMenu impersonateMenu;
 
 }