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 2022/08/04 08:54:48 UTC
[isis] branch master updated: ISIS-3109: properly amend authentication with zone-it post sign-in
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 1275167f00 ISIS-3109: properly amend authentication with zone-it post sign-in
1275167f00 is described below
commit 1275167f00db4fd1b6f69167df5380963abd3e31
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 4 10:54:42 2022 +0200
ISIS-3109: properly amend authentication with zone-it post sign-in
---
.../user/UserCurrentSessionTimeZoneHolder.java | 5 +++
.../internal/debug/xray/_CallStackMerger.java | 2 -
.../core/interaction/session/IsisInteraction.java | 13 +++---
.../session/InteractionServiceDefault.java | 2 +-
.../UserCurrentSessionTimeZoneHolderDefault.java | 7 +++-
.../AuthenticationRequestAbstract.java | 7 ++--
.../manager/AuthenticationManager.java | 13 +++++-
.../isis/security/AuthenticatorsForTesting.java | 10 ++---
.../AuthenticationManager_authenticators_Test.java | 3 ++
...rdAuthenticationManager_AuthenticationTest.java | 2 +
.../authenticator/AuthenticatorSecman.java | 2 -
.../AuthenticatorSecmanAutoConfiguration.java | 3 +-
.../shiro/authentication/AuthenticatorShiro.java | 13 +++---
.../spring/webmodule/SpringSecurityFilter.java | 5 ++-
.../model/isis/HasAmendableInteractionContext.java | 36 ++++++-----------
.../wicket/ui/pages/login/IsisSignInPanel.java | 47 ++++++++++++++++------
.../wicket/ui/pages/login/SignInPanelAbstract.java | 21 +++++++++-
.../AuthenticatedWebSessionForIsis.java | 28 ++++++++-----
...uthenticatedWebSessionForIsis_Authenticate.java | 1 +
.../AuthenticatedWebSessionForIsis_SignIn.java | 2 +
20 files changed, 146 insertions(+), 76 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java
index a52215246a..36463ed982 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java
@@ -49,5 +49,10 @@ public interface UserCurrentSessionTimeZoneHolder {
*/
Optional<ZoneId> getUserTimeZone();
+ /**
+ * Clears the user's current {@link ZoneId}
+ * within the context of the current session.
+ */
+ void clearUserTimeZone();
}
\ No newline at end of file
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/debug/xray/_CallStackMerger.java b/commons/src/main/java/org/apache/isis/commons/internal/debug/xray/_CallStackMerger.java
index 7a0fbc3840..22b5b3b39d 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/debug/xray/_CallStackMerger.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/debug/xray/_CallStackMerger.java
@@ -124,8 +124,6 @@ final class _CallStackMerger {
val executionLanes = new ArrayList<int[]>();
logEntries.forEach(logEntry->{
- //System.err.printf("joining %s%n", logEntry.getLabel());
-
val executionLane = new int[logEntry.getData().size()];
executionLanes.add(executionLane);
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/session/IsisInteraction.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/session/IsisInteraction.java
index f4f08190ef..eb14b08222 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/session/IsisInteraction.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/session/IsisInteraction.java
@@ -50,6 +50,7 @@ implements InteractionInternal {
public IsisInteraction(final @NonNull UUID interactionId) {
this.startedAtSystemNanos = System.nanoTime(); // used to measure time periods, so not using ClockService here
this.command = new Command(interactionId);
+ log.debug("new IsisInteraction id={}", interactionId);
}
@Getter(onMethod_ = {@Override})
@@ -108,7 +109,7 @@ implements InteractionInternal {
}
}
- private void pushAndStart(ActionInvocation actionInvocation, ClockService clockService, MetricsService metricsService, Command command) {
+ private void pushAndStart(final ActionInvocation actionInvocation, final ClockService clockService, final MetricsService metricsService, final Command command) {
push(actionInvocation);
start(actionInvocation, clockService, metricsService, command);
}
@@ -130,7 +131,7 @@ implements InteractionInternal {
}
}
- private <T extends Execution<?,?>> Object executeInternal(MemberExecutor<T> memberExecutor, T execution) {
+ private <T extends Execution<?,?>> Object executeInternal(final MemberExecutor<T> memberExecutor, final T execution) {
try {
Object result = memberExecutor.execute(execution);
@@ -236,22 +237,22 @@ implements InteractionInternal {
private final Map<Class<?>, Object> attributes = new HashMap<>();
@Override
- public <T> T putAttribute(Class<? super T> type, T value) {
+ public <T> T putAttribute(final Class<? super T> type, final T value) {
return _Casts.uncheckedCast(attributes.put(type, value));
}
@Override
- public <T> T computeAttributeIfAbsent(Class<? super T> type, Function<Class<?>, ? extends T> mappingFunction) {
+ public <T> T computeAttributeIfAbsent(final Class<? super T> type, final Function<Class<?>, ? extends T> mappingFunction) {
return _Casts.uncheckedCast(attributes.computeIfAbsent(type, mappingFunction));
}
@Override
- public <T> T getAttribute(Class<T> type) {
+ public <T> T getAttribute(final Class<T> type) {
return _Casts.uncheckedCast(attributes.get(type));
}
@Override
- public void removeAttribute(Class<?> type) {
+ public void removeAttribute(final Class<?> type) {
attributes.remove(type);
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionServiceDefault.java
index ec48c4be98..de8ab73e4f 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionServiceDefault.java
@@ -117,7 +117,7 @@ implements
final InteractionAwareTransactionalBoundaryHandler txBoundaryHandler,
final ClockService clockService,
final Provider<CommandPublisher> commandPublisherProvider,
- Provider<TransactionService> transactionServiceProvider,
+ final Provider<TransactionService> transactionServiceProvider,
final ConfigurableBeanFactory beanFactory,
final InteractionIdGenerator interactionIdGenerator) {
this.runtimeEventService = runtimeEventService;
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/UserCurrentSessionTimeZoneHolderDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/UserCurrentSessionTimeZoneHolderDefault.java
index cbe3d1c60b..d1cfae7c90 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/UserCurrentSessionTimeZoneHolderDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/user/UserCurrentSessionTimeZoneHolderDefault.java
@@ -48,7 +48,6 @@ implements UserCurrentSessionTimeZoneHolder {
public void setUserTimeZone(final @NonNull ZoneId zoneId) {
keyValueSessionStore
.ifPresent(store->store.put(SESSION_KEY_ZONE_ID, zoneId));
-
}
@Override
@@ -57,4 +56,10 @@ implements UserCurrentSessionTimeZoneHolder {
.flatMap(store->store.lookupAs(SESSION_KEY_ZONE_ID, ZoneId.class));
}
+ @Override
+ public void clearUserTimeZone() {
+ keyValueSessionStore
+ .ifPresent(store->store.clear(SESSION_KEY_ZONE_ID));
+ }
+
}
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
index 5734413a1b..3df2579801 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
@@ -29,7 +29,8 @@ import org.apache.isis.commons.internal.collections._Sets;
import static org.apache.isis.commons.internal.base._NullSafe.stream;
-public abstract class AuthenticationRequestAbstract implements AuthenticationRequest {
+public abstract class AuthenticationRequestAbstract
+implements AuthenticationRequest {
private final String name;
private final Set<String> roles = _Sets.newHashSet();
@@ -60,14 +61,14 @@ public abstract class AuthenticationRequestAbstract implements AuthenticationReq
* @param role
* @since 2.0
*/
- public void addRole(String role) {
+ public void addRole(final String role) {
if(_Strings.isNullOrEmpty(role)) {
return; // ignore
}
this.roles.add(role);
}
- public void addRoles(@Nullable Collection<String> roles) {
+ public void addRoles(final @Nullable Collection<String> roles) {
stream(roles)
.forEach(this::addRole);
}
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
index 69a1aa4343..be6ca8554e 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.security.authentication.manager;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.Priority;
import javax.inject.Inject;
@@ -34,6 +35,7 @@ import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.exceptions.unrecoverable.NoAuthenticatorException;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.user.UserCurrentSessionTimeZoneHolder;
import org.apache.isis.applib.util.ToString;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Timing;
@@ -60,16 +62,19 @@ public class AuthenticationManager {
private final @NonNull RandomCodeGenerator randomCodeGenerator;
private final @NonNull Can<Registrar> registrars;
private final @NonNull List<UserMementoRefiner> userMementoRefiners;
+ private final @NonNull Optional<UserCurrentSessionTimeZoneHolder> userCurrentSessionTimeZoneHolder;
@Inject
public AuthenticationManager(
final List<Authenticator> authenticators,
final InteractionService interactionService,
final RandomCodeGenerator randomCodeGenerator,
+ final Optional<UserCurrentSessionTimeZoneHolder> userCurrentSessionTimeZoneHolder,
final List<UserMementoRefiner> userMementoRefiners) {
this.interactionService = interactionService;
this.randomCodeGenerator = randomCodeGenerator;
this.authenticators = Can.ofCollection(authenticators);
+ this.userCurrentSessionTimeZoneHolder = userCurrentSessionTimeZoneHolder;
this.userMementoRefiners = userMementoRefiners;
if (this.authenticators.isEmpty()) {
throw new NoAuthenticatorException("No authenticators specified");
@@ -105,14 +110,20 @@ public class AuthenticationManager {
val interactionContext = authenticator.authenticate(request, getUnusedRandomCode());
if (interactionContext != null) {
+ val interactionContextWithTimeZone = interactionContext
+ .withTimeZoneIfAny(userCurrentSessionTimeZoneHolder
+ .flatMap(UserCurrentSessionTimeZoneHolder::getUserTimeZone));
+
val userRefined = UserMementoRefiner.refine(
interactionContext.getUser(),
userMementoRefiners);
- val interactionContextRefined = interactionContext.withUser(userRefined);
userByValidationCode.put(
userRefined.getAuthenticationCode(),
userRefined.getName());
+
+ val interactionContextRefined = interactionContextWithTimeZone
+ .withUser(userRefined);
return interactionContextRefined;
}
}
diff --git a/core/security/src/test/java/org/apache/isis/security/AuthenticatorsForTesting.java b/core/security/src/test/java/org/apache/isis/security/AuthenticatorsForTesting.java
index 79be745f89..873f4928c1 100644
--- a/core/security/src/test/java/org/apache/isis/security/AuthenticatorsForTesting.java
+++ b/core/security/src/test/java/org/apache/isis/security/AuthenticatorsForTesting.java
@@ -32,7 +32,7 @@ public class AuthenticatorsForTesting {
public boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
return true;
}
-
+
@Override
public boolean isValid(final AuthenticationRequest request) {
return true;
@@ -46,21 +46,21 @@ public class AuthenticatorsForTesting {
public boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
return true;
}
-
+
@Override
public boolean isValid(final AuthenticationRequest request) {
return false;
}
};
}
-
+
public static AuthenticatorAbstract authenticatorValidForFoo() {
return new AuthenticatorAbstract() {
@Override
public boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
return true;
}
-
+
@Override
public boolean isValid(final AuthenticationRequest request) {
if(!"foo".equals(request.getName())) {
@@ -70,6 +70,6 @@ public class AuthenticatorsForTesting {
}
};
}
-
+
}
diff --git a/core/security/src/test/java/org/apache/isis/security/authentication/standard/AuthenticationManager_authenticators_Test.java b/core/security/src/test/java/org/apache/isis/security/authentication/standard/AuthenticationManager_authenticators_Test.java
index bfac3d48b2..4df586d23c 100644
--- a/core/security/src/test/java/org/apache/isis/security/authentication/standard/AuthenticationManager_authenticators_Test.java
+++ b/core/security/src/test/java/org/apache/isis/security/authentication/standard/AuthenticationManager_authenticators_Test.java
@@ -19,6 +19,7 @@
package org.apache.isis.security.authentication.standard;
import java.util.Collections;
+import java.util.Optional;
import org.junit.Test;
@@ -46,6 +47,7 @@ public class AuthenticationManager_authenticators_Test {
Collections.emptyList(),
new InteractionService_forTesting(),
new RandomCodeGeneratorDefault(),
+ Optional.empty(),
Collections.emptyList());
authenticationManager.authenticate(new AuthenticationRequestPassword("foo", "bar"));
}
@@ -59,6 +61,7 @@ public class AuthenticationManager_authenticators_Test {
Collections.singletonList(auth),
new InteractionService_forTesting(),
new RandomCodeGeneratorDefault(),
+ Optional.empty(),
Collections.emptyList());
assertThat(authenticationManager.getAuthenticators().size(), is(1));
assertThat(authenticationManager.getAuthenticators().getElseFail(0), is(sameInstance(auth)));
diff --git a/core/security/src/test/java/org/apache/isis/security/authentication/standard/StandardAuthenticationManager_AuthenticationTest.java b/core/security/src/test/java/org/apache/isis/security/authentication/standard/StandardAuthenticationManager_AuthenticationTest.java
index fe67917dfd..b643e5260b 100644
--- a/core/security/src/test/java/org/apache/isis/security/authentication/standard/StandardAuthenticationManager_AuthenticationTest.java
+++ b/core/security/src/test/java/org/apache/isis/security/authentication/standard/StandardAuthenticationManager_AuthenticationTest.java
@@ -19,6 +19,7 @@
package org.apache.isis.security.authentication.standard;
import java.util.Collections;
+import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +45,7 @@ public class StandardAuthenticationManager_AuthenticationTest {
Collections.singletonList(AuthenticatorsForTesting.authenticatorValidForFoo()),
new InteractionService_forTesting(),
new RandomCodeGeneratorDefault(),
+ Optional.empty(),
Collections.emptyList());
}
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecman.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecman.java
index a6bcf42c15..b4a83676ca 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecman.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecman.java
@@ -101,6 +101,4 @@ public class AuthenticatorSecman implements Authenticator {
// be re-authenticated.
}
-
-
}
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecmanAutoConfiguration.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecmanAutoConfiguration.java
index 566cf50c86..7d0ce4ae4f 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecmanAutoConfiguration.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/authenticator/AuthenticatorSecmanAutoConfiguration.java
@@ -42,7 +42,8 @@ public class AuthenticatorSecmanAutoConfiguration {
public Authenticator authenticatorSecman(
final ApplicationUserRepository applicationUserRepository,
final @Qualifier("secman") PasswordEncoder passwordEncoder) {
- return new AuthenticatorSecman(applicationUserRepository, passwordEncoder);
+ return new AuthenticatorSecman(
+ applicationUserRepository, passwordEncoder);
}
}
diff --git a/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java b/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
index c1ed8429dd..d03bff1da2 100644
--- a/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
+++ b/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
@@ -81,14 +81,13 @@ public class AuthenticatorShiro implements Authenticator {
private final boolean autoLogout;
@Inject
- public AuthenticatorShiro(IsisConfiguration configuration) {
+ public AuthenticatorShiro(
+ final IsisConfiguration configuration) {
super();
this.configuration = configuration;
this.autoLogout = this.configuration.getSecurity().getShiro().isAutoLogoutIfAlreadyAuthenticated();
}
-
-
@Override
public final boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
if(getSecurityManager() == null) {
@@ -158,10 +157,10 @@ public class AuthenticatorShiro implements Authenticator {
}
InteractionContext authenticationFor(
- AuthenticationRequest request,
- String validationCode,
- AuthenticationToken token,
- Subject currentSubject) {
+ final AuthenticationRequest request,
+ final String validationCode,
+ final AuthenticationToken token,
+ final Subject currentSubject) {
final Stream<String> roles = Stream.concat(
streamRoles(currentSubject, token),
diff --git a/security/spring/src/main/java/org/apache/isis/security/spring/webmodule/SpringSecurityFilter.java b/security/spring/src/main/java/org/apache/isis/security/spring/webmodule/SpringSecurityFilter.java
index c958e4d45f..1be499c002 100644
--- a/security/spring/src/main/java/org/apache/isis/security/spring/webmodule/SpringSecurityFilter.java
+++ b/security/spring/src/main/java/org/apache/isis/security/spring/webmodule/SpringSecurityFilter.java
@@ -34,6 +34,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.user.UserCurrentSessionTimeZoneHolder;
import org.apache.isis.applib.services.user.UserMemento;
import org.apache.isis.applib.services.user.UserMemento.AuthenticationSource;
import org.apache.isis.security.spring.authconverters.AuthenticationConverter;
@@ -48,6 +49,7 @@ public class SpringSecurityFilter implements Filter {
@Autowired private InteractionService interactionService;
@Inject List<AuthenticationConverter> converters;
+ @Inject private UserCurrentSessionTimeZoneHolder userCurrentSessionTimeZoneHolder;
@Override
public void doFilter(
@@ -85,7 +87,8 @@ public class SpringSecurityFilter implements Filter {
.withAuthenticationSource(AuthenticationSource.EXTERNAL);
interactionService.run(
- InteractionContext.ofUserWithSystemDefaults(userMemento),
+ InteractionContext.ofUserWithSystemDefaults(userMemento)
+ .withTimeZoneIfAny(userCurrentSessionTimeZoneHolder.getUserTimeZone()),
()->filterChain.doFilter(servletRequest, servletResponse));
}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/HasAmendableInteractionContext.java
similarity index 52%
copy from api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java
copy to viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/HasAmendableInteractionContext.java
index a52215246a..d814175b90 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserCurrentSessionTimeZoneHolder.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/HasAmendableInteractionContext.java
@@ -16,38 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.applib.services.user;
+package org.apache.isis.viewer.wicket.model.isis;
-import java.time.ZoneId;
-import java.util.Optional;
+import java.util.function.UnaryOperator;
+
+import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import lombok.NonNull;
/**
- * Stores the user's current {@link ZoneId} with session scope.
- * <p>
- * eg. on application login
+ * Introduced, to allow for authenticated sessions to be amended with time-zone information
+ * (post sign-in).
*
- * @since 2.0 {@index}
+ * @since 2.0
*/
-public interface UserCurrentSessionTimeZoneHolder {
+public interface HasAmendableInteractionContext {
/**
- * Sets the user's current {@link ZoneId}
- * within the context of the current session.
- */
- void setUserTimeZone(@NonNull ZoneId zoneId);
-
- /**
- * Optionally returns the user's current {@link ZoneId},
- * based on whether it was set before,
- * within the context of the current session.
+ * Replaces the held {@link InteractionContext} with an amended version.
*
- * @apiNote not meant to fallback to system defaults,
- * instead return {@link Optional#empty()},
- * if there is no specific time-zone information available
+ * @param updater - operator must allow <code>null</code> argument
+ * and is allowed to return <code>null</code> (required)
*/
- Optional<ZoneId> getUserTimeZone();
-
+ void amendInteractionContext(@NonNull UnaryOperator<InteractionContext> updater);
-}
\ No newline at end of file
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/IsisSignInPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/IsisSignInPanel.java
index 6c19a27077..6c341c699a 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/IsisSignInPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/IsisSignInPanel.java
@@ -18,12 +18,14 @@
*/
package org.apache.isis.viewer.wicket.ui.pages.login;
+import java.time.ZoneId;
import java.util.Optional;
import javax.inject.Inject;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
@@ -33,9 +35,12 @@ import org.apache.isis.applib.services.user.UserCurrentSessionTimeZoneHolder;
import org.apache.isis.applib.services.userreg.EmailNotificationService;
import org.apache.isis.applib.services.userreg.UserRegistrationService;
import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.assertions._Assert;
+import org.apache.isis.viewer.wicket.model.isis.HasAmendableInteractionContext;
import org.apache.isis.viewer.wicket.model.models.PageType;
import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
+import lombok.NonNull;
import lombok.val;
import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel;
@@ -61,7 +66,7 @@ public class IsisSignInPanel extends SignInPanelAbstract {
private final boolean signUpLink;
private final boolean passwordResetLink;
- private final boolean clearOriginalDestination;
+ private final boolean isClearOriginalDestination;
/**
* Constructor
@@ -83,7 +88,7 @@ public class IsisSignInPanel extends SignInPanelAbstract {
super(id, rememberMe);
this.signUpLink = signUpLink;
this.passwordResetLink = passwordResetLink;
- this.clearOriginalDestination = !continueToOriginalDestination;
+ this.isClearOriginalDestination = !continueToOriginalDestination;
}
@Override
@@ -105,16 +110,42 @@ public class IsisSignInPanel extends SignInPanelAbstract {
@Override
protected void onSignInSucceeded() {
- signInHook();
+ if(isClearOriginalDestination) {
+ clearOriginalDestination();
+ }
super.onSignInSucceeded();
}
@Override
protected void onSignInRemembered() {
- signInHook();
+ if(isClearOriginalDestination) {
+ clearOriginalDestination();
+ }
super.onSignInRemembered();
}
+ @Override
+ protected void storeUserTimeZoneToSession(final @NonNull ZoneId zoneId) {
+ userCurrentSessionTimeZoneHolder.setUserTimeZone(zoneId);
+ // fail early if not wired up correctly: there must be a session available for storage
+ _Assert.assertEquals(zoneId, userCurrentSessionTimeZoneHolder.getUserTimeZone().orElse(null),
+ ()->"no session available to store time-zone data");
+
+ // amend authentication/context with time-zone,
+ // also propagate user's Locale from current InteractionContext to Wicket's session
+ val session = AuthenticatedWebSession.get();
+ ((HasAmendableInteractionContext)session).amendInteractionContext(interactionContext->{
+ Optional.ofNullable(interactionContext.getUser().getLanguageLocale())
+ .ifPresent(session::setLocale);
+ return interactionContext.withTimeZone(zoneId);
+ });
+ }
+
+ @Override
+ protected void clearUserTimeZoneFromSession() {
+ userCurrentSessionTimeZoneHolder.clearUserTimeZone();
+ }
+
// -- HELPER
private BookmarkablePageLink<Void> addPasswordResetLink() {
@@ -163,12 +194,4 @@ public class IsisSignInPanel extends SignInPanelAbstract {
}
}
- private void signInHook() {
- if(clearOriginalDestination) {
- clearOriginalDestination();
- }
- Optional.ofNullable(getTimezone())
- .ifPresent(userCurrentSessionTimeZoneHolder::setUserTimeZone);
- }
-
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/SignInPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
index d26ecdc33d..547cd7eb0b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
@@ -20,6 +20,7 @@ package org.apache.isis.viewer.wicket.ui.pages.login;
import java.time.ZoneId;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.wicket.RestartResponseException;
@@ -46,6 +47,7 @@ import org.apache.isis.core.runtime.context.IsisAppCommonContext.HasCommonContex
import org.apache.isis.viewer.wicket.model.util.WktContext;
import lombok.Getter;
+import lombok.NonNull;
import lombok.Setter;
import lombok.val;
@@ -54,7 +56,7 @@ import lombok.val;
* with an additional 'timezone' form field.
* @see org.apache.wicket.authroles.authentication.panel.SignInPanel
*/
-public class SignInPanelAbstract
+public abstract class SignInPanelAbstract
extends Panel
implements HasCommonContext {
@@ -63,7 +65,6 @@ implements HasCommonContext {
private static final String SIGN_IN_FORM = "signInForm";
private static final String TIME_ZONE_SELECT = "timezone-select";
-
/** True if the panel should display a remember-me checkbox */
private boolean includeRememberMe = true;
@@ -181,6 +182,7 @@ implements HasCommonContext {
* Called when sign in failed
*/
protected void onSignInFailed() {
+ clearUserTimeZoneFromSession();
// Try the component based localizer first. If not found try the
// application localizer. Else use the default
error(getLocalizer().getString("signInFailed", this, "Sign in failed"));
@@ -190,6 +192,8 @@ implements HasCommonContext {
* Called when sign in was successful
*/
protected void onSignInSucceeded() {
+ Optional.ofNullable(getTimezone())
+ .ifPresent(zoneId->storeUserTimeZoneToSession(zoneId));
// If login has been called because the user was not yet logged in, than continue to the
// original destination, otherwise to the Home page
continueToOriginalDestination();
@@ -208,6 +212,9 @@ implements HasCommonContext {
* @see #onConfigure()
*/
protected void onSignInRemembered() {
+ Optional.ofNullable(getTimezone())
+ .ifPresent(zoneId->storeUserTimeZoneToSession(zoneId));
+
// logon successful. Continue to the original destination
continueToOriginalDestination();
@@ -324,4 +331,14 @@ implements HasCommonContext {
}
+ /**
+ * Stores user's {@link ZoneId} to their session.
+ */
+ protected abstract void storeUserTimeZoneToSession(@NonNull ZoneId zoneId);
+
+ /**
+ * Clears user's {@link ZoneId} from their session.
+ */
+ protected abstract void clearUserTimeZoneFromSession();
+
}
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
index 7afc1c69fb..3380fe445a 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
@@ -19,6 +19,7 @@
package org.apache.isis.viewer.wicket.viewer.integration;
import java.util.UUID;
+import java.util.function.UnaryOperator;
import org.apache.wicket.Session;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
@@ -39,6 +40,7 @@ import org.apache.isis.core.runtime.context.IsisAppCommonContext;
import org.apache.isis.core.runtime.context.IsisAppCommonContext.HasCommonContext;
import org.apache.isis.core.security.authentication.AuthenticationRequestPassword;
import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
+import org.apache.isis.viewer.wicket.model.isis.HasAmendableInteractionContext;
import org.apache.isis.viewer.wicket.model.models.BookmarkedPagesModel;
import org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModel;
import org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModelProvider;
@@ -55,7 +57,11 @@ import lombok.val;
*/
public class AuthenticatedWebSessionForIsis
extends AuthenticatedWebSession
-implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonContext {
+implements
+ BreadcrumbModelProvider,
+ BookmarkedPagesModelProvider,
+ HasCommonContext,
+ HasAmendableInteractionContext {
private static final long serialVersionUID = 1L;
@@ -142,12 +148,12 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
? SessionSubscriber.CausedBy.USER
: SessionSubscriber.CausedBy.SESSION_EXPIRATION;
-
log(SessionSubscriber.Type.LOGOUT, userName, causedBy);
}
/**
- * If there is an {@link InteractionContext} already (as some authentication mechanisms setup in filters, eg
+ * If there is an {@link InteractionContext} already
+ * (as some authentication mechanisms setup in filters, eg
* SpringSecurityFilter), then just use it.
*
* <p>
@@ -155,10 +161,14 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
* </p>
*/
public void syncExternalAuthenticationIfAvailable() {
+ getInteractionService()
+ .currentInteractionContext()
+ .ifPresent(interactionContext -> this.authentication = interactionContext);
+ }
- val interactionService = commonContext.lookupServiceElseFail(InteractionService.class);
- val interactionContextIfAny = interactionService.currentInteractionContext();
- interactionContextIfAny.ifPresent(interactionContext -> this.authentication = interactionContext);
+ @Override
+ public void amendInteractionContext(final UnaryOperator<InteractionContext> updater) {
+ authentication = updater.apply(authentication);
}
/**
@@ -231,7 +241,7 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
final SessionSubscriber.CausedBy causedBy) {
- val interactionFactory = getInteractionService();
+ val interactionService = getInteractionService();
val sessionLoggingServices = getSessionLoggingServices();
final Runnable loggingTask = ()->{
@@ -244,8 +254,8 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
);
};
- if(interactionFactory!=null) {
- interactionFactory.runAnonymous(loggingTask::run);
+ if(interactionService!=null) {
+ interactionService.runAnonymous(loggingTask::run);
} else {
loggingTask.run();
}
diff --git a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
index fd2152fe80..0eb5a16e1f 100644
--- a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
+++ b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
@@ -76,6 +76,7 @@ public class AuthenticatedWebSessionForIsis_Authenticate {
Collections.singletonList(mockAuthenticator),
new InteractionService_forTesting(),
new RandomCodeGeneratorDefault(),
+ Optional.empty(),
Collections.emptyList());
context.checking(new Expectations() {
diff --git a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
index 4130b03b0a..7e6975b6bd 100644
--- a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
+++ b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
@@ -19,6 +19,7 @@
package org.apache.isis.viewer.wicket.viewer.integration;
import java.util.Locale;
+import java.util.Optional;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
@@ -70,6 +71,7 @@ public class AuthenticatedWebSessionForIsis_SignIn {
singletonList(mockAuthenticator),
new InteractionService_forTesting(),
new RandomCodeGeneratorDefault(),
+ Optional.empty(),
emptyList());
}