You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/05/28 06:43:24 UTC

[isis] branch ISIS-2700 created (now 19cedc2)

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

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


      at 19cedc2  ISIS-2700: sets up new facets to hide domain objects (and members to navigate those domain objects) if there are no permissions.

This branch includes the following new commits:

     new 253cf52  ISIS-2700: introduces HiddenTypeFacetDerivedFromAuthorization
     new 19cedc2  ISIS-2700: sets up new facets to hide domain objects (and members to navigate those domain objects) if there are no permissions.

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


[isis] 01/02: ISIS-2700: introduces HiddenTypeFacetDerivedFromAuthorization

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 253cf52aac5d5cb20b3506a52bf8575fb2181add
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu May 27 20:01:17 2021 +0100

    ISIS-2700: introduces HiddenTypeFacetDerivedFromAuthorization
---
 .../members/hiddenmember/HiddenMemberFacet.java    | 40 +++++++++++++
 ...enObjectFacet.java => HiddenInstanceFacet.java} | 12 +---
 .../facets/object/hidden/HiddenObjectFacet.java    | 17 +-----
 ...HiddenObjectFacet.java => HiddenTypeFacet.java} | 30 +---------
 .../HiddenTypeFacetDerivedFromAuthorization.java   | 67 ++++++++++++++++++++++
 ...nTypeFacetDerivedFromAuthorizationFactory.java} | 42 +++++---------
 .../hidden/method/HiddenObjectFacetViaMethod.java  |  2 +-
 .../dflt/ProgrammingModelFacetsJava8.java          |  3 +
 .../IsisModuleExtSecmanIntegration.java            |  1 -
 .../facets/TenantedAuthorizationPostProcessor.java |  2 -
 10 files changed, 129 insertions(+), 87 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java
new file mode 100644
index 0000000..e1e07ba
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.members.hiddenmember;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacetDerivedFromAuthorization;
+import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
+
+/**
+ * Hide a property, collection or action based <i>not</i> on the object
+ * instance itself, but at the &quot;type&quot; level, eg based on the
+ * permissions for the end-user accessing the object.
+ *
+ * <p>
+ * Used by {@link HiddenTypeFacetDerivedFromAuthorization}
+ * to determine if the type overall should be hidden from the end-user:
+ * if all members are hidden, then (all instanes of) the type should be also.
+ * </p>
+ */
+public interface HiddenMemberFacet extends Facet, HidingInteractionAdvisor {
+
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java
similarity index 80%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java
index 42c6e8f..8d34cbb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java
@@ -41,16 +41,6 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
  *
  * @see HiddenFacet
  */
-public interface HiddenObjectFacet extends Facet, HidingInteractionAdvisor {
-
-    /**
-     * Clone this facet onto another {@link FacetHolder}.
-     *
-     * <p>
-     * Introduced to allow this facet to be installed onto the
-     * {@link ObjectSpecification}, and then copied down onto each of the spec's
-     * {@link ObjectMember}s.
-     */
-    public void copyOnto(FacetHolder holder);
+public interface HiddenInstanceFacet extends Facet, HidingInteractionAdvisor {
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
index 42c6e8f..54ca733 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
@@ -26,22 +26,7 @@ import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
-/**
- * Mechanism for determining whether this object is should be hidden.
- *
- * <p>
- * Even though all the properties of an object may themselves be visible, there
- * could be reasons to hide the object.
- * </p>
- *
- * <p>
- * In the standard Apache Isis Programming Model, typically corresponds to the
- * <tt>hidden</tt> method.
- * </p>
- *
- * @see HiddenFacet
- */
-public interface HiddenObjectFacet extends Facet, HidingInteractionAdvisor {
+public interface HiddenObjectFacet extends HiddenInstanceFacet {
 
     /**
      * Clone this facet onto another {@link FacetHolder}.
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacet.java
similarity index 53%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacet.java
index 42c6e8f..5349e23 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacet.java
@@ -19,38 +19,10 @@
 
 package org.apache.isis.core.metamodel.facets.object.hidden;
 
-import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
-import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
-/**
- * Mechanism for determining whether this object is should be hidden.
- *
- * <p>
- * Even though all the properties of an object may themselves be visible, there
- * could be reasons to hide the object.
- * </p>
- *
- * <p>
- * In the standard Apache Isis Programming Model, typically corresponds to the
- * <tt>hidden</tt> method.
- * </p>
- *
- * @see HiddenFacet
- */
-public interface HiddenObjectFacet extends Facet, HidingInteractionAdvisor {
-
-    /**
-     * Clone this facet onto another {@link FacetHolder}.
-     *
-     * <p>
-     * Introduced to allow this facet to be installed onto the
-     * {@link ObjectSpecification}, and then copied down onto each of the spec's
-     * {@link ObjectMember}s.
-     */
-    public void copyOnto(FacetHolder holder);
+public interface HiddenTypeFacet extends HiddenInstanceFacet {
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
new file mode 100644
index 0000000..6744444
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.object.hidden;
+
+import java.util.function.BinaryOperator;
+
+import org.apache.isis.applib.services.metamodel.BeanSort;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.members.hiddenmember.HiddenMemberFacet;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
+import org.apache.isis.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.MixedIn;
+
+import lombok.val;
+
+public class HiddenTypeFacetDerivedFromAuthorization extends FacetAbstract implements HiddenTypeFacet {
+
+    public static Class<? extends Facet> type() {
+        return HiddenTypeFacet.class;
+    }
+
+    public HiddenTypeFacetDerivedFromAuthorization(final FacetHolder holder) {
+        super(type(), holder, Derivation.NOT_DERIVED);
+    }
+
+    @Override
+    public String hides(final VisibilityContext ic) {
+        val obj = ic.getTarget();
+        val specification = obj.getSpecification();
+        val beanSort = specification.getBeanSort();
+        switch (beanSort) {
+            case VIEW_MODEL:
+            case ENTITY:
+                final boolean allHidden = specification.streamAssociations(MixedIn.INCLUDED)
+                        .map(x -> {
+                            final AuthorizationFacet facet = x.getFacet(AuthorizationFacet.class);
+                            return facet != null && facet.hides(ic) != null;
+                        })
+                        .reduce(true, (prev, next) -> prev && next);
+                return allHidden ? "all members hidden" : null;
+            default:
+                return null;
+        }
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorizationFactory.java
similarity index 50%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorizationFactory.java
index 42c6e8f..3e9890e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenObjectFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorizationFactory.java
@@ -19,38 +19,26 @@
 
 package org.apache.isis.core.metamodel.facets.object.hidden;
 
-import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
-import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
 /**
- * Mechanism for determining whether this object is should be hidden.
- *
- * <p>
- * Even though all the properties of an object may themselves be visible, there
- * could be reasons to hide the object.
- * </p>
- *
- * <p>
- * In the standard Apache Isis Programming Model, typically corresponds to the
- * <tt>hidden</tt> method.
- * </p>
- *
- * @see HiddenFacet
+ * Installs the {@link HiddenTypeFacetDerivedFromAuthorization} on the
+ * {@link ObjectSpecification}.
  */
-public interface HiddenObjectFacet extends Facet, HidingInteractionAdvisor {
+public class HiddenTypeFacetDerivedFromAuthorizationFactory extends FacetFactoryAbstract {
+
+    public HiddenTypeFacetDerivedFromAuthorizationFactory() {
+        super(FeatureType.OBJECTS_ONLY);
+    }
 
-    /**
-     * Clone this facet onto another {@link FacetHolder}.
-     *
-     * <p>
-     * Introduced to allow this facet to be installed onto the
-     * {@link ObjectSpecification}, and then copied down onto each of the spec's
-     * {@link ObjectMember}s.
-     */
-    public void copyOnto(FacetHolder holder);
+    @Override
+    public void process(final ProcessClassContext processClassContext) {
+        final FacetHolder facetHolder = processClassContext.getFacetHolder();
+        FacetUtil.addFacet(new HiddenTypeFacetDerivedFromAuthorization(facetHolder));
+    }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java
index 98eb12b..55b2951 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java
@@ -51,7 +51,7 @@ extends HiddenObjectFacetAbstract {
             return null;
         }
         final Boolean isHidden = (Boolean) ManagedObjects.InvokeUtil.invoke(method, target);
-        return isHidden.booleanValue() ? "Hidden" : null;
+        return isHidden ? "Hidden" : null;
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
index aef4b28..fc6d00b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
@@ -59,6 +59,7 @@ import org.apache.isis.core.metamodel.facets.object.domainservice.annotation.Dom
 import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.facets.annotation.FacetsFacetAnnotationFactory;
 import org.apache.isis.core.metamodel.facets.object.grid.GridFacetFactory;
+import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacetDerivedFromAuthorizationFactory;
 import org.apache.isis.core.metamodel.facets.object.hidden.method.HiddenObjectFacetViaMethodFactory;
 import org.apache.isis.core.metamodel.facets.object.icon.method.IconFacetMethodFactory;
 import org.apache.isis.core.metamodel.facets.object.ignore.annotation.RemoveAnnotatedMethodsFacetFactory;
@@ -347,6 +348,8 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, OffsetDateTimeValueFacetUsingSemanticsProviderFactory.class);
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, ZonedDateTimeValueFacetUsingSemanticsProviderFactory.class);
 
+        addFactory(FacetProcessingOrder.Z0_BEFORE_FINALLY, HiddenTypeFacetDerivedFromAuthorizationFactory.class);
+
         // written to not trample over TypeOf if already installed
         addFactory(FacetProcessingOrder.Z1_FINALLY, CollectionFacetFactory.class);
         // must come after CollectionFacetFactory
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
index f48b694..23eb2a8 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/IsisModuleExtSecmanIntegration.java
@@ -24,7 +24,6 @@ import org.springframework.context.annotation.Import;
 import org.apache.isis.extensions.secman.applib.IsisModuleExtSecmanApplib;
 import org.apache.isis.extensions.secman.integration.authorizor.AuthorizorSecman;
 import org.apache.isis.extensions.secman.integration.facets.TenantedAuthorizationPostProcessor;
-import org.apache.isis.extensions.secman.applib.seed.SeedSecurityModuleService;
 import org.apache.isis.extensions.secman.integration.spiimpl.ImpersonateMenuAdvisorForSecman;
 import org.apache.isis.extensions.secman.integration.spiimpl.TableColumnVisibilityServiceForSecman;
 import org.apache.isis.extensions.secman.integration.userreg.UserRegistrationServiceForSecman;
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java
index f4b6fdf..993e1ae 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/isis/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java
@@ -26,7 +26,6 @@ import javax.inject.Provider;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 
-import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.applib.services.user.UserService;
@@ -107,7 +106,6 @@ public class TenantedAuthorizationPostProcessor
     }
 
     @Inject ServiceRegistry serviceRegistry;
-    @Inject ServiceInjector serviceInjector;
     @Inject UserService userService;
     @Inject @Lazy ApplicationUserRepository userRepository;
     @Inject Provider<QueryResultsCache> queryResultsCacheProvider;

[isis] 02/02: ISIS-2700: sets up new facets to hide domain objects (and members to navigate those domain objects) if there are no permissions.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 19cedc2c77cb10255af625b6a9e14ff918183a25
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri May 28 07:42:19 2021 +0100

    ISIS-2700: sets up new facets to hide domain objects (and members to navigate those domain objects) if there are no permissions.
---
 .../NavigationFacet.java}                          | 24 ++++-----
 .../HiddenTypeFacetDerivedFromAuthorization.java   | 54 ++++++++++++++-----
 ...NavigationFacetFromHiddenTypePostProcessor.java | 63 ++++++++++++++++++++++
 .../NavigationFacetDerivedFromHiddenType.java}     | 47 ++++++++--------
 .../dflt/ProgrammingModelFacetsJava8.java          |  5 +-
 .../executor/MemberExecutorServiceDefault.java     |  2 +-
 ...onOrphanedPermissionManager.layout.fallback.xml | 46 ++++++++++++++++
 ...IsisExtSecmanRegularUserRoleAndPermissions.java |  4 +-
 8 files changed, 191 insertions(+), 54 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/navigation/NavigationFacet.java
similarity index 60%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java
rename to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/navigation/NavigationFacet.java
index e1e07ba..eedbc83 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hiddenmember/HiddenMemberFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/navigation/NavigationFacet.java
@@ -17,24 +17,24 @@
  *  under the License.
  */
 
-package org.apache.isis.core.metamodel.facets.members.hiddenmember;
+package org.apache.isis.core.metamodel.facets.members.navigation;
 
 import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacetDerivedFromAuthorization;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacet;
 import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
+import org.apache.isis.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationFacet;
+import org.apache.isis.core.metamodel.spec.feature.MixedIn;
+
+import lombok.val;
 
 /**
- * Hide a property, collection or action based <i>not</i> on the object
- * instance itself, but at the &quot;type&quot; level, eg based on the
- * permissions for the end-user accessing the object.
- *
- * <p>
- * Used by {@link HiddenTypeFacetDerivedFromAuthorization}
- * to determine if the type overall should be hidden from the end-user:
- * if all members are hidden, then (all instanes of) the type should be also.
- * </p>
+ * Hides object members that would allow navigation to a domain type that is
+ * {@link HiddenTypeFacet hidden} (typically due to security permissions).
  */
-public interface HiddenMemberFacet extends Facet, HidingInteractionAdvisor {
+public interface NavigationFacet extends Facet, HidingInteractionAdvisor {
 
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
index 6744444..d507dd3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
@@ -19,16 +19,14 @@
 
 package org.apache.isis.core.metamodel.facets.object.hidden;
 
-import java.util.function.BinaryOperator;
-
-import org.apache.isis.applib.services.metamodel.BeanSort;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.members.hiddenmember.HiddenMemberFacet;
+import org.apache.isis.core.metamodel.interactions.ActionVisibilityContext;
+import org.apache.isis.core.metamodel.interactions.CollectionVisibilityContext;
+import org.apache.isis.core.metamodel.interactions.PropertyVisibilityContext;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationFacet;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
 
@@ -41,24 +39,56 @@ public class HiddenTypeFacetDerivedFromAuthorization extends FacetAbstract imple
     }
 
     public HiddenTypeFacetDerivedFromAuthorization(final FacetHolder holder) {
-        super(type(), holder, Derivation.NOT_DERIVED);
+        super(type(), holder, Derivation.DERIVED);
     }
 
     @Override
-    public String hides(final VisibilityContext ic) {
-        val obj = ic.getTarget();
-        val specification = obj.getSpecification();
+    public String hides(final VisibilityContext vc) {
+        val specification = (ObjectSpecification) getFacetHolder();
         val beanSort = specification.getBeanSort();
         switch (beanSort) {
+            case ABSTRACT:
             case VIEW_MODEL:
             case ENTITY:
-                final boolean allHidden = specification.streamAssociations(MixedIn.INCLUDED)
+                val allPropsHidden = specification.streamProperties(MixedIn.INCLUDED)
+                        .map(x -> {
+                            final AuthorizationFacet facet = x.getFacet(AuthorizationFacet.class);
+                            val avc = new PropertyVisibilityContext(vc.getHead(), x.getIdentifier(), vc.getInitiatedBy(), vc.getWhere());
+                            return facet != null && facet.hides(avc) != null;
+                        })
+                        .reduce(true, (prev, next) -> prev && next);
+                if (!allPropsHidden) {
+                    return null;
+                }
+
+                val allCollsHidden = specification.streamCollections(MixedIn.INCLUDED)
                         .map(x -> {
                             final AuthorizationFacet facet = x.getFacet(AuthorizationFacet.class);
-                            return facet != null && facet.hides(ic) != null;
+                            val avc = new CollectionVisibilityContext(vc.getHead(), x.getIdentifier(), vc.getInitiatedBy(), vc.getWhere());
+                            return facet != null && facet.hides(avc) != null;
                         })
                         .reduce(true, (prev, next) -> prev && next);
-                return allHidden ? "all members hidden" : null;
+                if (!allCollsHidden) {
+                    return null;
+                }
+
+                //noinspection ConstantConditions
+                if (false) {
+                    // not sure that we need to check that all actions
+                    // are hidden before inferring that the type overall is hidden.
+                    val allActsHidden = specification.streamAnyActions(MixedIn.INCLUDED)
+                            .map(x -> {
+                                final AuthorizationFacet facet = x.getFacet(AuthorizationFacet.class);
+                                val avc = new ActionVisibilityContext(vc.getHead(), x, x.getIdentifier(), vc.getInitiatedBy(), vc.getWhere());
+                                return facet != null && facet.hides(avc) != null;
+                            })
+                            .reduce(true, (prev, next) -> prev && next);
+                    if (!allActsHidden) {
+                        return null;
+                    }
+                }
+
+                return "All properties and collections are hidden";
             default:
                 return null;
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/DeriveNavigationFacetFromHiddenTypePostProcessor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/DeriveNavigationFacetFromHiddenTypePostProcessor.java
new file mode 100644
index 0000000..83e1500
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/DeriveNavigationFacetFromHiddenTypePostProcessor.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.postprocessors.members.navigation;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacet;
+import org.apache.isis.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+/**
+ * Installs the {@link NavigationFacetDerivedFromHiddenType} on all of the
+ * {@link ObjectMember}s of the {@link ObjectSpecification}.
+ */
+public class DeriveNavigationFacetFromHiddenTypePostProcessor extends ObjectSpecificationPostProcessorAbstract {
+
+    @Override protected void doPostProcess(ObjectSpecification objectSpecification) {
+    }
+
+    @Override protected void doPostProcess(ObjectSpecification objectSpecification, ObjectAction act) {
+        addFacetIfRequired(act, act.getReturnType());
+    }
+
+    @Override protected void doPostProcess(ObjectSpecification objectSpecification, ObjectAction objectAction, ObjectActionParameter param) {
+    }
+
+    @Override protected void doPostProcess(ObjectSpecification objectSpecification, OneToOneAssociation prop) {
+        addFacetIfRequired(prop, prop.getSpecification());
+    }
+
+    @Override protected void doPostProcess(ObjectSpecification objectSpecification, OneToManyAssociation coll) {
+        addFacetIfRequired(coll, coll.getSpecification());
+    }
+
+    private static void addFacetIfRequired(FacetHolder facetHolder, ObjectSpecification navigatedType) {
+        if(navigatedType.containsNonFallbackFacet(HiddenTypeFacet.class)) {
+            FacetUtil.addFacet(new NavigationFacetDerivedFromHiddenType(facetHolder, navigatedType));
+        }
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/NavigationFacetDerivedFromHiddenType.java
similarity index 51%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/NavigationFacetDerivedFromHiddenType.java
index 6744444..61ecf7f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/hidden/HiddenTypeFacetDerivedFromAuthorization.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/members/navigation/NavigationFacetDerivedFromHiddenType.java
@@ -17,51 +17,48 @@
  *  under the License.
  */
 
-package org.apache.isis.core.metamodel.facets.object.hidden;
+package org.apache.isis.core.metamodel.postprocessors.members.navigation;
 
-import java.util.function.BinaryOperator;
-
-import org.apache.isis.applib.services.metamodel.BeanSort;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.members.hiddenmember.HiddenMemberFacet;
+import org.apache.isis.core.metamodel.facets.members.navigation.NavigationFacet;
+import org.apache.isis.core.metamodel.facets.object.hidden.HiddenTypeFacet;
+import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
+import org.apache.isis.core.metamodel.interactions.ObjectVisibilityContext;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationFacet;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
 
 import lombok.val;
 
-public class HiddenTypeFacetDerivedFromAuthorization extends FacetAbstract implements HiddenTypeFacet {
+public class NavigationFacetDerivedFromHiddenType extends FacetAbstract implements NavigationFacet {
+
+    private final ObjectSpecification navigatedType;
 
     public static Class<? extends Facet> type() {
-        return HiddenTypeFacet.class;
+        return NavigationFacet.class;
     }
 
-    public HiddenTypeFacetDerivedFromAuthorization(final FacetHolder holder) {
-        super(type(), holder, Derivation.NOT_DERIVED);
+    public NavigationFacetDerivedFromHiddenType(final FacetHolder holder, final ObjectSpecification navigatedType) {
+        super(type(), holder, Derivation.DERIVED);
+        this.navigatedType = navigatedType;
     }
 
     @Override
     public String hides(final VisibilityContext ic) {
-        val obj = ic.getTarget();
-        val specification = obj.getSpecification();
-        val beanSort = specification.getBeanSort();
-        switch (beanSort) {
-            case VIEW_MODEL:
-            case ENTITY:
-                final boolean allHidden = specification.streamAssociations(MixedIn.INCLUDED)
-                        .map(x -> {
-                            final AuthorizationFacet facet = x.getFacet(AuthorizationFacet.class);
-                            return facet != null && facet.hides(ic) != null;
-                        })
-                        .reduce(true, (prev, next) -> prev && next);
-                return allHidden ? "all members hidden" : null;
-            default:
-                return null;
+        val facet = navigatedType.getFacet(HiddenTypeFacet.class);
+        if(facet == null) {
+            // not expected to happen; this facet should only be installed for object members
+            // that navigate to a class that has the HiddenTypeFacet
+            return null;
         }
+        val ovc = new ObjectVisibilityContext(ic.getHead().getOwner(), Identifier.classIdentifier(navigatedType.getLogicalType()), ic.getInitiatedBy(), ic.getWhere());
+        final String hides = facet.hides(ovc);
+        return hides;
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
index fc6d00b..db74742 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
@@ -146,6 +146,7 @@ import org.apache.isis.core.metamodel.postprocessors.all.DeriveDescribedAsFromTy
 import org.apache.isis.core.metamodel.postprocessors.all.i18n.TranslationPostProcessor;
 import org.apache.isis.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationFacetPostProcessor;
 import org.apache.isis.core.metamodel.postprocessors.collparam.DeriveCollectionParamDefaultsAndChoicesPostProcessor;
+import org.apache.isis.core.metamodel.postprocessors.members.navigation.DeriveNavigationFacetFromHiddenTypePostProcessor;
 import org.apache.isis.core.metamodel.postprocessors.members.TweakDomainEventsForMixinPostProcessor;
 import org.apache.isis.core.metamodel.postprocessors.object.DeriveProjectionFacetsPostProcessor;
 import org.apache.isis.core.metamodel.postprocessors.properties.DeriveDisabledFromImmutablePostProcessor;
@@ -278,6 +279,7 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
         // must come after DomainObjectAnnotationFacetFactory & MixinFacetFactory
         addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, ContributingFacetDerivedFromMixinFacetFactory.class);
 
+        addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, HiddenTypeFacetDerivedFromAuthorizationFactory.class);
 
         addFactory(FacetProcessingOrder.F1_LAYOUT, GridFacetFactory.class);
 
@@ -348,8 +350,6 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, OffsetDateTimeValueFacetUsingSemanticsProviderFactory.class);
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, ZonedDateTimeValueFacetUsingSemanticsProviderFactory.class);
 
-        addFactory(FacetProcessingOrder.Z0_BEFORE_FINALLY, HiddenTypeFacetDerivedFromAuthorizationFactory.class);
-
         // written to not trample over TypeOf if already installed
         addFactory(FacetProcessingOrder.Z1_FINALLY, CollectionFacetFactory.class);
         // must come after CollectionFacetFactory
@@ -383,6 +383,7 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
         addPostProcessor(PostProcessingOrder.A1_BUILTIN, DeriveCollectionParamDefaultsAndChoicesPostProcessor.class);
         addPostProcessor(PostProcessingOrder.A1_BUILTIN, TweakDomainEventsForMixinPostProcessor.class);
         addPostProcessor(PostProcessingOrder.A1_BUILTIN, DeriveProjectionFacetsPostProcessor.class);
+        addPostProcessor(PostProcessingOrder.A1_BUILTIN, DeriveNavigationFacetFromHiddenTypePostProcessor.class);
 
         // must be after all named facets and description facets have been installed
         addPostProcessor(PostProcessingOrder.A1_BUILTIN, TranslationPostProcessor.class);
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
index 99d0358..979023e 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
@@ -260,7 +260,7 @@ implements MemberExecutorService {
         }
 
         val entityState = ManagedObjects.EntityUtil.getEntityState(resultAdapter);
-        if(entityState.isDetached()) {
+        if(entityState.isDetached())   {
             // ensure that any still-to-be-persisted adapters get persisted to DB.
             getTransactionService().flushTransaction();
         }
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/app/ApplicationOrphanedPermissionManager.layout.fallback.xml b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/app/ApplicationOrphanedPermissionManager.layout.fallback.xml
new file mode 100644
index 0000000..736e807
--- /dev/null
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/permission/app/ApplicationOrphanedPermissionManager.layout.fallback.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+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.
+-->
+<bs3:grid
+        xsi:schemaLocation="http://isis.apache.org/applib/layout/component http://isis.apache.org/applib/layout/component/component.xsd   http://isis.apache.org/applib/layout/grid/bootstrap3 http://isis.apache.org/applib/layout/grid/bootstrap3/bootstrap3.xsd"
+        xmlns:bs3="http://isis.apache.org/applib/layout/grid/bootstrap3"
+        xmlns:cpt="http://isis.apache.org/applib/layout/component"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <bs3:row>
+        <bs3:col span="12" unreferencedActions="true">
+            <cpt:domainObject/>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="12">
+            <cpt:collection id="orphanedCollections"/>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="12">
+            <bs3:tabGroup unreferencedCollections="true"/>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="12">
+            <cpt:fieldSet name="Metadata" id="metadata"/>
+            <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
+        </bs3:col>
+    </bs3:row>
+</bs3:grid>
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 34cf4f6..e1c5d2f 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
@@ -104,8 +104,8 @@ public class IsisExtSecmanRegularUserRoleAndPermissions extends AbstractRoleAndP
         val vetoViewing = Can.of(
                 // we explicitly ensure that the user cannot grant themselves
                 // additional privileges or see stuff that they shouldn't
-                ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "permissions"),
-                ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "filterPermissions"),
+                ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "effectiveMemberPermissions"),
+                ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "filterEffectiveMemberPermissions"),
                 ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "resetPassword"),
                 ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "lock"),
                 ApplicationFeatureId.newMember(ApplicationUser.LOGICAL_TYPE_NAME, "unlock"),