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

danhaywood pushed a commit to branch CAUSEWAY-3524
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 3f660e3c77cfb38dcdf228307e1048d367acd7e2
Author: danhaywood <[email protected]>
AuthorDate: Sat Jul 8 17:51:44 2023 +0100

    CAUSEWAY-3524: adds tests for PermissionsEvaluationServiceForSecman
    
    with regular nd with v1 compatible impls of ApplicationFeatureIdTransformer
---
 .../services/appfeat/ApplicationFeatureId.java     |  46 ++++++-
 .../permission/dom/ApplicationPermissionValue.java |   1 -
 .../PermissionsEvaluationServiceForSecman.java     |  19 +++
 ...icationFeatureIdTransformerV1Compatibility.java |  34 +++---
 ...onFeatureIdTransformerV1Compatibility_Test.java |  40 +++++-
 ...EvaluationServiceForSecmanV1_evaluate_Test.java | 136 +++++++++++++++++++++
 ...nsEvaluationServiceForSecman_evaluate_Test.java | 125 +++++++++++++++++++
 7 files changed, 380 insertions(+), 21 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureId.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureId.java
index b1432099c0..b80aaf2b5c 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureId.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureId.java
@@ -243,18 +243,29 @@ implements
     @Programmatic
     @Getter private String namespace;
 
+    /**
+     * The type name, eg &quot;Customer&quot;.
+     *
+     * <p>
+     * Will be {@code null} if this feature is a {@link 
ApplicationFeatureSort#NAMESPACE namespace}.
+     * </p>
+     */
     @Programmatic
     @Getter private String typeSimpleName;
 
     /**
      * Logical (simple) name of the member (in case of actions not including 
the parameter list).
-     * Consequently method overloading is not supported.
+     * (This works because method overloading of actions is not supported by 
the framework).
+     *
      * <p>
      * If there is a member name clash involving an <i>action</i> and an 
<i>association</i>,
      * then consequently any permissions defined automatically apply to both 
and one cannot separate
      * these.
+     * </p>
+     *
      * <p>
-     * {@code null} if not a member
+     * Will be {@code null} if this feature is not a {@link 
ApplicationFeatureSort#MEMBER member}.
+     * </p>
      */
     @Programmatic
     @Getter private String logicalMemberName;
@@ -450,4 +461,35 @@ implements
         return newFeature(namespace, this.getTypeSimpleName(), 
this.getLogicalMemberName());
     }
 
+    /**
+     * Returns a new instance that is a clone of this feature (expected to be a
+     * {@link ApplicationFeatureSort#MEMBER member} or {@link 
ApplicationFeatureSort#TYPE type}), but with the
+     * logicalTypeName taken from the argument.
+     *
+     * <p>
+     *     If this feature is instead a {@link 
ApplicationFeatureSort#NAMESPACE namespace} then the feature is
+     *     returned unchanged.
+     * </p>
+     *
+     * <p>
+     *     Note: if the feature is a {@link ApplicationFeatureSort#TYPE type}, 
then this method will be the same as
+     *     if {@link ApplicationFeatureId#newType(String)} had been used to 
create a new instance.  The method exists
+     *     though to provide a standardized way of transforming {@link 
ApplicationFeatureId}s where possible, without
+     *     the caller having to worry as to what {@link #getSort() sort} of 
feature it is dealing with.
+     * </p>
+     *
+     * @param logicalTypeName
+     */
+    public ApplicationFeatureId withLogicalTypeName(final @NonNull String 
logicalTypeName) {
+        switch (getSort()) {
+            case MEMBER:
+                return newMember(logicalTypeName, this.getLogicalMemberName());
+            case TYPE:
+                return newType(logicalTypeName);
+            case NAMESPACE:
+            default:
+                return this;
+        }
+    }
+
 }
diff --git 
a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
 
b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
index 77ed07c631..54a3b2a514 100644
--- 
a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
+++ 
b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
@@ -51,7 +51,6 @@ public class ApplicationPermissionValue implements 
Comparable<ApplicationPermiss
         this.mode = mode;
     }
 
-
     // -- featureId
     private final ApplicationFeatureId featureId;
     @Programmatic
diff --git 
a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
 
b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
index b0a6adb8bb..35c56b43d6 100644
--- 
a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
+++ 
b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
@@ -26,6 +26,9 @@ import java.util.Optional;
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
@@ -62,6 +65,22 @@ implements PermissionsEvaluationService {
 
     private final @NonNull PermissionsEvaluationPolicy policy; // serializable
 
+    /**
+     * for testing only
+     *
+     * @param policy
+     * @param applicationFeatureIdTransformer
+     */
+    @Builder
+    private PermissionsEvaluationServiceForSecman(
+            PermissionsEvaluationPolicy policy,
+            ApplicationFeatureIdTransformer applicationFeatureIdTransformer
+    ) {
+        this.policy = policy;
+        this.applicationFeatureIdTransformer = applicationFeatureIdTransformer;
+    }
+
+
     @Inject
     public PermissionsEvaluationServiceForSecman(final CausewayConfiguration 
causewayConfiguration) {
         this.policy = Optional.ofNullable(
diff --git 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility.java
 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility.java
index debde0dad2..403607ef8b 100644
--- 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility.java
+++ 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility.java
@@ -18,23 +18,18 @@
  */
 package org.apache.causeway.extensions.secman.integration.permissions;
 
-import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 import lombok.RequiredArgsConstructor;
 
-import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
+import lombok.val;
 
-import org.springframework.beans.factory.annotation.Qualifier;
-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.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
 
-import org.apache.causeway.applib.annotation.PriorityPrecedence;
 import org.apache.causeway.applib.annotation.Programmatic;
 import org.apache.causeway.applib.services.appfeat.ApplicationFeatureId;
-import 
org.apache.causeway.extensions.secman.applib.CausewayModuleExtSecmanApplib;
-import 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValue;
 
 import javax.inject.Inject;
 
@@ -44,16 +39,25 @@ public class ApplicationFeatureIdTransformerV1Compatibility 
implements Applicati
 
     private final SpecificationLoader specificationLoader;
 
+    /**
+     * local cache.
+     */
+    private final Map<ApplicationFeatureId, ApplicationFeatureId> 
transformedByOriginal = new HashMap<>();
+
     @Programmatic
     @Override
     public ApplicationFeatureId transform(ApplicationFeatureId 
applicationFeatureId) {
-        return applicationFeatureId;
+        return transformedByOriginal.computeIfAbsent(applicationFeatureId, 
this::doTransform);
     }
 
-    @Programmatic
-    @Override
-    public Collection<ApplicationPermissionValue> 
transform(Collection<ApplicationPermissionValue> permissionValues) {
-        return permissionValues;
+    private ApplicationFeatureId doTransform(ApplicationFeatureId 
applicationFeatureId) {
+        val logicalTypeName = applicationFeatureId.getLogicalTypeName();
+        val logicalTypeNameBasedOnPhysicalName =
+                specificationLoader.specForLogicalTypeName(logicalTypeName)
+                .map(ObjectSpecification::getCorrespondingClass)
+                .map(Class::getName)
+                .orElse(logicalTypeName);
+        return 
applicationFeatureId.withLogicalTypeName(logicalTypeNameBasedOnPhysicalName);
     }
 
 }
diff --git 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility_Test.java
 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility_Test.java
index eae7ce4454..fb15280fd8 100644
--- 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility_Test.java
+++ 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformerV1Compatibility_Test.java
@@ -2,6 +2,7 @@ package 
org.apache.causeway.extensions.secman.integration.permissions;
 
 import org.apache.causeway.applib.services.appfeat.ApplicationFeatureId;
 
+import org.apache.causeway.applib.services.appfeat.ApplicationFeatureSort;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
 
@@ -37,11 +38,44 @@ class ApplicationFeatureIdTransformerV1Compatibility_Test {
     }
 
     @Test
-    void happy_case() {
+    void member_when_its_owning_type_exists() {
         ApplicationFeatureId input = 
ApplicationFeatureId.newMember("customer.Customer", "lastName");
-        ApplicationFeatureId transform = transformer.transform(input);
+        ApplicationFeatureId transformed = transformer.transform(input);
 
-        
assertThat(transform.getLogicalTypeName()).isEqualTo(Customer.class.getName());
+        
assertThat(transformed.getSort()).isEqualTo(ApplicationFeatureSort.MEMBER);
+        
assertThat(transformed.getLogicalTypeName()).isEqualTo(Customer.class.getName());
+        assertThat(transformed.getLogicalMemberName()).isEqualTo("lastName");
+    }
+
+    @Test
+    void member_when_its_owning_type_does_not_exist() {
+        ApplicationFeatureId input = 
ApplicationFeatureId.newMember("order.Order", "placedOn");
+        ApplicationFeatureId transformed = transformer.transform(input);
+
+        
assertThat(transformed.getSort()).isEqualTo(ApplicationFeatureSort.MEMBER);
+        assertThat(transformed.getLogicalTypeName()).isEqualTo("order.Order");
+        assertThat(transformed.getLogicalMemberName()).isEqualTo("placedOn");
+    }
+
+    @Test
+    void type_when_exists() {
+        ApplicationFeatureId input = 
ApplicationFeatureId.newType("customer.Customer");
+        ApplicationFeatureId transformed = transformer.transform(input);
+
+        
assertThat(transformed.getSort()).isEqualTo(ApplicationFeatureSort.TYPE);
+        
assertThat(transformed.getLogicalTypeName()).isEqualTo(Customer.class.getName());
+        assertThat(transformed.getLogicalMemberName()).isNull();
+    }
+
+
+    @Test
+    void type_when_does_not_exist() {
+        ApplicationFeatureId input = 
ApplicationFeatureId.newType("order.Order");
+        ApplicationFeatureId transformed = transformer.transform(input);
+
+        
assertThat(transformed.getSort()).isEqualTo(ApplicationFeatureSort.TYPE);
+        assertThat(transformed.getLogicalTypeName()).isEqualTo("order.Order");
+        assertThat(transformed.getLogicalMemberName()).isNull();
     }
 
 }
\ No newline at end of file
diff --git 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecmanV1_evaluate_Test.java
 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecmanV1_evaluate_Test.java
new file mode 100644
index 0000000000..f2e311fda9
--- /dev/null
+++ 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecmanV1_evaluate_Test.java
@@ -0,0 +1,136 @@
+package org.apache.causeway.extensions.secman.integration.permissions;
+
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
+import 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValue;
+import 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValueSet;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+import java.util.Optional;
+
+import static 
org.apache.causeway.applib.services.appfeat.ApplicationFeatureId.*;
+import static 
org.apache.causeway.core.config.CausewayConfiguration.Extensions.Secman.PermissionsEvaluationPolicy.ALLOW_BEATS_VETO;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionMode.CHANGING;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionMode.VIEWING;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionRule.ALLOW;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionRule.VETO;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.lenient;
+
+@ExtendWith(MockitoExtension.class)
+class PermissionsEvaluationServiceForSecmanV1_evaluate_Test {
+
+    static class Customer {}
+
+    @Mock SpecificationLoader mockSpecificationLoader;
+    @Mock ObjectSpecification mockSpecificationForCustomerClass;
+
+    PermissionsEvaluationServiceForSecman evaluator;
+    ApplicationFeatureIdTransformer applicationFeatureIdTransformer;
+
+    @BeforeEach
+    void setup() {
+        applicationFeatureIdTransformer = new 
ApplicationFeatureIdTransformerV1Compatibility(mockSpecificationLoader);
+
+        
lenient().when(mockSpecificationLoader.specForLogicalTypeName("customer.Customer")).thenReturn(Optional.of(mockSpecificationForCustomerClass));
+        
lenient().when(mockSpecificationForCustomerClass.getCorrespondingClass()).then(__
 -> ApplicationFeatureIdTransformerV1Compatibility_Test.Customer.class);
+
+        evaluator = PermissionsEvaluationServiceForSecman.builder()
+                
.applicationFeatureIdTransformer(applicationFeatureIdTransformer)
+                .policy(ALLOW_BEATS_VETO)
+                .build();
+    }
+
+    @Test
+    void granted_viewing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void granted_viewing_via_namespace_changing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, CHANGING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void no_opinion_changing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                CHANGING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate).isNull();
+    }
+
+    @Test
+    void granted_changing_via_namespace_changing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                CHANGING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, CHANGING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void granted_viewing_via_type() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new 
ApplicationPermissionValue(newType("customer.Customer"), ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void veto_viewing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                        new 
ApplicationPermissionValue(newNamespace("customer"), VETO, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isFalse();
+    }
+
+    @Test
+    void 
granted_viewing_when_namespace_veto_viewing_overridden_by_type_allowing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                        new 
ApplicationPermissionValue(newNamespace("customer"), VETO, VIEWING),
+                        new 
ApplicationPermissionValue(newNamespace("customer.Customer"), ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isFalse();
+    }
+
+}
\ No newline at end of file
diff --git 
a/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman_evaluate_Test.java
 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman_evaluate_Test.java
new file mode 100644
index 0000000000..a5b00e4c15
--- /dev/null
+++ 
b/extensions/security/secman/integration/src/test/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman_evaluate_Test.java
@@ -0,0 +1,125 @@
+package org.apache.causeway.extensions.secman.integration.permissions;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValue;
+import 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValueSet;
+
+import static 
org.apache.causeway.applib.services.appfeat.ApplicationFeatureId.newMember;
+import static 
org.apache.causeway.applib.services.appfeat.ApplicationFeatureId.newNamespace;
+import static 
org.apache.causeway.applib.services.appfeat.ApplicationFeatureId.newType;
+import static 
org.apache.causeway.core.config.CausewayConfiguration.Extensions.Secman.PermissionsEvaluationPolicy.ALLOW_BEATS_VETO;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionMode.CHANGING;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionMode.VIEWING;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionRule.ALLOW;
+import static 
org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionRule.VETO;
+
+@ExtendWith(MockitoExtension.class)
+class PermissionsEvaluationServiceForSecman_evaluate_Test {
+
+    PermissionsEvaluationServiceForSecman evaluator;
+    ApplicationFeatureIdTransformer applicationFeatureIdTransformer;
+
+    @BeforeEach
+    void setup() {
+        applicationFeatureIdTransformer = new 
ApplicationFeatureIdTransformerIdentity();
+
+        evaluator = PermissionsEvaluationServiceForSecman.builder()
+                
.applicationFeatureIdTransformer(applicationFeatureIdTransformer)
+                .policy(ALLOW_BEATS_VETO)
+                .build();
+    }
+
+    @Test
+    void granted_viewing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void granted_viewing_via_namespace_changing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, CHANGING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void no_opinion_changing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                CHANGING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate).isNull();
+    }
+
+    @Test
+    void granted_changing_via_namespace_changing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                CHANGING,
+                List.of(
+                    new ApplicationPermissionValue(newNamespace("customer"), 
ALLOW, CHANGING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void granted_viewing_via_type() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                    new 
ApplicationPermissionValue(newType("customer.Customer"), ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isTrue();
+    }
+
+    @Test
+    void veto_viewing_via_namespace_viewing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                        new 
ApplicationPermissionValue(newNamespace("customer"), VETO, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isFalse();
+    }
+
+    @Test
+    void 
granted_viewing_when_namespace_veto_viewing_overridden_by_type_allowing() {
+        ApplicationPermissionValueSet.Evaluation evaluate = evaluator.evaluate(
+                newMember("customer.Customer#lastName"),
+                VIEWING,
+                List.of(
+                        new 
ApplicationPermissionValue(newNamespace("customer"), VETO, VIEWING),
+                        new 
ApplicationPermissionValue(newNamespace("customer.Customer"), ALLOW, VIEWING)
+                )
+        );
+        assertThat(evaluate.isGranted()).isFalse();
+    }
+
+}
\ No newline at end of file

Reply via email to