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/03 16:51:55 UTC
[isis] branch master updated: ISIS-2464: overhaul of the SudoService
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 188750c ISIS-2464: overhaul of the SudoService
188750c is described below
commit 188750c922d30e639fad1c137eaf7a204622fab9
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Dec 3 17:51:39 2020 +0100
ISIS-2464: overhaul of the SudoService
also re-integrate properly with the framework (on top of Interaction
handling)
---
.../isis/applib/services/sudo/SudoService.java | 72 ++++++--------------
.../command/CommandExecutorServiceDefault.java | 8 +--
.../runtimeservices/sudo/SudoServiceDefault.java | 79 ++++++++++------------
3 files changed, 59 insertions(+), 100 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 621828b..10337da 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
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.isis.applib.services.sudo;
-import java.util.List;
-import java.util.function.Supplier;
+import java.util.concurrent.Callable;
+import org.apache.isis.applib.services.user.UserMemento;
import org.apache.isis.applib.services.user.UserService;
+import lombok.NonNull;
+
/**
* Intended only for use by fixture scripts and integration tests, allows a block of code to execute
* while the {@link UserService}'s {@link UserService#getUser() getUser()} method returns the specified user/role
@@ -43,69 +44,38 @@ public interface SudoService {
// end::refguide[]
/**
* Executes the supplied block, with the {@link UserService} returning the specified user.
- *
- * <p>
- * The roles of this user will be the same as the currently logged-in user.
- * </p>
+ * @since 2.0
*/
// tag::refguide[]
- void sudo( // <.>
- String username,
- final Runnable runnable);
+ <T> T call( // <.>
+ @NonNull UserMemento user,
+ @NonNull Callable<T> supplier);
// end::refguide[]
/**
* Executes the supplied block, with the {@link UserService} returning the specified user.
- *
- * <p>
- * The roles of this user will be the same as the currently logged-in user.
- * </p>
- */
- // tag::refguide[]
- <T> T sudo( // <.>
- String username,
- final Supplier<T> supplier);
-
- // end::refguide[]
- /**
- * Executes the supplied block, with the {@link UserService} returning the specified user with the specified roles.
- */
- // tag::refguide[]
- void sudo( // <.>
- String username, List<String> roles,
- final Runnable runnable);
-
- // end::refguide[]
- /**
- * Executes the supplied block, with the {@link UserService} returning the specified user with the specified roles.
+ * @since 2.0
*/
// tag::refguide[]
- <T> T sudo( // <.>
- String username, List<String> roles,
- final Supplier<T> supplier);
+ default void run( // <.>
+ final @NonNull UserMemento user,
+ final @NonNull Runnable runnable) {
+ call(user, ()->{runnable.run(); return null;});
+ }
// end::refguide[]
-
- // tag::refguide-1[]
+
+
/**
* Allows the {@link SudoService} to notify other services/components that the effective user has been changed.
+ * @since 2.0
*/
- interface Spi {
+ // tag::refguide-1[]
+ interface Listener {
- // end::refguide-1[]
- /**
- * Any implementation of the {@link SudoService} should call this method on all implementations of the
- * {@link Spi} service whenever {@link SudoService#sudo(String, List, Supplier)} (or its overloads)
- * is called.
- *
- * <p>
- * Modelled after Shiro security's <a href="https://shiro.apache.org/static/1.2.6/apidocs/org/apache/shiro/subject/Subject.html#runAs-org.apache.shiro.subject.PrincipalCollection-">runAs</a> support.
- * </p>
- */
- // tag::refguide-1[]
- void runAs(String username, List<String> roles); // <.>
+ void beforeCall(@NonNull UserMemento user); // <.>
- void releaseRunAs(); // <.>
+ void afterCall(); // <.>
}
// 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 7ff753b..e298f39 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
@@ -44,6 +44,7 @@ import org.apache.isis.applib.services.command.CommandOutcomeHandler;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.iactn.InteractionContext;
import org.apache.isis.applib.services.sudo.SudoService;
+import org.apache.isis.applib.services.user.UserMemento;
import org.apache.isis.applib.services.xactn.TransactionService;
import org.apache.isis.applib.util.schema.CommandDtoUtils;
import org.apache.isis.applib.util.schema.CommonDtoUtils;
@@ -149,8 +150,8 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
try {
val result = transactionService.executeWithinTransaction(
() -> sudoPolicy == SudoPolicy.SWITCH
- ? sudoService.sudo(
- dto.getUser(),
+ ? sudoService.call(
+ UserMemento.ofName(dto.getUser()),
() -> doExecuteCommand(dto))
: doExecuteCommand(dto));
@@ -211,8 +212,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
} else {
head = InteractionHead.simple(targetAdapter);
}
- val resultAdapter = objectAction.execute(head
- , argAdapters, InteractionInitiatedBy.FRAMEWORK);
+ val resultAdapter = objectAction.execute(head, argAdapters, InteractionInitiatedBy.FRAMEWORK);
// flush any Isis PersistenceCommands pending
// (else might get transient objects for the return value)
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 930d16c..c26b4a0 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
@@ -19,8 +19,7 @@
package org.apache.isis.core.runtimeservices.sudo;
-import java.util.List;
-import java.util.function.Supplier;
+import java.util.concurrent.Callable;
import javax.inject.Inject;
import javax.inject.Named;
@@ -31,73 +30,63 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.apache.isis.applib.annotation.OrderPrecedence;
+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.IsisInteractionFactory;
+import org.apache.isis.core.security.authentication.standard.SimpleSession;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+import jakarta.annotation.PostConstruct;
@Service
@Named("isisRuntimeServices.SudoServiceDefault")
@Order(OrderPrecedence.MIDPOINT)
@Primary
@Qualifier("Default")
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
public class SudoServiceDefault implements SudoService {
- @Inject private List<SudoService.Spi> spiServices;
-
- @Override
- public void sudo(final String username, final Runnable runnable) {
- try {
- runAs(username, null);
- runnable.run();
- } finally {
- releaseRunAs();
- }
- }
+ private final IsisInteractionFactory interactionFactory;
- @Override
- public <T> T sudo(final String username, final Supplier<T> supplier) {
- try {
- runAs(username, null);
- return supplier.get();
- } finally {
- releaseRunAs();
- }
- }
+ private Can<SudoService.Listener> sudoListeners = Can.empty();
@Override
- public void sudo(final String username, final List<String> roles, final Runnable runnable) {
+ public <T> T call(final @NonNull UserMemento user, final @NonNull Callable<T> callable) {
+
try {
- runAs(username, roles);
- runnable.run();
+ beforeCall(user);
+ return interactionFactory.callAuthenticated(SimpleSession.validOf(user), callable);
} finally {
- releaseRunAs();
+ afterCall();
}
}
- @Override
- public <T> T sudo(final String username, final List<String> roles, final Supplier<T> supplier) {
- try {
- runAs(username, roles);
- return supplier.get();
- } finally {
- releaseRunAs();
- }
+ @PostConstruct @Inject
+ public void init(final ServiceRegistry serviceRegistry) {
+ this.sudoListeners = serviceRegistry.select(SudoService.Listener.class);
}
- private void runAs(final String username, final List<String> roles) {
- if(spiServices != null) {
- for (SudoService.Spi spiService : spiServices) {
- spiService.runAs(username, roles);
- }
+ // -- HELPER
+
+ private void beforeCall(final @NonNull UserMemento user) {
+ for (val sudoListener : sudoListeners) {
+ sudoListener.beforeCall(user);
}
}
- private void releaseRunAs() {
- if(spiServices != null) {
- for (SudoService.Spi spiService : spiServices) {
- spiService.releaseRunAs();
- }
+ private void afterCall() {
+ for (val sudoListener : sudoListeners) {
+ sudoListener.afterCall();
}
}
-
+
+
+
}