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 2022/08/23 17:05:26 UTC

[isis] 01/02: ISIS-3169: also adds auto-created users to a set of initial roles.

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

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

commit 849917841242f7e98dcda709583ddbb19e53efa3
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Aug 23 16:29:50 2022 +0100

    ISIS-3169: also adds auto-created users to a set of initial roles.
---
 .../apache/isis/core/config/IsisConfiguration.java | 17 +++++++-
 .../dom/ApplicationUserAutoCreationService.java    | 47 ++++++++++++++++++++--
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
index 2be200a9fe..c6bb6c980b 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
@@ -3105,7 +3105,6 @@ public class IsisConfiguration {
                 public enum AutoCreatePolicy {
                     AUTO_CREATE_AS_LOCKED,
                     AUTO_CREATE_AS_UNLOCKED,
-                    // NO_AUTO_CREATE
                 }
 
                 /**
@@ -3115,10 +3114,26 @@ public class IsisConfiguration {
                  * BE AWARE THAT if any users are auto-created as unlocked, then the set of roles that
                  * they are given should be highly restricted !!!
                  * </p>
+                 *
+                 * <p>
+                 *     NOTE also that this configuration policy is ignored if running secman with Spring OAuth2
+                 *     or Keycloak as the authenticator; users are always auto-created.
+                 * </p>
                  */
                 @Getter @Setter
                 private AutoCreatePolicy autoCreatePolicy = AutoCreatePolicy.AUTO_CREATE_AS_LOCKED;
 
+                /**
+                 * The set of roles that users that have been automatically created are granted automatically.
+                 *
+                 * <p>
+                 *     Typically the regular user role (as per <code>isis.secman.seed.regular-user.role-name</code>
+                 *     will be one of the roles listed here; that will provide the ability for the end-user to logout,
+                 *     among other things (!).
+                 * </p>
+                 */
+                private List<String> initialRoleNames = new ArrayList<>();
+
             }
 
             public enum PermissionsEvaluationPolicy {
diff --git a/extensions/security/secman/delegated-springoauth2/src/main/java/org/apache/isis/extensions/secman/delegated/springoauth2/dom/ApplicationUserAutoCreationService.java b/extensions/security/secman/delegated-springoauth2/src/main/java/org/apache/isis/extensions/secman/delegated/springoauth2/dom/ApplicationUserAutoCreationService.java
index f485a6825e..85289c6e31 100644
--- a/extensions/security/secman/delegated-springoauth2/src/main/java/org/apache/isis/extensions/secman/delegated/springoauth2/dom/ApplicationUserAutoCreationService.java
+++ b/extensions/security/secman/delegated-springoauth2/src/main/java/org/apache/isis/extensions/secman/delegated/springoauth2/dom/ApplicationUserAutoCreationService.java
@@ -20,16 +20,27 @@
 
 package org.apache.isis.extensions.secman.delegated.springoauth2.dom;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 import javax.inject.Inject;
 
 import org.springframework.context.ApplicationListener;
+import org.springframework.lang.Nullable;
 import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
 import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRoleRepository;
+import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUser;
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserRepository;
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserStatus;
+import org.apache.isis.extensions.secman.applib.user.dom.mixins.ApplicationUser_addRole;
+import org.apache.isis.extensions.secman.applib.user.dom.mixins.ApplicationUser_updateEmailAddress;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
@@ -40,7 +51,10 @@ public class ApplicationUserAutoCreationService
         implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
 
     private final ApplicationUserRepository applicationUserRepository;
+    private final ApplicationRoleRepository applicationRoleRepository;
     private final InteractionService interactionService;
+    private final IsisConfiguration isisConfiguration;
+    private final FactoryService factoryService;
 
     @Override
     public void onApplicationEvent(final InteractiveAuthenticationSuccessEvent event) {
@@ -53,8 +67,35 @@ public class ApplicationUserAutoCreationService
         val oidcUser = (DefaultOidcUser) principal;
         val username = oidcUser.getIdToken().getPreferredUsername();
         val email = oidcUser.getIdToken().getEmail();
-        val applicationUser = interactionService.callAnonymous(() -> applicationUserRepository.findOrCreateUserByUsername(username));
-        applicationUser.setEmailAddress(email);
-        applicationUser.setStatus(ApplicationUserStatus.UNLOCKED);  // locking not supported for keycloak
+        interactionService.runAnonymous(() -> {
+            Optional<ApplicationUser> userIfAny = applicationUserRepository.findByUsername(username);
+            if (userIfAny.isEmpty()) {
+                val status = ApplicationUserStatus.UNLOCKED;  // locking not supported for spring delegated accounts
+                val applicationUser = applicationUserRepository.newDelegateUser(username, status);
+                factoryService.mixin(ApplicationUser_updateEmailAddress.class, applicationUser).act(email);
+
+                val initialRoleNames = isisConfiguration.getExtensions().getSecman().getDelegatedUsers().getInitialRoleNames();
+                if (notEmpty(initialRoleNames)) {
+                    for (String initialRoleName : initialRoleNames) {
+                        addRoleIfExists(applicationUser, initialRoleName);
+                    }
+                }
+            }
+        });
     }
+
+    private void addRoleIfExists(ApplicationUser applicationUser, String initialRoleName) {
+        applicationRoleRepository.findByName(initialRoleName).ifPresent(role -> {
+            factoryService.mixin(ApplicationUser_addRole.class, applicationUser).act(role);
+        });
+    }
+
+    private static boolean notEmpty(List<String> initialRoleNames) {
+        return !isEmpty(initialRoleNames);
+    }
+
+    private static boolean isEmpty(@Nullable Collection<?> collection) {
+        return collection == null || collection.isEmpty();
+    }
+
 }