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/01/10 10:00:48 UTC

[isis] branch master updated: ISIS-2856: remove deprecated SecmanConfiguration bean

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 bfa9c36  ISIS-2856: remove deprecated SecmanConfiguration bean
bfa9c36 is described below

commit bfa9c3681b00d382d1194c3c5dae827789176de0
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jan 10 11:00:38 2022 +0100

    ISIS-2856: remove deprecated SecmanConfiguration bean
---
 .../modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc |   3 +
 .../secman/applib/SecmanAutoConfiguration.java     |  53 -------
 .../secman/applib/SecmanConfiguration.java         | 175 ---------------------
 .../dom/ApplicationRoleRepositoryAbstract.java     |  25 +--
 .../mixins/ApplicationRole_removePermissions.java  |  18 ++-
 .../seed/IsisExtSecmanAdminRoleAndPermissions.java |  40 +++--
 ...IsisExtSecmanRegularUserRoleAndPermissions.java |   8 +-
 .../scripts/SeedUsersAndRolesFixtureScript.java    |  16 +-
 .../ApplicationUserManager_newDelegateUser.java    |   8 +-
 .../ApplicationUserManager_newLocalUser.java       |   8 +-
 .../secman/applib/user/dom/ApplicationUser.java    |  11 +-
 .../dom/ApplicationUserRepositoryAbstract.java     |   9 +-
 .../user/dom/mixins/ApplicationUser_lock.java      |   6 +-
 .../applib/user/seed/IsisExtSecmanAdminUser.java   |  10 +-
 .../src/main/resources/META-INF/spring.factories   |   2 -
 .../shiro/IsisModuleExtSecmanShiroRealm.java       |  11 +-
 .../changetracking/EntityChangeTrackerJdo.java     |   1 +
 17 files changed, 108 insertions(+), 296 deletions(-)

diff --git a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
index 982e5ef..fdf247a 100644
--- a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
+++ b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
@@ -180,6 +180,9 @@ customize via `ValueSemanticsProvider<T>`
 use `isis.value-types.temporal.editing.*-pattern` instead or
 customize via `ValueSemanticsProvider<T>`
 
+| _SecMan's_ `SecmanConfiguration` bean was removed
+| use `org.apache.isis.core.config.IsisConfiguration.Extensions.Secman` (immutable) instead.
+
 |===
 
 === Password Hashing
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanAutoConfiguration.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanAutoConfiguration.java
deleted file mode 100644
index b047298..0000000
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanAutoConfiguration.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  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.applib;
-
-import org.springframework.boot.autoconfigure.AutoConfigureOrder;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import org.apache.isis.applib.annotations.PriorityPrecedence;
-import org.apache.isis.core.config.IsisConfiguration;
-
-import lombok.val;
-
-@AutoConfigureOrder(PriorityPrecedence.LAST)
-@Configuration
-public class SecmanAutoConfiguration {
-
-    /**
-     * Provides a default implementation of {@link SecmanConfiguration} based on configuration properties.
-     */
-    @Bean("isis.ext.secman.SecmanConfiguration")
-    @ConditionalOnMissingBean(SecmanConfiguration.class)
-    public SecmanConfiguration secmanConfiguration(final IsisConfiguration isisConfiguration) {
-        val secman = isisConfiguration.getExtensions().getSecman();
-        return SecmanConfiguration.builder()
-                .adminUserName(secman.getSeed().getAdmin().getUserName())
-                .adminPassword(secman.getSeed().getAdmin().getPassword())
-                .adminRoleName(secman.getSeed().getAdmin().getRoleName())
-                .adminStickyNamespacePermissions(secman.getSeed().getAdmin().getNamespacePermissions().getSticky().toArray(new String[]{}))
-                .adminAdditionalNamespacePermissions(secman.getSeed().getAdmin().getNamespacePermissions().getAdditional())
-                .regularUserRoleName(secman.getSeed().getRegularUser().getRoleName())
-                .autoUnlockIfDelegatedAndAuthenticated(secman.getDelegatedUsers().getAutoCreatePolicy() == IsisConfiguration.Extensions.Secman.DelegatedUsers.AutoCreatePolicy.AUTO_CREATE_AS_UNLOCKED)
-                .build();
-    }
-
-}
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanConfiguration.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanConfiguration.java
deleted file mode 100644
index d6106d6..0000000
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/SecmanConfiguration.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  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.applib;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.collections._Sets;
-import org.apache.isis.core.config.IsisConfiguration;
-
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.Singular;
-
-/**
- * Applications consuming secman must instantiate a
- * {@link org.springframework.context.annotation.Bean} of this type; secman
- * then uses this bean to configure itself.
- *
- * <p>
- * The typical place to create this bean is in the top-level
- * <code>AppManifest</code>
- * {@link org.springframework.context.annotation.Configuration} class.
- * </p>
- *
- * <p>
- * This class is implemented as a builder (courtesy of Lombok) but it
- * provides reasonable defaults.
- * </p>
- *
- * @deprecated - use <code>application.yml</code> config properties instead;
- * defaults are
- * <ul>
- * <li><code>isis.extensions.secman.seed.admin.user-name=secman-admin</code></li>
- * <li><code>isis.extensions.secman.seed.admin.namespace-permissions.sticky=isis ...</code></li>
- * <li><code>isis.extensions.secman.seed.admin.password=pass</code></li>
- * <li><code>isis.extensions.secman.seed.admin.role-name=isis-ext-secman-admin</code></li>
- * <li><code>isis.extensions.secman.seed.admin.user-name=sven</code></li>
- * <li><code>isis.extensions.secman.seed.regular-user.role-name=isis-ext-secman-user</code></li>
- * <li><code>isis.extensions.secman.seed.admin.namespace-permissions.additional=</code></li>
- * <li><code>isis.extensions.secman.delegated-users.auto-create-policy=AUTO_CREATE_AS_UNLOCKED</code></li>
- * </ul>
- *
- * @since 2.0 {@index}
- */
-@Deprecated
-@Builder
-public class SecmanConfiguration {
-
-    // -- ADMIN
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.Admin#getUserName()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    @NonNull
-    final String adminUserName = IsisConfiguration.Extensions.Secman.Seed.ADMIN_USER_NAME_DEFAULT;
-
-    // sonar-ignore-on (detects potential security risk, which we are aware of)
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.Admin#getPassword()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    @NonNull
-    final String adminPassword = IsisConfiguration.Extensions.Secman.Seed.ADMIN_PASSWORD_DEFAULT;
-    // sonar-ignore-off
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.Admin#getRoleName()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    @NonNull
-    final String adminRoleName = IsisConfiguration.Extensions.Secman.Seed.ADMIN_ROLE_NAME_DEFAULT;
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.Admin.NamespacePermissions#getSticky()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    @NonNull
-    final String[] adminStickyNamespacePermissions = arrayOf(IsisConfiguration.Extensions.Secman.Seed.ADMIN_STICKY_NAMESPACE_PERMISSIONS_DEFAULT);
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.Admin.NamespacePermissions#getAdditional()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Singular
-    final Set<String> adminAdditionalNamespacePermissions;
-
-
-
-    // -- REGULAR USER
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.Seed.RegularUser#getRoleName()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    @NonNull
-    final String regularUserRoleName = IsisConfiguration.Extensions.Secman.Seed.REGULAR_USER_ROLE_NAME_DEFAULT;
-
-    /**
-     * @see IsisConfiguration.Extensions.Secman.DelegatedUsers#getAutoCreatePolicy()
-     *
-     * @deprecated - use <code>application.yml</code> config properties instead.
-     */
-    @Deprecated
-    @Getter
-    @Builder.Default
-    final boolean autoUnlockIfDelegatedAndAuthenticated = IsisConfiguration.Extensions.Secman.Seed.AUTO_UNLOCK_IF_DELEGATED_AND_AUTHENTICATED_DEFAULT;
-
-
-    // -- UTILITIES
-
-    public Stream<String> streamAdminNamespacePermissions() {
-        return Stream.concat(
-                _NullSafe.stream(adminStickyNamespacePermissions),
-                _NullSafe.stream(adminAdditionalNamespacePermissions));
-    }
-
-    public boolean isStickyAdminNamespace(final String featureFqn) {
-        return _NullSafe.stream(adminStickyNamespacePermissions)
-                .anyMatch(stickyPackage -> stickyPackage.equals(featureFqn));
-    }
-
-    private static Set<String> setOf(final Collection<String> coll) {
-        return _Sets.newTreeSet(coll);
-    }
-    private static String[] arrayOf(final List<String> list) {
-        return list.toArray(new String[]{});
-    }
-
-}
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/ApplicationRoleRepositoryAbstract.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/ApplicationRoleRepositoryAbstract.java
index 5ab94da..60b96b7 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/ApplicationRoleRepositoryAbstract.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/ApplicationRoleRepositoryAbstract.java
@@ -35,7 +35,7 @@ import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.collections._Sets;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
+import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.extensions.secman.applib.permission.dom.mixins.ApplicationPermission_delete;
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUser;
 import org.apache.isis.extensions.secman.applib.util.RegexReplacer;
@@ -49,14 +49,14 @@ implements ApplicationRoleRepository {
 
     @Inject private FactoryService factoryService;
     @Inject private RepositoryService repository;
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
     @Inject RegexReplacer regexReplacer;
 
     @Inject private Provider<QueryResultsCache> queryResultsCacheProvider;
 
     private final Class<R> applicationRoleClass;
 
-    protected ApplicationRoleRepositoryAbstract(Class<R> applicationRoleClass) {
+    protected ApplicationRoleRepositoryAbstract(final Class<R> applicationRoleClass) {
         this.applicationRoleClass = applicationRoleClass;
     }
 
@@ -125,7 +125,7 @@ implements ApplicationRoleRepository {
     }
 
     @Override
-    public Collection<ApplicationRole> findMatching(String search) {
+    public Collection<ApplicationRole> findMatching(final String search) {
         if (search != null && search.length() > 0 ) {
             return findNameContaining(search);
         }
@@ -134,8 +134,8 @@ implements ApplicationRoleRepository {
 
     @Override
     public void addRoleToUser(
-            ApplicationRole role,
-            ApplicationUser user) {
+            final ApplicationRole role,
+            final ApplicationUser user) {
 
         user.getRoles().add(role);
         role.getUsers().add(user);
@@ -145,8 +145,8 @@ implements ApplicationRoleRepository {
 
     @Override
     public void removeRoleFromUser(
-            ApplicationRole role,
-            ApplicationUser user) {
+            final ApplicationRole role,
+            final ApplicationUser user) {
 
         user.getRoles().remove(role);
         role.getUsers().remove(user);
@@ -155,13 +155,14 @@ implements ApplicationRoleRepository {
     }
 
     @Override
-    public boolean isAdminRole(ApplicationRole genericRole) {
-        final ApplicationRole adminRole = findByNameCached(configBean.getAdminRoleName()).orElse(null);
+    public boolean isAdminRole(final ApplicationRole genericRole) {
+        val adminRoleName = config.getExtensions().getSecman().getSeed().getAdmin().getRoleName();
+        final ApplicationRole adminRole = findByNameCached(adminRoleName).orElse(null);
         return Objects.equals(adminRole, genericRole);
     }
 
     @Override
-    public void deleteRole(ApplicationRole role) {
+    public void deleteRole(final ApplicationRole role) {
 
         role.getUsers().clear();
         val permissions = role.getPermissions();
@@ -174,7 +175,7 @@ implements ApplicationRoleRepository {
 
     @Override
     public Collection<ApplicationRole> getRoles(
-            ApplicationUser user) {
+            final ApplicationUser user) {
         return user.getRoles();
     }
 
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/mixins/ApplicationRole_removePermissions.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/mixins/ApplicationRole_removePermissions.java
index 49e26c4..bd8c9fb 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/mixins/ApplicationRole_removePermissions.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/dom/mixins/ApplicationRole_removePermissions.java
@@ -31,14 +31,16 @@ import org.apache.isis.applib.annotations.SemanticsOf;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermission;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.applib.role.dom.mixins.ApplicationRole_removePermissions.DomainEvent;
 
 import lombok.RequiredArgsConstructor;
+import lombok.val;
 
 @Action(
         choicesFrom = "permissions",
@@ -58,13 +60,13 @@ public class ApplicationRole_removePermissions {
             extends IsisModuleExtSecmanApplib.ActionDomainEvent<ApplicationRole_removePermissions> {}
 
     @Inject private MessageService messageService;
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
     @Inject private RepositoryService repository;
     @Inject private ApplicationRoleRepository applicationRoleRepository;
 
     private final ApplicationRole target;
 
-    @MemberSupport public ApplicationRole act(Collection<ApplicationPermission> permissions) {
+    @MemberSupport public ApplicationRole act(final Collection<ApplicationPermission> permissions) {
 
         _NullSafe.stream(permissions)
         .filter(this::canRemove)
@@ -73,12 +75,12 @@ public class ApplicationRole_removePermissions {
         return target;
     }
 
-    private boolean canRemove(ApplicationPermission permission) {
+    private boolean canRemove(final ApplicationPermission permission) {
         if(!Objects.equals(permission.getRole(), target)) {
             return false;
         }
         if(applicationRoleRepository.isAdminRole(target)
-                && configBean.isStickyAdminNamespace(permission.getFeatureFqn())) {
+                && isStickyAdminNamespace(config.getExtensions().getSecman(), permission.getFeatureFqn())) {
 
             messageService.warnUser("Cannot remove top-level namespace permissions for the admin role.");
             return false;
@@ -86,4 +88,10 @@ public class ApplicationRole_removePermissions {
         return true;
     }
 
+    private static boolean isStickyAdminNamespace(final Secman secman, final String featureFqn) {
+        val adminNamespacePermissions = secman.getSeed().getAdmin().getNamespacePermissions();
+        return _NullSafe.stream(adminNamespacePermissions.getSticky())
+                .anyMatch(stickyPackage -> stickyPackage.equals(featureFqn));
+    }
+
 }
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanAdminRoleAndPermissions.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanAdminRoleAndPermissions.java
index 079d474..9dbcbe7 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanAdminRoleAndPermissions.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanAdminRoleAndPermissions.java
@@ -18,38 +18,45 @@
  */
 package org.apache.isis.extensions.secman.applib.role.seed;
 
-import java.util.List;
+import java.util.LinkedHashSet;
+import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.commons.collections.Can;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
+import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman.Seed.Admin;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman.Seed.Admin.NamespacePermissions;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.applib.role.fixtures.AbstractRoleAndPermissionsFixtureScript;
 
+import lombok.val;
+
 /**
- * Sets up the {@link SecmanConfiguration#getAdminRoleName() secman admin role}
+ * Sets up the {@link Admin#getRoleName() secman admin role}
  * with its initial set of permissions (the union of
- * {@link SecmanConfiguration#getAdminStickyNamespacePermissions()}
- * and {@link SecmanConfiguration#getAdminAdditionalNamespacePermissions()}).
+ * {@link NamespacePermissions#getSticky()}
+ * and {@link NamespacePermissions#getAdditional()}).
  *
- * @see SecmanConfiguration
+ * @see Secman
  *
  * @since 2.0 {@index}
  */
 public class IsisExtSecmanAdminRoleAndPermissions extends AbstractRoleAndPermissionsFixtureScript {
 
-    private final List<String> adminInitialPackagePermissions;
+    private final Set<String> adminInitialPackagePermissions;
 
-    public IsisExtSecmanAdminRoleAndPermissions(SecmanConfiguration configBean) {
-        super(configBean.getAdminRoleName(), "Administer security");
-        this.adminInitialPackagePermissions = configBean.streamAdminNamespacePermissions()
-                .collect(Collectors.toList());
+    public IsisExtSecmanAdminRoleAndPermissions(final Secman config) {
+        super(config.getSeed().getAdmin().getRoleName(), "Administer security");
+        this.adminInitialPackagePermissions = streamAdminNamespacePermissions(config)
+                .collect(Collectors.toCollection(LinkedHashSet::new)); // preserve order, discard duplicates
     }
 
     @Override
-    protected void execute(ExecutionContext executionContext) {
+    protected void execute(final ExecutionContext executionContext) {
         newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
@@ -57,4 +64,13 @@ public class IsisExtSecmanAdminRoleAndPermissions extends AbstractRoleAndPermiss
                         .map(ApplicationFeatureId::newNamespace));
     }
 
+    // -- HELPER
+
+    private static Stream<String> streamAdminNamespacePermissions(final Secman secman) {
+        val adminNamespacePermissions = secman.getSeed().getAdmin().getNamespacePermissions();
+        return Stream.concat(
+                _NullSafe.stream(adminNamespacePermissions.getSticky()),
+                _NullSafe.stream(adminNamespacePermissions.getAdditional()));
+    }
+
 }
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanRegularUserRoleAndPermissions.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanRegularUserRoleAndPermissions.java
index 2581b57..da60fac 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanRegularUserRoleAndPermissions.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/role/seed/IsisExtSecmanRegularUserRoleAndPermissions.java
@@ -21,9 +21,9 @@ package org.apache.isis.extensions.secman.applib.role.seed;
 import org.apache.isis.applib.IsisModuleApplib;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman;
 import org.apache.isis.core.security.IsisModuleCoreSecurity;
 import org.apache.isis.core.security.authentication.logout.LogoutMenu;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole;
@@ -66,12 +66,12 @@ import lombok.val;
  */
 public class IsisExtSecmanRegularUserRoleAndPermissions extends AbstractRoleAndPermissionsFixtureScript {
 
-    public IsisExtSecmanRegularUserRoleAndPermissions(SecmanConfiguration configBean) {
-        super(configBean.getRegularUserRoleName(), "Regular user of the security module");
+    public IsisExtSecmanRegularUserRoleAndPermissions(final Secman config) {
+        super(config.getSeed().getRegularUser().getRoleName(), "Regular user of the security module");
     }
 
     @Override
-    protected void execute(ExecutionContext executionContext) {
+    protected void execute(final ExecutionContext executionContext) {
 
         val allowChanging = Can.of(
                 // everything under "isis.applib" is granted.
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
index 1e086ec..6393a20 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
@@ -20,7 +20,7 @@ package org.apache.isis.extensions.secman.applib.seed.scripts;
 
 import javax.inject.Inject;
 
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
+import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.extensions.secman.applib.role.seed.IsisAppFeatureRoleAndPermissions;
 import org.apache.isis.extensions.secman.applib.role.seed.IsisConfigurationRoleAndPermissions;
 import org.apache.isis.extensions.secman.applib.role.seed.IsisExtCommandReplayPrimaryRoleAndPermissions;
@@ -36,6 +36,8 @@ import org.apache.isis.extensions.secman.applib.tenancy.seed.GlobalTenancy;
 import org.apache.isis.extensions.secman.applib.user.seed.IsisExtSecmanAdminUser;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
 
+import lombok.val;
+
 /**
  * Sets up roles and permissions for both Secman itself and also for all other modules that expose UI features
  * for use by end-users.
@@ -50,19 +52,21 @@ import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
  */
 public class SeedUsersAndRolesFixtureScript extends FixtureScript {
 
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
 
     @Override
-    protected void execute(ExecutionContext executionContext) {
+    protected void execute(final ExecutionContext executionContext) {
+
+        val secmanConfig = config.getExtensions().getSecman();
 
         // global tenancy
         executionContext.executeChild(this, new GlobalTenancy());
 
         // secman (admin and regular users)
         executionContext.executeChildren(this,
-                new IsisExtSecmanAdminRoleAndPermissions(configBean),
-                new IsisExtSecmanAdminUser(configBean),
-                new IsisExtSecmanRegularUserRoleAndPermissions(configBean));
+                new IsisExtSecmanAdminRoleAndPermissions(secmanConfig),
+                new IsisExtSecmanAdminUser(secmanConfig),
+                new IsisExtSecmanRegularUserRoleAndPermissions(secmanConfig));
 
         // other modules
         executionContext.executeChildren(this,
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newDelegateUser.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newDelegateUser.java
index f289c71..7b9c320 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newDelegateUser.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newDelegateUser.java
@@ -27,8 +27,8 @@ import org.apache.isis.applib.annotations.Optionality;
 import org.apache.isis.applib.annotations.Parameter;
 import org.apache.isis.applib.annotations.ParameterLayout;
 import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.applib.user.app.ApplicationUserManager;
@@ -38,6 +38,7 @@ import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserReposito
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
+import lombok.val;
 
 @Action(
         domainEvent = DomainEvent.class
@@ -54,7 +55,7 @@ public class ApplicationUserManager_newDelegateUser {
 
     @Inject private ApplicationRoleRepository applicationRoleRepository;
     @Inject private ApplicationUserRepository applicationUserRepository;
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
     @Inject private RepositoryService repository;
 
     private final ApplicationUserManager target;
@@ -86,8 +87,9 @@ public class ApplicationUserManager_newDelegateUser {
     }
 
     @MemberSupport public ApplicationRole default1Act() {
+        val regularUserRoleName = config.getExtensions().getSecman().getSeed().getRegularUser().getRoleName();
         return applicationRoleRepository
-                .findByNameCached(configBean.getRegularUserRoleName())
+                .findByNameCached(regularUserRoleName)
                 .orElse(null);
     }
 
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newLocalUser.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newLocalUser.java
index 11fd903..53f3541 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newLocalUser.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/app/mixins/ApplicationUserManager_newLocalUser.java
@@ -31,8 +31,8 @@ import org.apache.isis.applib.annotations.ParameterLayout;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Password;
+import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.applib.user.app.ApplicationUserManager;
@@ -43,6 +43,7 @@ import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserStatus;
 import org.apache.isis.extensions.secman.applib.user.dom.mixins.ApplicationUser_updateEmailAddress;
 
 import lombok.RequiredArgsConstructor;
+import lombok.val;
 
 @Action(
         domainEvent = DomainEvent.class
@@ -60,7 +61,7 @@ extends ApplicationUserManager_newLocalUserAbstract {
 
     @Inject private ApplicationRoleRepository applicationRoleRepository;
     @Inject private ApplicationUserRepository applicationUserRepository;
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
     @Inject private FactoryService factory;
     @Inject private RepositoryService repository;
 
@@ -123,8 +124,9 @@ extends ApplicationUserManager_newLocalUserAbstract {
     }
 
     @MemberSupport public ApplicationRole default3Act() {
+        val regularUserRoleName = config.getExtensions().getSecman().getSeed().getRegularUser().getRoleName();
         return applicationRoleRepository
-                .findByNameCached(configBean.getRegularUserRoleName())
+                .findByNameCached(regularUserRoleName)
                 .orElse(null);
     }
 
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUser.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUser.java
index 5ca72ce..4c0d8ce 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUser.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUser.java
@@ -51,8 +51,9 @@ import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermission;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.applib.permission.dom.ApplicationPermissionRepository;
@@ -78,7 +79,7 @@ public abstract class ApplicationUser
     @Inject private transient ApplicationPermissionRepository applicationPermissionRepository;
     @Inject private transient UserService userService;
     @Inject private transient PermissionsEvaluationService permissionsEvaluationService;
-    @Inject private transient SecmanConfiguration configBean;
+    @Inject private transient IsisConfiguration config;
 
     protected ApplicationUserRepository getApplicationUserRepository() {
         return applicationUserRepository;
@@ -101,8 +102,8 @@ public abstract class ApplicationUser
         return permissionsEvaluationService;
     }
 
-    protected SecmanConfiguration getConfigBean() {
-        return configBean;
+    protected Secman getSecmanConfig() {
+        return config.getExtensions().getSecman();
     }
 
     // -- CONSTANTS
@@ -614,7 +615,7 @@ public abstract class ApplicationUser
 
     @Programmatic
     private String getAdminRoleName() {
-        return getConfigBean().getAdminRoleName();
+        return getSecmanConfig().getSeed().getAdmin().getRoleName();
     }
 
     @Programmatic
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUserRepositoryAbstract.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUserRepositoryAbstract.java
index db69145..cd15845 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUserRepositoryAbstract.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/ApplicationUserRepositoryAbstract.java
@@ -20,6 +20,7 @@ package org.apache.isis.extensions.secman.applib.user.dom;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Consumer;
 
@@ -39,7 +40,6 @@ import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.core.config.IsisConfiguration;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.role.dom.ApplicationRole;
 import org.apache.isis.extensions.secman.applib.tenancy.dom.ApplicationTenancy;
 import org.apache.isis.extensions.secman.applib.user.dom.mixins.ApplicationUser_lock;
@@ -55,8 +55,7 @@ implements ApplicationUserRepository {
 
     @Inject private FactoryService factoryService;
     @Inject private RepositoryService repository;
-    @Inject private SecmanConfiguration configBean;
-	@Inject protected IsisConfiguration isisConfiguration;
+	@Inject protected IsisConfiguration config;
     @Inject private EventBusService eventBusService;
     @Inject RegexReplacer regexReplacer;
 
@@ -199,7 +198,9 @@ implements ApplicationUserRepository {
 
     @Override
     public boolean isAdminUser(final ApplicationUser user) {
-        return configBean.getAdminUserName().equals(user.getName());
+        return Objects.equals(
+                config.getExtensions().getSecman().getSeed().getAdmin().getUserName(),
+                user.getName());
     }
 
     @Override
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/ApplicationUser_lock.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/ApplicationUser_lock.java
index faf5acc..f4229c4 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/ApplicationUser_lock.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/ApplicationUser_lock.java
@@ -24,8 +24,8 @@ import org.apache.isis.applib.annotations.Action;
 import org.apache.isis.applib.annotations.ActionLayout;
 import org.apache.isis.applib.annotations.MemberSupport;
 import org.apache.isis.applib.annotations.SemanticsOf;
+import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 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;
@@ -49,7 +49,7 @@ public class ApplicationUser_lock {
             extends IsisModuleExtSecmanApplib.ActionDomainEvent<ApplicationUser_lock> {}
 
     @Inject private ApplicationUserRepository applicationUserRepository;
-    @Inject private SecmanConfiguration configBean;
+    @Inject private IsisConfiguration config;
 
     private final ApplicationUser target;
 
@@ -60,7 +60,7 @@ public class ApplicationUser_lock {
 
     @MemberSupport public String disableAct() {
         if(applicationUserRepository.isAdminUser(target)) {
-            return String.format("Cannot lock the '%s' user.", configBean.getAdminUserName());
+            return String.format("Cannot lock the '%s' user.", config.getExtensions().getSecman().getSeed().getAdmin().getUserName());
         }
         return target.getStatus() == ApplicationUserStatus.LOCKED ? "Status is already set to LOCKED": null;
     }
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/seed/IsisExtSecmanAdminUser.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/seed/IsisExtSecmanAdminUser.java
index a3d8ee5..a3bc8e4 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/seed/IsisExtSecmanAdminUser.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/seed/IsisExtSecmanAdminUser.java
@@ -19,7 +19,7 @@
 package org.apache.isis.extensions.secman.applib.user.seed;
 
 import org.apache.isis.commons.collections.Can;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman;
 import org.apache.isis.extensions.secman.applib.tenancy.seed.GlobalTenancy;
 import org.apache.isis.extensions.secman.applib.user.dom.AccountType;
 import org.apache.isis.extensions.secman.applib.user.fixtures.AbstractUserAndRolesFixtureScript;
@@ -30,13 +30,13 @@ import org.apache.isis.extensions.secman.applib.user.fixtures.AbstractUserAndRol
  */
 public class IsisExtSecmanAdminUser extends AbstractUserAndRolesFixtureScript {
 
-    public IsisExtSecmanAdminUser(SecmanConfiguration configBean) {
+    public IsisExtSecmanAdminUser(final Secman config) {
         super(
-                configBean.getAdminUserName(),
-                configBean.getAdminPassword(),
+                config.getSeed().getAdmin().getUserName(),
+                config.getSeed().getAdmin().getPassword(),
                 null,
                 GlobalTenancy.TENANCY_PATH,
                 AccountType.LOCAL,
-                Can.of(configBean.getAdminRoleName()));
+                Can.of(config.getSeed().getAdmin().getRoleName()));
     }
 }
diff --git a/extensions/security/secman/applib/src/main/resources/META-INF/spring.factories b/extensions/security/secman/applib/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index c505230..0000000
--- a/extensions/security/secman/applib/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-  org.apache.isis.extensions.secman.applib.SecmanAutoConfiguration
diff --git a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
index ab50f49..3cfbdf7 100644
--- a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
+++ b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
@@ -46,8 +46,8 @@ import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.config.IsisConfiguration.Extensions.Secman.DelegatedUsers.AutoCreatePolicy;
 import org.apache.isis.core.security.authorization.Authorizor;
-import org.apache.isis.extensions.secman.applib.SecmanConfiguration;
 import org.apache.isis.extensions.secman.applib.user.dom.AccountType;
 import org.apache.isis.extensions.secman.applib.user.dom.ApplicationUserRepository;
 import org.apache.isis.extensions.secman.shiro.util.ShiroUtils;
@@ -65,8 +65,7 @@ public class IsisModuleExtSecmanShiroRealm extends AuthorizingRealm {
 	@Inject protected ServiceInjector serviceInjector;
     @Inject protected InteractionService interactionService;
     @Inject protected PlatformTransactionManager txMan;
-    @Inject private SecmanConfiguration configBean;
-	@Inject protected IsisConfiguration isisConfiguration;
+	@Inject protected IsisConfiguration config;
 
     @Getter @Setter private AuthenticatingRealm delegateAuthenticationRealm;
     @Getter @Setter private boolean autoCreateUser = true;
@@ -121,7 +120,11 @@ public class IsisModuleExtSecmanShiroRealm extends AuthorizingRealm {
 
             _Assert.assertNotNull(newPrincipal);
 
-            if(configBean.isAutoUnlockIfDelegatedAndAuthenticated()) {
+            val isAutoUnlockIfDelegatedAndAuthenticated =
+                    config.getExtensions().getSecman().getDelegatedUsers().getAutoCreatePolicy()
+                        == AutoCreatePolicy.AUTO_CREATE_AS_UNLOCKED;
+
+            if(isAutoUnlockIfDelegatedAndAuthenticated) {
                 principal = newPrincipal;
             } else {
                 _Assert.assertTrue(newPrincipal.isLocked(), "As configured in " + SECMAN_UNLOCK_DELEGATED_USERS + ", auto-created user accounts are initially locked!");
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/changetracking/EntityChangeTrackerJdo.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/changetracking/EntityChangeTrackerJdo.java
index 1e32f4d..44d57f0 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/changetracking/EntityChangeTrackerJdo.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/changetracking/EntityChangeTrackerJdo.java
@@ -316,6 +316,7 @@ implements
         val records = propertyChangeRecordsById.values().stream()
                 // set post values, which have been left empty up to now
                 .peek(rec->{
+                    // assuming this check correctly detects deleted entities (JDO)
                     if(EntityUtil.isDetachedOrRemoved(rec.getEntity())) {
                         rec.updatePostValueAsDeleted();
                     } else {