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 2020/12/04 22:21:26 UTC

[isis] branch master updated: ISIS-2464: SudoService overhaul

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 5b7ba8b  ISIS-2464: SudoService overhaul
5b7ba8b is described below

commit 5b7ba8b34b71faa91522ee31ce047a2cbcff0922
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 4 23:21:08 2020 +0100

    ISIS-2464: SudoService overhaul
    
    allows full control of the ExecutionContext to use for sudo, based on
    the current ExecutionContext that sits on top of the current thread's
    stack; we use the wither idiom here to create copies of
    ExecutionContexts
---
 .../isis/applib/services/sudo/SudoService.java     | 16 ++++++-----
 .../command/CommandExecutorServiceDefault.java     |  4 +--
 .../runtimeservices/sudo/SudoServiceDefault.java   | 31 +++++++++++++---------
 3 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/sudo/SudoService.java b/api/applib/src/main/java/org/apache/isis/applib/services/sudo/SudoService.java
index 72518eb..edff67b 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/sudo/SudoService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/sudo/SudoService.java
@@ -19,9 +19,10 @@
 package org.apache.isis.applib.services.sudo;
 
 import java.util.concurrent.Callable;
+import java.util.function.UnaryOperator;
 
+import org.apache.isis.applib.services.iactn.ExecutionContext;
 import org.apache.isis.applib.services.user.RoleMemento;
-import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.applib.services.user.UserService;
 
 import lombok.NonNull;
@@ -48,23 +49,25 @@ public interface SudoService {
     // end::refguide[]
     /**
      * Executes the supplied block, with the {@link UserService} returning the specified user.
+     * @param sudoMapper - maps the current {@link ExecutionContext} to the sudo one
      * @since 2.0
      */
     // tag::refguide[]
     <T> T call(                                             // <.>
-            @NonNull UserMemento user,
+            @NonNull UnaryOperator<ExecutionContext> sudoMapper,
             @NonNull Callable<T> supplier);
 
     // end::refguide[]
     /**
      * Executes the supplied block, with the {@link UserService} returning the specified user.
+     * @param sudoMapper - maps the current {@link ExecutionContext} to the sudo one
      * @since 2.0
      */
     // tag::refguide[]
     default void run(                                        // <.>
-            final @NonNull UserMemento user,
+            final @NonNull UnaryOperator<ExecutionContext> sudoMapper,
             final @NonNull Runnable runnable) {
-        call(user, ()->{runnable.run(); return null;});
+        call(sudoMapper, ()->{runnable.run(); return null;});
     }
 
     // end::refguide[]
@@ -73,14 +76,13 @@ public interface SudoService {
     /**
      * Allows the {@link SudoService} to notify other services/components that the effective user has been changed.
      * @since 2.0
-     * @deprecated its better to subscribe to interaction life-cycle events on the event bus 
      */
     // tag::refguide-1[]
     interface Listener {
 
-        void beforeCall(@NonNull UserMemento user);          // <.>
+        void beforeCall(@NonNull ExecutionContext before, @NonNull ExecutionContext after);          // <.>
 
-        void afterCall();                                    // <.>
+        void afterCall(@NonNull ExecutionContext before, @NonNull ExecutionContext after);          // <.>
     }
     // end::refguide-1[]
 
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
index 25598e2..2f441af 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
@@ -151,8 +151,8 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
             val result = transactionService.executeWithinTransaction(
                 () -> sudoPolicy == SudoPolicy.SWITCH
                     ? sudoService.call(
-                        UserMemento.ofName(dto.getUser()),
-                        () -> doExecuteCommand(dto))
+                            context->context.withUser(UserMemento.ofName(dto.getUser())),
+                            () -> doExecuteCommand(dto))
                     : doExecuteCommand(dto));
 
             return handleOutcomeAndSetCompletedAt(commandUpdater, result, null);
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sudo/SudoServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sudo/SudoServiceDefault.java
index 759e986..fe41e68 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sudo/SudoServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sudo/SudoServiceDefault.java
@@ -20,6 +20,7 @@
 package org.apache.isis.core.runtimeservices.sudo;
 
 import java.util.concurrent.Callable;
+import java.util.function.UnaryOperator;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -30,9 +31,9 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.applib.services.iactn.ExecutionContext;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.applib.services.sudo.SudoService;
-import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.runtime.iactn.InteractionFactory;
 import org.apache.isis.core.runtime.iactn.InteractionTracker;
@@ -66,36 +67,42 @@ public class SudoServiceDefault implements SudoService {
     // -- IMPLEMENTATION
     
     @Override
-    public <T> T call(final @NonNull UserMemento sudoUser, final @NonNull Callable<T> callable) {
+    public <T> T call(
+            final @NonNull UnaryOperator<ExecutionContext> sudoMapper, 
+            final @NonNull Callable<T> callable) {
 
-        val currentinteractionLayer = interactionTracker.currentInteractionLayerElseFail();
-        val currentExecutionContext = currentinteractionLayer.getExecutionContext();
-        val sudoExecutionContext = currentExecutionContext.withUser(sudoUser);
+        val currentInteractionLayer = interactionTracker.currentInteractionLayerElseFail();
+        val currentExecutionContext = currentInteractionLayer.getExecutionContext();
+        val sudoExecutionContext = sudoMapper.apply(currentExecutionContext);
         
-        val sodoSession = currentinteractionLayer
+        val sodoSession = currentInteractionLayer
                 .getAuthenticationSession()
                 .withExecutionContext(sudoExecutionContext);
         
         try {
-            beforeCall(sudoUser);
+            beforeCall(currentExecutionContext, sudoExecutionContext);
             
             return interactionFactory.callAuthenticated(sodoSession, callable);
         } finally {
-            afterCall();
+            afterCall(sudoExecutionContext, currentExecutionContext);
         }
     }
 
     // -- HELPER
 
-    private void beforeCall(final @NonNull UserMemento sudoUser) {
+    private void beforeCall(
+            final @NonNull ExecutionContext before, 
+            final @NonNull ExecutionContext after) {
         for (val sudoListener : sudoListeners) {
-            sudoListener.beforeCall(sudoUser);
+            sudoListener.beforeCall(before, after);
         }
     }
 
-    private void afterCall() {
+    private void afterCall(
+            final @NonNull ExecutionContext before, 
+            final @NonNull ExecutionContext after) {
         for (val sudoListener : sudoListeners) {
-            sudoListener.afterCall();
+            sudoListener.afterCall(before, after);
         }
     }