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 2021/03/04 19:50:07 UTC

[isis] branch master updated: ISIS-2562: SecMan: make seeding namespace aware

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 7000946  ISIS-2562: SecMan: make seeding namespace aware
7000946 is described below

commit 7000946e4fb25a05bf7db8d8eea2f9e66695b3fc
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Mar 4 20:49:53 2021 +0100

    ISIS-2562: SecMan: make seeding namespace aware
---
 .../security/authentication/logout/LogoutMenu.java |  6 +-
 .../AbstractRoleAndPermissionsFixtureScript.java   | 97 ++++------------------
 ...xtFixturesFixtureResultsRoleAndPermissions.java | 10 ++-
 .../IsisExtSecmanAdminRoleAndPermissions.java      |  7 +-
 .../IsisExtSecmanFixtureRoleAndPermissions.java    |  8 +-
 ...IsisExtSecmanRegularUserRoleAndPermissions.java | 88 +++++++++-----------
 .../AbstractRoleAndPermissionsFixtureScript.java   | 90 ++++----------------
 ...xtFixturesFixtureResultsRoleAndPermissions.java | 12 ++-
 .../IsisExtSecmanAdminRoleAndPermissions.java      |  7 +-
 .../IsisExtSecmanFixtureRoleAndPermissions.java    |  7 +-
 ...IsisExtSecmanRegularUserRoleAndPermissions.java | 88 +++++++++-----------
 .../applib/fixturescripts/FixtureResult.java       |  4 +-
 12 files changed, 145 insertions(+), 279 deletions(-)

diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/logout/LogoutMenu.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/logout/LogoutMenu.java
index 4d0d804..03db925 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/logout/LogoutMenu.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/logout/LogoutMenu.java
@@ -43,12 +43,14 @@ import org.apache.isis.core.security.authentication.AuthenticationContext;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
-@Named("isis.security.LogoutMenu")
-@DomainService(objectType = "isis.security.LogoutMenu")
+@Named(LogoutMenu.OBJECT_TYPE)
+@DomainService(objectType = LogoutMenu.OBJECT_TYPE)
 @DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.TERTIARY)
 @RequiredArgsConstructor(onConstructor_ = {@Inject})
 public class LogoutMenu {
 
+    public static final String OBJECT_TYPE = "isis.security.LogoutMenu"; // referenced by secman seeding
+    
     private final List<LogoutHandler> logoutHandler;
     private final AuthenticationContext authenticationTracker;
     private final IsisConfiguration configuration;
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
index 6f60896..4e5ad4a 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
@@ -18,17 +18,10 @@
  */
 package org.apache.isis.extensions.secman.jdo.seed.scripts;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
 import javax.inject.Inject;
 
-import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
@@ -42,7 +35,6 @@ public abstract class AbstractRoleAndPermissionsFixtureScript extends FixtureScr
 
     @Inject private ApplicationRoleRepository applicationRoleRepository;
     @Inject private ApplicationPermissionRepository applicationPermissionRepository;
-    @Inject private SpecificationLoader specificationLoader;
     
     private final String roleName;
     private final String roleDescription;
@@ -55,60 +47,22 @@ public abstract class AbstractRoleAndPermissionsFixtureScript extends FixtureScr
     }
 
     /**
-     * Subclasses should override and call any of
-     * {@link #newPackagePermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, String...)},
-     * {@link #newClassPermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, Class[])} or
-     * {@link #newMemberPermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, Class, String...)}.
+     * Subclasses should override and call
+     * {@link #newPermissions(ApplicationPermissionRule, ApplicationPermissionMode, Can)}
      */
     @Override
     protected abstract void execute(ExecutionContext executionContext);
 
-    // -- newPackagePermissions, newClassPermissions, newMemberPermissions
-
-    /**
-     * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
-     */
-    protected void newPackagePermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final String... featureFqns) {
-
-        newPermissions(rule, mode, ApplicationFeatureSort.NAMESPACE, Arrays.asList(featureFqns));
-    }
-
-    /**
-     * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
-     */
-    protected void newClassPermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final Class<?>... classes) {
-
-        newPermissions(rule, mode, ApplicationFeatureSort.TYPE, asFeatureFqns(classes));
-    }
-
-
     /**
      * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
      */
-    protected void newMemberPermissions(
+    protected void newPermissions(
             final ApplicationPermissionRule rule,
             final ApplicationPermissionMode mode,
-            final Class<?> cls,
-            final String... members) {
-        newPermissions(rule, mode, ApplicationFeatureSort.MEMBER, asFeatureFqns(cls, members));
-    }
-
-
-    // -- helpers
+            final Can<ApplicationFeatureId> featureIds) {
 
-    private void newPermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final ApplicationFeatureSort featureSort,
-            final Iterable<String> featureFqns) {
-
-        if(featureFqns == null) {
+        if(featureIds == null
+                || featureIds.isEmpty()) {
             return;
         }
 
@@ -116,45 +70,22 @@ public abstract class AbstractRoleAndPermissionsFixtureScript extends FixtureScr
         if(securityRole == null) {
             securityRole = applicationRoleRepository.newRole(roleName, roleDescription);
         }
-        for (String featureFqn : featureFqns) {
+        
+        for(ApplicationFeatureId featureId : featureIds) {
+            val featureFqn = featureId.getFullyQualifiedName();
+
             // can't use role#addPackage because that does a check for existence of the package, which is
             // not guaranteed to exist yet (the SecurityFeatures#init() may not have run).
-
             ((org.apache.isis.extensions.secman.jdo.dom.permission.ApplicationPermissionRepository)
                     applicationPermissionRepository)
             .newPermissionNoCheck(
                     (org.apache.isis.extensions.secman.jdo.dom.role.ApplicationRole)securityRole,
                     rule,
                     mode,
-                    featureSort, featureFqn);
+                    featureId.getSort(), 
+                    featureFqn);
         }
     }
-    
-    private String asFeatureFqns(Class<?> cls) {
-        return Optional.ofNullable(specificationLoader.loadSpecification(cls))
-                .map(ObjectSpecification::getLogicalTypeName)
-                .orElseGet(()->cls.getName());
-    }
-
-    private List<String> asFeatureFqns(Class<?>[] classes) {
-        return _NullSafe.stream(classes)
-                .map(this::asFeatureFqns)
-                .collect(Collectors.toList());
-    }
-
-    private Iterable<String> asFeatureFqns(final Class<?> cls, final String[] members) {
-        return _NullSafe.stream(members)
-                .map(memberName->{
-                    val buf = new StringBuilder(asFeatureFqns(cls));
-                    if(!memberName.startsWith("#")) {
-                        buf.append("#");
-                    }
-                    buf.append(memberName);
-                    return buf.toString();
-                })
-                .collect(Collectors.toList());
-    }
-
 
 
 }
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
index 4bc5012..303d336 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
@@ -19,13 +19,16 @@
 package org.apache.isis.extensions.secman.jdo.seed.scripts;
 
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureResult;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 
 /**
  * @since 2.0 {@index}
  */
-public class IsisExtFixturesFixtureResultsRoleAndPermissions extends AbstractRoleAndPermissionsFixtureScript {
+public class IsisExtFixturesFixtureResultsRoleAndPermissions 
+extends AbstractRoleAndPermissionsFixtureScript {
 
     public static final String ROLE_NAME = "isis-ext-fixtures-fixtureresults";
 
@@ -35,9 +38,10 @@ public class IsisExtFixturesFixtureResultsRoleAndPermissions extends AbstractRol
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newClassPermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                FixtureResult.class);
+                Can.ofSingleton(
+                        ApplicationFeatureId.newType(FixtureResult.OBJECT_TYPE)));
     }
 }
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
index 3285d50..715c42b 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.secman.jdo.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
@@ -38,10 +40,11 @@ public class IsisExtSecmanAdminRoleAndPermissions extends AbstractRoleAndPermiss
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newPackagePermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                adminInitialPackagePermissions);
+                Can.ofArray(adminInitialPackagePermissions)
+                    .map(ApplicationFeatureId::newNamespace));
     }
 
 }
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
index 8bf6a6f..8980772 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.secman.jdo.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
@@ -35,9 +37,11 @@ public class IsisExtSecmanFixtureRoleAndPermissions extends AbstractRoleAndPermi
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newPackagePermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                "org.apache.isis.extensions.secman.jdo.fixture");
+                Can.ofSingleton(
+                        ApplicationFeatureId.newNamespace("isis.ext.secman")));
+                
     }
 }
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
index 2e05546..2cb99ed 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
@@ -18,13 +18,14 @@
  */
 package org.apache.isis.extensions.secman.jdo.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.security.authentication.logout.LogoutMenu;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
-import org.apache.isis.extensions.secman.jdo.dom.role.ApplicationRole;
-import org.apache.isis.extensions.secman.jdo.dom.user.ApplicationUser;
-import org.apache.isis.extensions.secman.model.dom.user.MeService;
+
+import lombok.val;
 
 /**
  * Role for regular users of the security module, providing the ability to lookup their user account using the
@@ -41,60 +42,45 @@ public class IsisExtSecmanRegularUserRoleAndPermissions extends AbstractRoleAndP
     @Override
     protected void execute(ExecutionContext executionContext) {
 
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.CHANGING,
-                LogoutMenu.class,
-                "logout");
-
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.CHANGING,
-                MeService.class,
-                "me");
-
-        newClassPermissions(
+        val allowViewing = Can.of(
+                ApplicationFeatureId.newType("isis.ext.secman.ApplicationUser"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationRole", "name"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationRole", "description")
+                );
+        
+        val allowChanging = Can.of(
+                ApplicationFeatureId.newMember(LogoutMenu.OBJECT_TYPE, "logout"),
+                ApplicationFeatureId.newMember("isis.ext.secman.MeService", "me"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateName"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updatePassword"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateEmailAddress"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updatePhoneNumber"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateFaxNumber")
+                );
+        
+        val vetoViewing = Can.of(
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "filterPermissions"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "resetPassword"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "lock"), // named 'enable' in the UI
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "unlock"), // named 'disable' in the UI
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "addRole"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "removeRoles")
+                );
+        
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.VIEWING,
-                ApplicationUser.class);
-
-        newMemberPermissions(
+                allowViewing);
+        
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                ApplicationUser.class,
-                "updateName",
-                "updatePassword",
-                "updateEmailAddress",
-                "updatePhoneNumber",
-                "updateFaxNumber");
-
-        newMemberPermissions(
+                allowChanging);
+        
+        newPermissions(
                 ApplicationPermissionRule.VETO,
                 ApplicationPermissionMode.VIEWING,
-                ApplicationUser.class,
-                "filterPermissions",
-                "resetPassword",
-                //"updateTenancy", // removed
-                "lock", // renamed as 'enable' in the UI
-                "unlock", // renamed as 'disable' in the UI
-                "addRole",
-                "removeRole");
-
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.VIEWING,
-                ApplicationRole.class,
-                "name",
-                "description");
-
-        //        // for adhoc testing of #42
-        //        newMemberPermissions(
-        //                ApplicationPermissionRule.ALLOW,
-        //                ApplicationPermissionMode.CHANGING,
-        //                ApplicationUser.class,
-        //                "orphanedUpdateEmailAddress",
-        //                "orphanedUpdatePhoneNumber",
-        //                "orphanedUpdateFaxNumber");
+                vetoViewing);
 
     }
 
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
index 19c3bf1..e1616e6 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
@@ -18,14 +18,10 @@
  */
 package org.apache.isis.extensions.secman.jpa.seed.scripts;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
 import javax.inject.Inject;
 
-import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
-import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
@@ -51,62 +47,22 @@ public abstract class AbstractRoleAndPermissionsFixtureScript extends FixtureScr
     }
 
     /**
-     * Subclasses should override and call any of
-     * {@link #newPackagePermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, String...)},
-     * {@link #newClassPermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, Class[])} or
-     * {@link #newMemberPermissions(org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule, org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode, Class, String...)}.
+     * Subclasses should override and call
+     * {@link #newPermissions(ApplicationPermissionRule, ApplicationPermissionMode, Can)}
      */
     @Override
     protected abstract void execute(ExecutionContext executionContext);
 
-    // -- newPackagePermissions, newClassPermissions, newMemberPermissions
-
-    /**
-     * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
-     */
-    protected void newPackagePermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final String... featureFqns) {
-
-        newPermissions(rule, mode, ApplicationFeatureSort.NAMESPACE, Arrays.asList(featureFqns));
-    }
-
     /**
      * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
      */
-    protected void newClassPermissions(
+    protected void newPermissions(
             final ApplicationPermissionRule rule,
             final ApplicationPermissionMode mode,
-            final Class<?>... classes) {
-
-        newPermissions(rule, mode, ApplicationFeatureSort.TYPE, asFeatureFqns(classes));
-    }
+            final Can<ApplicationFeatureId> featureIds) {
 
-
-    /**
-     * For subclasses to call in {@link #execute(FixtureScript.ExecutionContext)}.
-     */
-    protected void newMemberPermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final Class<?> cls,
-            final String... members) {
-        newPermissions(rule, mode, ApplicationFeatureSort.MEMBER, asFeatureFqns(cls, members));
-    }
-
-
-
-
-    // -- helpers
-
-    private void newPermissions(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final ApplicationFeatureSort featureSort,
-            final Iterable<String> featureFqns) {
-
-        if(featureFqns == null) {
+        if(featureIds == null
+                || featureIds.isEmpty()) {
             return;
         }
 
@@ -114,39 +70,21 @@ public abstract class AbstractRoleAndPermissionsFixtureScript extends FixtureScr
         if(securityRole == null) {
             securityRole = applicationRoleRepository.newRole(roleName, roleDescription);
         }
-        for (String featureFqn : featureFqns) {
+        
+        for(ApplicationFeatureId featureId : featureIds) {
+            val featureFqn = featureId.getFullyQualifiedName();
+
             // can't use role#addPackage because that does a check for existence of the package, which is
             // not guaranteed to exist yet (the SecurityFeatures#init() may not have run).
-
             ((org.apache.isis.extensions.secman.jpa.dom.permission.ApplicationPermissionRepository)
                     applicationPermissionRepository)
             .newPermissionNoCheck(
                     (org.apache.isis.extensions.secman.jpa.dom.role.ApplicationRole)securityRole,
                     rule,
                     mode,
-                    featureSort, featureFqn);
+                    featureId.getSort(), 
+                    featureFqn);
         }
     }
 
-    private static List<String> asFeatureFqns(Class<?>[] classes) {
-        return _NullSafe.stream(classes)
-                .map(Class::getName)
-                .collect(Collectors.toList());
-    }
-
-    private static Iterable<String> asFeatureFqns(final Class<?> cls, final String[] members) {
-        return _NullSafe.stream(members)
-                .map(memberName->{
-                    val buf = new StringBuilder(cls.getName());
-                    if(!memberName.startsWith("#")) {
-                        buf.append("#");
-                    }
-                    buf.append(memberName);
-                    return buf.toString();
-                })
-                .collect(Collectors.toList());
-    }
-
-
-
 }
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
index 35c6934..6ef9702 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtFixturesFixtureResultsRoleAndPermissions.java
@@ -18,14 +18,17 @@
  */
 package org.apache.isis.extensions.secman.jpa.seed.scripts;
 
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureResult;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
+import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureResult;
 
 /**
  * @since 2.0 {@index}
  */
-public class IsisExtFixturesFixtureResultsRoleAndPermissions extends AbstractRoleAndPermissionsFixtureScript {
+public class IsisExtFixturesFixtureResultsRoleAndPermissions 
+extends AbstractRoleAndPermissionsFixtureScript {
 
     public static final String ROLE_NAME = "isis-ext-fixtures-fixtureresults";
 
@@ -35,9 +38,10 @@ public class IsisExtFixturesFixtureResultsRoleAndPermissions extends AbstractRol
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newClassPermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                FixtureResult.class);
+                Can.ofSingleton(
+                        ApplicationFeatureId.newType(FixtureResult.OBJECT_TYPE)));
     }
 }
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
index fd80466..b3e168c 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanAdminRoleAndPermissions.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.secman.jpa.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
@@ -38,10 +40,11 @@ public class IsisExtSecmanAdminRoleAndPermissions extends AbstractRoleAndPermiss
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newPackagePermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                adminInitialPackagePermissions);
+                Can.ofArray(adminInitialPackagePermissions)
+                    .map(ApplicationFeatureId::newNamespace));
     }
 
 }
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
index 08092b2..cc7bd14 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanFixtureRoleAndPermissions.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.secman.jpa.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
@@ -35,9 +37,10 @@ public class IsisExtSecmanFixtureRoleAndPermissions extends AbstractRoleAndPermi
 
     @Override
     protected void execute(ExecutionContext executionContext) {
-        newPackagePermissions(
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                "org.apache.isis.extensions.secman.jdo.fixture");
+                Can.ofSingleton(
+                        ApplicationFeatureId.newNamespace("isis.ext.secman")));
     }
 }
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
index f25cdda..213f0d2 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/IsisExtSecmanRegularUserRoleAndPermissions.java
@@ -18,13 +18,14 @@
  */
 package org.apache.isis.extensions.secman.jpa.seed.scripts;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.security.authentication.logout.LogoutMenu;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
-import org.apache.isis.extensions.secman.jpa.dom.role.ApplicationRole;
-import org.apache.isis.extensions.secman.jpa.dom.user.ApplicationUser;
-import org.apache.isis.extensions.secman.model.dom.user.MeService;
+
+import lombok.val;
 
 /**
  * Role for regular users of the security module, providing the ability to lookup their user account using the
@@ -41,60 +42,45 @@ public class IsisExtSecmanRegularUserRoleAndPermissions extends AbstractRoleAndP
     @Override
     protected void execute(ExecutionContext executionContext) {
 
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.CHANGING,
-                LogoutMenu.class,
-                "logout");
-
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.CHANGING,
-                MeService.class,
-                "me");
-
-        newClassPermissions(
+        val allowViewing = Can.of(
+                ApplicationFeatureId.newType("isis.ext.secman.ApplicationUser"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationRole", "name"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationRole", "description")
+                );
+        
+        val allowChanging = Can.of(
+                ApplicationFeatureId.newMember(LogoutMenu.OBJECT_TYPE, "logout"),
+                ApplicationFeatureId.newMember("isis.ext.secman.MeService", "me"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateName"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updatePassword"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateEmailAddress"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updatePhoneNumber"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "updateFaxNumber")
+                );
+        
+        val vetoViewing = Can.of(
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "filterPermissions"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "resetPassword"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "lock"), // named 'enable' in the UI
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "unlock"), // named 'disable' in the UI
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "addRole"),
+                ApplicationFeatureId.newMember("isis.ext.secman.ApplicationUser", "removeRoles")
+                );
+        
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.VIEWING,
-                ApplicationUser.class);
-
-        newMemberPermissions(
+                allowViewing);
+        
+        newPermissions(
                 ApplicationPermissionRule.ALLOW,
                 ApplicationPermissionMode.CHANGING,
-                ApplicationUser.class,
-                "updateName",
-                "updatePassword",
-                "updateEmailAddress",
-                "updatePhoneNumber",
-                "updateFaxNumber");
-
-        newMemberPermissions(
+                allowChanging);
+        
+        newPermissions(
                 ApplicationPermissionRule.VETO,
                 ApplicationPermissionMode.VIEWING,
-                ApplicationUser.class,
-                "filterPermissions",
-                "resetPassword",
-                //"updateTenancy", // removed
-                "lock", // renamed as 'enable' in the UI
-                "unlock", // renamed as 'disable' in the UI
-                "addRole",
-                "removeRole");
-
-        newMemberPermissions(
-                ApplicationPermissionRule.ALLOW,
-                ApplicationPermissionMode.VIEWING,
-                ApplicationRole.class,
-                "name",
-                "description");
-
-        //        // for adhoc testing of #42
-        //        newMemberPermissions(
-        //                ApplicationPermissionRule.ALLOW,
-        //                ApplicationPermissionMode.CHANGING,
-        //                ApplicationUser.class,
-        //                "orphanedUpdateEmailAddress",
-        //                "orphanedUpdatePhoneNumber",
-        //                "orphanedUpdateFaxNumber");
+                vetoViewing);
 
     }
 
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/fixturescripts/FixtureResult.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/fixturescripts/FixtureResult.java
index 5269e70..e10eb42 100644
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/fixturescripts/FixtureResult.java
+++ b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/fixturescripts/FixtureResult.java
@@ -42,7 +42,7 @@ import lombok.Setter;
 
 @DomainObject(
         nature = Nature.VIEW_MODEL,
-        objectType = "isis.ext.fixtures.FixtureResult"
+        objectType = FixtureResult.OBJECT_TYPE
         )
 @DomainObjectLayout(paged=500)
 @XmlRootElement(name = "fixtureResult")
@@ -56,6 +56,8 @@ import lombok.Setter;
 )
 @XmlAccessorType(XmlAccessType.FIELD)
 public class FixtureResult {
+    
+    public static final String OBJECT_TYPE = "isis.ext.fixtures.FixtureResult"; // secman seeding
 
     @PropertyLayout(named="Fixture script")
     @Property(optionality = Optionality.OPTIONAL)