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 21:04:39 UTC

[isis] branch ISIS-2728 updated (b255e47 -> cc1d574)

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

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


 discard b255e47  ISIS-2728: adds secman implementation of UserMementoRefiner
 discard e44bebe  ISIS-2728: introduces UserMementoRefiner as a new SPI
 discard e141c7f  ISIS-2728: adds UserMemento#multiTenancyToken unit tests
 discard 279be8e  ISIS-2728: adds multiTenancyToken into UserMemento
     new da98c72  ISIS-2483: reverts docs on @Nested
     new 243fb29  ISIS-2728: adds multiTenancyToken into UserMemento
     new 6de24fe  ISIS-2728: adds UserMemento#multiTenancyToken unit tests
     new 5536482  ISIS-2728: introduces UserMementoRefiner as a new SPI
     new cc1d574  ISIS-2728: adds secman implementation of UserMementoRefiner

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (b255e47)
            \
             N -- N -- N   refs/heads/ISIS-2728 (cc1d574)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .run/SimpleApp.run.xml                                   | 16 ++++++++++++++++
 .../services/iactnlayer/InteractionContextUtil.java      |  7 +------
 .../fixtures/pages/fixture-scripts/api-and-usage.adoc    |  3 +--
 .../adoc/modules/integtestsupport/pages/about.adoc       |  3 +--
 4 files changed, 19 insertions(+), 10 deletions(-)
 create mode 100644 .run/SimpleApp.run.xml

[isis] 05/05: ISIS-2728: adds secman implementation of UserMementoRefiner

Posted by da...@apache.org.
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 cc1d5743ea40a2335a76290a891690364832322c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Jun 29 10:23:09 2021 +0100

    ISIS-2728: adds secman implementation of UserMementoRefiner
    
    ... to copy the ApplicationUser#atPath onto the UserMemento#multiTenancyToken
    
    (cherry picked from commit b255e47d4206a6046fc0806e851fd4eb9536c993)
---
 .../UserMementoRefinerFromApplicationUser.java     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)

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
new file mode 100644
index 0000000..2b29aa2
--- /dev/null
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/usermementorefiner/UserMementoRefinerFromApplicationUser.java
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.extensions.secman.integration.usermementorefiner;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Service;
+
+import org.apache.isis.applib.services.user.UserMemento;
+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
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class UserMementoRefinerFromApplicationUser implements UserMementoRefiner {
+
+    private final ApplicationUserRepository applicationUserRepository;
+
+    @Override
+    public UserMemento refine(UserMemento userMemento) {
+        return applicationUserRepository.findByUsername(userMemento.getName())
+                .map(applicationUser -> userMemento.withMultiTenancyToken(applicationUser.getAtPath()))
+                .orElse(userMemento);
+    }
+}

[isis] 02/05: ISIS-2728: adds multiTenancyToken into UserMemento

Posted by da...@apache.org.
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 243fb2960ed04eb0c728671a9ece787995e187ef
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Jun 29 07:22:04 2021 +0100

    ISIS-2728: adds multiTenancyToken into UserMemento
    
    (cherry picked from commit 279be8e853667adfece8ad321ee6c1b0ff32fe5c)
---
 .../org/apache/isis/applib/services/user/UserMemento.java    | 12 ++++++++++--
 .../applib/services/user/UserMemento.layout.fallback.xml     |  2 +-
 2 files changed, 11 insertions(+), 3 deletions(-)

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 38825f7..4469a1e 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
@@ -183,7 +183,7 @@ public class UserMemento implements Serializable {
      * where the validity of the session is defined by headers in the request.
      */
     @Property
-    @PropertyLayout(fieldSetId = "authentication", sequence = "1")
+    @PropertyLayout(fieldSetId = "security", sequence = "1")
     @Getter @Builder.Default @With(onMethod_ = {@Programmatic})
     @NonNull
     AuthenticationSource authenticationSource = AuthenticationSource.DEFAULT;
@@ -205,11 +205,18 @@ public class UserMemento implements Serializable {
 
 
     @Property(optionality = Optionality.OPTIONAL)
-    @PropertyLayout(fieldSetId = "authentication", sequence = "2")
+    @PropertyLayout(fieldSetId = "security", sequence = "2")
     @Getter @Builder.Default @With(onMethod_ = {@Programmatic})
     boolean impersonating = false;
 
 
+    @Property(optionality = Optionality.OPTIONAL)
+    @PropertyLayout(fieldSetId = "security", sequence = "3")
+    @Getter @With(onMethod_ = {@Programmatic})
+    @Nullable
+    String multiTenancyToken;
+
+
     private static final String DEFAULT_AUTH_VALID_CODE = "";
 
     /**
@@ -282,6 +289,7 @@ public class UserMemento implements Serializable {
                 .avatarUrl(avatarUrl)
                 .impersonating(impersonating)
                 .realName(realName)
+                .multiTenancyToken(multiTenancyToken)
                 .roles(roles);
     }
 
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.layout.fallback.xml b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.layout.fallback.xml
index 1b2d386..abe976c 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.layout.fallback.xml
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/UserMemento.layout.fallback.xml
@@ -53,7 +53,7 @@ under the License.
                 </bs3:tab>
             </bs3:tabGroup>
             <cpt:fieldSet name="Details" id="details"/>
-            <cpt:fieldSet name="Authentication" id="authentication"/>
+            <cpt:fieldSet name="Security" id="security"/>
         </bs3:col>
         <bs3:col span="6">
             <cpt:collection id="roles"/>

[isis] 01/05: ISIS-2483: reverts docs on @Nested

Posted by da...@apache.org.
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 da98c72b2c9c15072d2e4983e49d88900458bb5f
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Aug 5 19:51:09 2021 +0100

    ISIS-2483: reverts docs on @Nested
---
 .run/SimpleApp.run.xml                                   | 16 ++++++++++++++++
 .../fixtures/pages/fixture-scripts/api-and-usage.adoc    |  3 +--
 .../adoc/modules/integtestsupport/pages/about.adoc       |  3 +--
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/.run/SimpleApp.run.xml b/.run/SimpleApp.run.xml
new file mode 100644
index 0000000..983ba73
--- /dev/null
+++ b/.run/SimpleApp.run.xml
@@ -0,0 +1,16 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="SimpleApp" type="Application" factoryName="Application" nameIsGenerated="true">
+    <option name="MAIN_CLASS_NAME" value="domainapp.webapp.SimpleApp" />
+    <module name="simpleapp-jpa-webapp" />
+    <shortenClasspath name="ARGS_FILE" />
+    <extension name="coverage">
+      <pattern>
+        <option name="PATTERN" value="domainapp.webapp.*" />
+        <option name="ENABLED" value="true" />
+      </pattern>
+    </extension>
+    <method v="2">
+      <option name="Make" enabled="true" />
+    </method>
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/api-and-usage.adoc b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/api-and-usage.adoc
index 074a6a4..c5920d1 100644
--- a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/api-and-usage.adoc
+++ b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/api-and-usage.adoc
@@ -326,8 +326,7 @@ public class SimpleObject_IntegTest extends SimpleModuleIntegTestAbstract {
         simpleObject = fixtureScripts.runPersona(SimpleObject_persona.FOO); // <.>
     }
 
-    @Nested
-    public class updateName{
+    public static class updateName extends SimpleObject_IntegTest {
 
         @Test
         void can_be_updated_directly() {
diff --git a/testing/integtestsupport/adoc/modules/integtestsupport/pages/about.adoc b/testing/integtestsupport/adoc/modules/integtestsupport/pages/about.adoc
index ee205d0..18553c0 100644
--- a/testing/integtestsupport/adoc/modules/integtestsupport/pages/about.adoc
+++ b/testing/integtestsupport/adoc/modules/integtestsupport/pages/about.adoc
@@ -236,8 +236,7 @@ By convention, we group tests into nested static classes, so the corresponding i
 ----
 public class SimpleObject_IntegTest extends SimpleModuleIntegTestAbstract {
     ...
-    @Nested
-    public class Name {
+    public static class name extends SimpleObject_IntegTest {
 
         @Test
         void accessible() {

[isis] 04/05: ISIS-2728: introduces UserMementoRefiner as a new SPI

Posted by da...@apache.org.
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 5536482fd17986686c867418de4615f1f0d8d6a1
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Jun 29 10:17:43 2021 +0100

    ISIS-2728: introduces UserMementoRefiner as a new SPI
    
    to allow secman to be able to add in the multiTenancyToken from the ApplicationUser
    
    (cherry picked from commit e44bebe8a9928f58cc42c1be73c1cd13066801da)
---
 .../services/iactnlayer/InteractionContext.java    | 35 ++++++++--
 .../iactnlayer/InteractionContextUtil.java         | 22 ++++++
 .../manager/AuthenticationManager.java             | 36 ++++++++--
 .../authentication/manager/UserMementoRefiner.java | 78 ++++++++++++++++++++++
 .../authconverters/AuthenticationConverter.java    |  2 +-
 5 files changed, 160 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 1d75cb7..c7d30f9 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
@@ -28,10 +28,14 @@ import org.apache.isis.applib.clock.VirtualClock;
 import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.user.UserMemento;
 
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Builder;
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
+import lombok.ToString;
 import lombok.With;
 
 /**
@@ -39,7 +43,12 @@ import lombok.With;
  *
  * @since 2.0 {@index}
  */
-@lombok.Value @Builder
+@Getter
+@lombok.experimental.FieldDefaults(makeFinal=false, level= AccessLevel.PRIVATE)
+@AllArgsConstructor
+@ToString
+@EqualsAndHashCode
+@Builder
 @RequiredArgsConstructor
 public class InteractionContext implements Serializable {
 
@@ -66,11 +75,12 @@ public class InteractionContext implements Serializable {
     /**
      * The (programmatically) simulated (or actual) user.
      *
-     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its
+     * @apiNote practically immutable, allows an {@link Interaction} to (logically) run with its
      * own simulated (or actual) user
+     *
      */
     @With @Getter @Builder.Default
-    @NonNull UserMemento user = UserMemento.system();
+    @NonNull /*final*/ UserMemento user = UserMemento.system();
 
     /**
      * The (programmatically) simulated (or actual) clock.
@@ -79,13 +89,13 @@ public class InteractionContext implements Serializable {
      * own simulated (or actual) clock
      */
     @With @Getter @Builder.Default
-    @NonNull VirtualClock clock = VirtualClock.system();
+    @NonNull final VirtualClock clock = VirtualClock.system();
 
     @With @Getter @Builder.Default
-    @NonNull Locale locale = Locale.getDefault();
+    @NonNull final Locale locale = Locale.getDefault();
 
     @With @Getter @Builder.Default
-    @NonNull TimeZone timeZone = TimeZone.getDefault();
+    @NonNull final TimeZone timeZone = TimeZone.getDefault();
 
 
     /**
@@ -146,5 +156,16 @@ public class InteractionContext implements Serializable {
         return mappers.reduce(t -> t, (a,b) -> a.andThen(b)::apply);
     }
 
-
+    /**
+     * For internal usage, not API.
+     *
+     * <p>
+     *     Instead, use {@link #withUser(UserMemento)}, which honours the value semantics of this class.
+     * </p>
+     *
+     * @param user
+     */
+    void replaceUser(UserMemento user) {
+        this.user = user;
+    }
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContextUtil.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContextUtil.java
new file mode 100644
index 0000000..4f38b42
--- /dev/null
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContextUtil.java
@@ -0,0 +1,22 @@
+package org.apache.isis.applib.services.iactnlayer;
+
+import org.apache.isis.applib.services.user.UserMemento;
+
+import lombok.experimental.UtilityClass;
+
+
+@UtilityClass
+public class InteractionContextUtil{
+
+    /**
+     * For internal usage, not formal API.
+     *
+     * <p>
+     *     Instead, use {@link InteractionContext#withUser(UserMemento)}, which honours the value semantics of this class.
+     * </p>
+     */
+    public static void replaceUserIn(InteractionContext interactionContext, UserMemento userMemento) {
+        interactionContext.replaceUser(userMemento);
+    }
+
+}
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 8f03b81..5457f18 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
@@ -35,7 +35,9 @@ import org.springframework.transaction.annotation.Transactional;
 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.InteractionContextUtil;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.applib.util.ToString;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Timing;
@@ -61,16 +63,19 @@ public class AuthenticationManager {
     private final @NonNull InteractionService interactionService;
     private final @NonNull RandomCodeGenerator randomCodeGenerator;
     private final @NonNull Can<Registrar> registrars;
+    private final @NonNull List<UserMementoRefiner> userMementoRefiners;
 
     @Inject
     public AuthenticationManager(
             final List<Authenticator> authenticators,
             // needs @Lazy due to circular provisioning dependency
             final @Lazy InteractionService anonymousInteractionFactory,
-            final RandomCodeGenerator randomCodeGenerator) {
+            final RandomCodeGenerator randomCodeGenerator,
+            final List<UserMementoRefiner> userMementoRefiners) {
         this.interactionService = anonymousInteractionFactory;
         this.randomCodeGenerator = randomCodeGenerator;
         this.authenticators = Can.ofCollection(authenticators);
+        this.userMementoRefiners = userMementoRefiners;
         if (this.authenticators.isEmpty()) {
             throw new NoAuthenticatorException("No authenticators specified");
         }
@@ -102,13 +107,13 @@ public class AuthenticationManager {
         return interactionService.callAnonymous(()->{
 
             for (val authenticator : compatibleAuthenticators) {
-                val authentication = authenticator.authenticate(request, getUnusedRandomCode());
-                if (authentication != null) {
-                    val userMemento = authentication.getUser();
+                val interactionContext = authenticator.authenticate(request, getUnusedRandomCode());
+                if (interactionContext != null) {
+                    val userMemento = refineUserWithin(interactionContext);
                     userByValidationCode.put(
                             userMemento.getAuthenticationCode(),
                             userMemento.getName());
-                    return authentication;
+                    return interactionContext;
                 }
             }
 
@@ -116,6 +121,27 @@ public class AuthenticationManager {
         });
     }
 
+    /**
+     * Iterates over all available {@link UserMementoRefiner}s; if at the end the {@link UserMemento} has been changed,
+     * then replaces (using a private API) the {@link UserMemento} held within {@link InteractionContext}.
+     *
+     * @param interactionContext
+     * @return
+     */
+    @NonNull
+    private UserMemento refineUserWithin(InteractionContext interactionContext) {
+        val userMementoOrig = interactionContext.getUser();
+        UserMemento userMemento = userMementoOrig;
+        for (UserMementoRefiner refiner : userMementoRefiners) {
+            final UserMemento refined = refiner.refine(userMemento);
+            userMemento = refined != null ? refined : userMemento;
+        }
+        if(userMemento != userMementoOrig) {
+            InteractionContextUtil.replaceUserIn(interactionContext, userMemento);
+        }
+        return interactionContext.getUser();
+    }
+
     private String getUnusedRandomCode() {
 
         val stopWatch = _Timing.now();
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/UserMementoRefiner.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/UserMementoRefiner.java
new file mode 100644
index 0000000..cdd895f
--- /dev/null
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/UserMementoRefiner.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.security.authentication.manager;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+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.UserMemento;
+import org.apache.isis.applib.util.ToString;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Timing;
+import org.apache.isis.commons.internal.collections._Maps;
+import org.apache.isis.core.security.authentication.AuthenticationRequest;
+import org.apache.isis.core.security.authentication.Authenticator;
+import org.apache.isis.core.security.authentication.standard.RandomCodeGenerator;
+import org.apache.isis.core.security.authentication.standard.Registrar;
+
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.val;
+
+/**
+ * SPI provided by the internal {@link AuthenticationManager}, allowing the {@link UserMemento} representing an
+ * authenticated (logged in) user to be refined.
+ *
+ * <p>
+ *     As {@link UserMemento} is immutable, the implementation must return a new instance.  This new instance replaces
+ *     the {@link InteractionContext#getUser() user reference held} by {@link InteractionContext}.
+ * </p>
+ *
+ * <p>
+ *     Originally introduced to allow SecMan to update the {@link UserMemento#getMultiTenancyToken() multi-tenancy}
+ *     token of {@link UserMemento}.
+ * </p>
+ */
+public interface UserMementoRefiner {
+
+    /**
+     * Return either the same (unchanged) or an updated {@link UserMemento} to use instead of the original within the
+     * owning {@link InteractionContext}.
+     *
+     * @param userMemento - to be refined
+     * @return the userMemento that is refined, or else unchanged.
+     */
+    UserMemento refine(final UserMemento userMemento);
+
+}
diff --git a/security/spring/src/main/java/org/apache/isis/security/spring/authconverters/AuthenticationConverter.java b/security/spring/src/main/java/org/apache/isis/security/spring/authconverters/AuthenticationConverter.java
index 39efb07..535a3c2 100644
--- a/security/spring/src/main/java/org/apache/isis/security/spring/authconverters/AuthenticationConverter.java
+++ b/security/spring/src/main/java/org/apache/isis/security/spring/authconverters/AuthenticationConverter.java
@@ -24,7 +24,7 @@ import org.apache.isis.applib.services.user.UserMemento;
  *     All known converters are checked one by one, but checking stops once one
  *     converter has successively converted the {@link Authentication} into a
  *     {@link UserMemento} (in other words, chain-of-responsibility pattern).
- *     Use the {@link org.springframework.core.Ordered} to influence the order
+ *     Use the {@link javax.annotation.Priority} annotation to influence the order
  *     in which converter implementations are checked.
  * </p>
  *

[isis] 03/05: ISIS-2728: adds UserMemento#multiTenancyToken unit tests

Posted by da...@apache.org.
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 6de24feb8a29d2ec325679d6497ac6887d9949f2
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 16:47:00 2021 +0100

    ISIS-2728: adds UserMemento#multiTenancyToken unit tests
    
    (cherry picked from commit e141c7ffb8f401eb80d99997e12b0121604a1d21)
---
 .../isis/applib/services/user/UserMemento.java     |  7 ++++++
 .../applib/services/user/UserMemento_Test.java     | 29 +++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

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 4469a1e..5b5c78b 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
@@ -210,6 +210,13 @@ public class UserMemento implements Serializable {
     boolean impersonating = false;
 
 
+    /**
+     * Indicates which tenancy (or tenancies) this user has access to.
+     *
+     * <p>
+     * The interpretation of this token is implementation-specific.
+     * </p>
+     */
     @Property(optionality = Optionality.OPTIONAL)
     @PropertyLayout(fieldSetId = "security", sequence = "3")
     @Getter @With(onMethod_ = {@Programmatic})
diff --git a/api/applib/src/test/java/org/apache/isis/applib/services/user/UserMemento_Test.java b/api/applib/src/test/java/org/apache/isis/applib/services/user/UserMemento_Test.java
index 504ac66..8cef9df 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/services/user/UserMemento_Test.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/services/user/UserMemento_Test.java
@@ -215,6 +215,29 @@ class UserMemento_Test {
     }
 
     @Nested
+    class withTenancyToken {
+
+        @Test
+        void user_and_roles_preserved_and_impersonating_flag_set() throws MalformedURLException {
+
+            // given
+            val userMemento = UserMemento.ofNameAndRoleNames("fredflintstone", "CAVEMAN", "HUSBAND");
+
+            // when
+            val userMemento2 = userMemento.withMultiTenancyToken("/ITA");
+
+            // then copy created
+            Assertions.assertThat(userMemento2).isNotSameAs(userMemento);
+
+            // then copy correct
+            Assertions.assertThat(userMemento2.getMultiTenancyToken()).isEqualTo("/ITA");
+
+            // then original unchanged
+            Assertions.assertThat(userMemento.getMultiTenancyToken()).isNull();
+        }
+    }
+
+    @Nested
     class all_the_withers {
 
         @Test
@@ -225,7 +248,9 @@ class UserMemento_Test {
                     .withRoleAdded("CAVEMAN")
                     .withRoleAdded("HUSBAND")
                     .withAvatarUrl(new java.net.URL("https://upload.wikimedia.org/wikipedia/en/a/ad/Fred_Flintstone.png"))
-                    .withRealName("Fred Flintstone");
+                    .withRealName("Fred Flintstone")
+                    .withMultiTenancyToken("/USA/Bedrock")
+                    ;
 
             // then
             Assertions.assertThat(userMemento.getName()).isEqualTo("fredflintstone");
@@ -250,6 +275,7 @@ class UserMemento_Test {
             Assertions.assertThat(userMemento2.getAvatarUrl()).isEqualTo(new java.net.URL("https://upload.wikimedia.org/wikipedia/en/a/ad/Fred_Flintstone.png"));
             Assertions.assertThat(userMemento2.getRealName()).isEqualTo("Fred Flintstone");
             Assertions.assertThat(userMemento2.isImpersonating()).isTrue();
+            Assertions.assertThat(userMemento2.getMultiTenancyToken()).isEqualTo("/USA/Bedrock");
 
             // then original unchanged
             Assertions.assertThat(userMemento.getName()).isEqualTo("fredflintstone");
@@ -259,6 +285,7 @@ class UserMemento_Test {
             Assertions.assertThat(userMemento.getAvatarUrl()).isEqualTo(new java.net.URL("https://upload.wikimedia.org/wikipedia/en/a/ad/Fred_Flintstone.png"));
             Assertions.assertThat(userMemento.getRealName()).isEqualTo("Fred Flintstone");
             Assertions.assertThat(userMemento.isImpersonating()).isFalse();
+            Assertions.assertThat(userMemento.getMultiTenancyToken()).isEqualTo("/USA/Bedrock");
 
         }
     }