diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationCompositeRoleTest.java b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationCompositeRoleTest.java
new file mode 100644
index 0000000..2b9e856
--- /dev/null
+++ b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationCompositeRoleTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed 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.keycloak.client.testsuite.authz;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.DecisionEffect;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest;
+import org.keycloak.representations.idm.authorization.PolicyEvaluationResponse;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.RealmBuilder;
+import org.keycloak.testsuite.util.RoleBuilder;
+import org.keycloak.testsuite.util.RolesBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
+
+/**
+ * @author Bill Burke
+ * @version $Revision: 1 $
+ */
+public class PolicyEvaluationCompositeRoleTest extends AbstractAuthzTest {
+
+ @Override
+ public List getRealmsForImport() {
+ List testRealms = new ArrayList<>();
+ testRealms
+ .add(RealmBuilder.create().name("test")
+ .user(UserBuilder.create().username("userok").password("password").addRoles("composite"))
+ .user(UserBuilder.create().username("userko").password("password"))
+ .client(ClientBuilder.create().clientId("myclient").secret("secret")
+ .authorizationServicesEnabled(true).redirectUris("http://localhost/myclient").directAccessGrants())
+ .roles(RolesBuilder.create()
+ .clientRole("myclient", RoleBuilder.create().name("client-role1").build())
+ .realmRole(RoleBuilder.create().name("composite").clientComposite("myclient", "client-role1").build()))
+ .build());
+ return testRealms;
+ }
+
+ private ClientResource getClient() {
+ ClientsResource clients = adminClient.realm("test").clients();
+ return clients.findByClientId("myclient").stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
+ }
+
+ private void createRolePolicy() {
+ RolePolicyRepresentation policy = new RolePolicyRepresentation();
+
+ policy.setName("client-role1");
+ policy.addClientRole("myclient", "client-role1", true);
+ policy.setDecisionStrategy(DecisionStrategy.UNANIMOUS);
+ policy.setLogic(Logic.POSITIVE);
+
+ getClient().authorization().policies().role().create(policy).close();
+ }
+
+ private void createResource() {
+ AuthorizationResource authorization = getClient().authorization();
+ ResourceRepresentation resource = new ResourceRepresentation("myresource");
+
+ authorization.resources().create(resource).close();
+ }
+
+ private void createScope() {
+ AuthorizationResource authorization = getClient().authorization();
+ ScopeRepresentation scope = new ScopeRepresentation("myscope");
+
+ authorization.scopes().create(scope).close();
+ }
+
+ private void createScopePermission() {
+ ScopePermissionRepresentation permission = new ScopePermissionRepresentation();
+
+ permission.setName("mypermission");
+ permission.addResource("myresource");
+ permission.addPolicy("client-role1");
+ permission.setScopes(Set.of("myscope"));
+
+ getClient().authorization().permissions().scope().create(permission).close();
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ createResource();
+ createScope();
+ createRolePolicy();
+ createScopePermission();
+
+ RealmResource realm = adminClient.realm("test");
+ String resourceServerId = realm.clients().findByClientId("myclient").get(0).getId();
+ UserRepresentation userok = realm.users().search("userok").get(0);
+ UserRepresentation userko = realm.users().search("userko").get(0);
+
+ PolicyEvaluationRequest request = new PolicyEvaluationRequest();
+ request.setUserId(userok.getId());
+ request.setClientId(resourceServerId);
+ request.addResource("myresource");
+ PolicyEvaluationResponse result = realm.clients().get(resourceServerId).authorization().policies().evaluate(request);
+ Assertions.assertEquals(DecisionEffect.PERMIT, result.getStatus());
+
+ request = new PolicyEvaluationRequest();
+ request.setUserId(userko.getId());
+ request.setClientId(resourceServerId);
+ request.addResource("myresource");
+ result = realm.clients().get(resourceServerId).authorization().policies().evaluate(request);
+ Assertions.assertEquals(DecisionEffect.DENY, result.getStatus());
+ }
+}
\ No newline at end of file
diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationTest.java b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationTest.java
new file mode 100644
index 0000000..f4ab749
--- /dev/null
+++ b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/PolicyEvaluationTest.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2018 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed 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.keycloak.client.testsuite.authz;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.DecisionEffect;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest;
+import org.keycloak.representations.idm.authorization.PolicyEvaluationResponse;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+import org.keycloak.representations.userprofile.config.UPConfig;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.GroupBuilder;
+import org.keycloak.testsuite.util.RealmBuilder;
+import org.keycloak.testsuite.util.RoleBuilder;
+import org.keycloak.testsuite.util.RolesBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
+
+/**
+ * @author Pedro Igor
+ */
+public class PolicyEvaluationTest extends AbstractAuthzTest {
+
+ @Override
+ public List getRealmsForImport() {
+ List testRealms = new ArrayList<>();
+
+ ProtocolMapperRepresentation groupProtocolMapper = new ProtocolMapperRepresentation();
+
+ groupProtocolMapper.setName("groups");
+ groupProtocolMapper.setProtocolMapper("oidc-group-membership-mapper");
+ groupProtocolMapper.setProtocol("openid-connect");
+ Map config = new HashMap<>();
+ config.put("claim.name", "groups");
+ config.put("access.token.claim", "true");
+ config.put("id.token.claim", "true");
+ config.put("full.path", "true");
+ groupProtocolMapper.setConfig(config);
+
+ testRealms.add(RealmBuilder.create().name("authz-test")
+ .roles(RolesBuilder.create()
+ .realmRole(RoleBuilder.create().name("uma_authorization").build())
+ .realmRole(RoleBuilder.create().name("role-a").build())
+ .realmRole(RoleBuilder.create().name("role-b").build())
+ )
+ .group(GroupBuilder.create().name("Group A")
+ .subGroups(Arrays.asList("Group B", "Group D").stream().map(name -> {
+ if ("Group B".equals(name)) {
+ return GroupBuilder.create().name(name).subGroups(Arrays.asList("Group C", "Group E").stream()
+ .map((String name1) -> GroupBuilder.create().name(name1).build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+ return GroupBuilder.create().name(name).realmRoles(Arrays.asList("role-a")).build();
+ }).collect(Collectors.toList())).build())
+ .group(GroupBuilder.create().name("Group E").build())
+ .user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization", "role-a").addGroups("Group A"))
+ .user(UserBuilder.create().username("alice").password("password").addRoles("uma_authorization").addGroups("/Group A/Group B/Group E"))
+ .user(UserBuilder.create().username("kolo").password("password").addRoles("uma_authorization").addGroups("/Group A/Group D"))
+ .user(UserBuilder.create().username("trinity").password("password").addRoles("uma_authorization").role("role-mapping-client", "client-role-a"))
+ .user(UserBuilder.create().username("jdoe").password("password").addGroups("/Group A/Group B", "/Group A/Group D"))
+ .client(ClientBuilder.create().clientId("resource-server-test")
+ .secret("secret")
+ .authorizationServicesEnabled(true)
+ .redirectUris("http://localhost/resource-server-test")
+ .defaultRoles("uma_protection")
+ .directAccessGrants()
+ .protocolMapper(groupProtocolMapper))
+ .client(ClientBuilder.create().clientId("role-mapping-client")
+ .defaultRoles("client-role-a", "client-role-b"))
+ .build());
+ return testRealms;
+ }
+
+ private ClientResource getClient(RealmResource realm) {
+ ClientsResource clients = realm.clients();
+ return clients.findByClientId("resource-server-test").stream()
+ .map(representation -> clients.get(representation.getId()))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
+ }
+
+ private void remove(ClientResource client, ResourceRepresentation resource) {
+ if (resource != null && resource.getId() != null) {
+ client.authorization().resources().resource(resource.getId()).remove();
+ }
+ }
+
+ private void remove(ClientResource client, AbstractPolicyRepresentation policy) {
+ if (policy != null && policy.getId() != null) {
+ client.authorization().policies().policy(policy.getId()).remove();
+ }
+ }
+
+ private void remove(ClientResource client, ResourcePermissionRepresentation permission) {
+ if (permission != null && permission.getId() != null) {
+ client.authorization().permissions().resource().findById(permission.getId()).remove();
+ }
+ }
+
+ private void remove(ClientResource client, ScopePermissionRepresentation permission) {
+ if (permission != null && permission.getId() != null) {
+ client.authorization().permissions().scope().findById(permission.getId()).remove();
+ }
+ }
+
+ private void remove(ClientResource client, ScopeRepresentation scope) {
+ if (scope != null && scope.getId() != null) {
+ client.authorization().scopes().scope(scope.getId()).remove();
+ }
+ }
+
+ private ResourceRepresentation createResource(ClientResource client, String name, String... scopes) {
+ ResourceRepresentation resource = new ResourceRepresentation(name);
+ if (scopes != null && scopes.length > 0) {
+ resource.addScope(scopes);
+ }
+ client.authorization().resources().create(resource).close();
+ resource.setId(client.authorization().resources().findByName(resource.getName()).iterator().next().getId());
+ return resource;
+ }
+
+ private TimePolicyRepresentation createTimePolicy(ClientResource client, boolean valid) {
+ TimePolicyRepresentation policy = new TimePolicyRepresentation();
+ policy.setName("time-policy");
+ long notOnOrAfter = System.currentTimeMillis() + (valid ? 24 * 3600 * 1000 : -24 * 3600 * 1000);
+ Date notOnOrAfterDate = new Date(notOnOrAfter);
+ policy.setNotOnOrAfter(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(notOnOrAfterDate));
+ client.authorization().policies().time().create(policy).close();
+ policy.setId(client.authorization().policies().findByName(policy.getName()).getId());
+ return policy;
+ }
+
+ private JSPolicyRepresentation createJSPolicy(ClientResource client, String name, Logic logic) {
+ JSPolicyRepresentation policy = new JSPolicyRepresentation();
+ policy.setName("javascript-policy");
+ policy.setType(name);
+ policy.setLogic(logic);
+ client.authorization().policies().js().create(policy).close();
+ policy.setId(client.authorization().policies().findByName(policy.getName()).getId());
+ return policy;
+ }
+
+ private ResourcePermissionRepresentation createResourcePermission(ClientResource client,
+ String name, String resourceId, String policyId) {
+ ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
+ permission.setName(name);
+ permission.addResource(resourceId);
+ permission.addPolicy(policyId);
+ client.authorization().permissions().resource().create(permission).close();
+ permission.setId(client.authorization().permissions().resource().findByName(permission.getName()).getId());
+ return permission;
+ }
+
+ private PolicyEvaluationResponse evaluate(ClientResource client, String userId, String resourceId) {
+ PolicyEvaluationRequest request = new PolicyEvaluationRequest();
+ request.setUserId(userId);
+ request.setClientId(client.toRepresentation().getId());
+ request.addResource(resourceId);
+ PolicyEvaluationResponse result = client.authorization().policies().evaluate(request);
+ return result;
+ }
+
+ private ScopeRepresentation createScope(ClientResource client, String name) {
+ ScopeRepresentation scope = new ScopeRepresentation();
+ scope.setName(name);
+ client.authorization().scopes().create(scope).close();
+ scope.setId(client.authorization().scopes().findByName(scope.getName()).getId());
+ return scope;
+ }
+
+ private ScopePermissionRepresentation createScopePermission(ClientResource client, String name, String scopeId, String policyId) {
+ ScopePermissionRepresentation permission = new ScopePermissionRepresentation();
+ permission.setName(name);
+ permission.addScope(scopeId);
+ permission.addPolicy(policyId);
+ client.authorization().permissions().scope().create(permission).close();
+ permission.setId(client.authorization().permissions().resource().findByName(permission.getName()).getId());
+ return permission;
+ }
+
+ private void testCheckDateAndTime(DecisionEffect effect) {
+ RealmResource realm = adminClient.realm("authz-test");
+ ClientResource client = getClient(realm);
+ UserRepresentation marta = realm.users().search("marta").get(0);
+
+ ResourceRepresentation resource = null;
+ TimePolicyRepresentation policy = null;
+ ResourcePermissionRepresentation permission = null;
+
+ try {
+ resource = createResource(client, "time-resource");
+ policy = createTimePolicy(client, DecisionEffect.PERMIT == effect);
+ permission = createResourcePermission(client, "time-resource-permission", resource.getId(), policy.getId());
+
+ PolicyEvaluationResponse result = evaluate(client, marta.getId(), resource.getId());
+ Assertions.assertEquals(effect, result.getStatus());
+ } finally {
+ remove(client, permission);
+ remove(client, policy);
+ remove(client, resource);
+ }
+ }
+
+ @Test
+ public void testCheckDateAndTime() {
+ testCheckDateAndTime(DecisionEffect.PERMIT);
+ testCheckDateAndTime(DecisionEffect.DENY);
+ }
+
+ private void testJavaScriptPolicy(DecisionEffect effect, String name) {
+ RealmResource realm = adminClient.realm("authz-test");
+ ClientResource client = getClient(realm);
+ UserRepresentation marta = realm.users().search("marta").get(0);
+
+ ResourceRepresentation resource = null;
+ JSPolicyRepresentation policy = null;
+ ResourcePermissionRepresentation permission = null;
+
+ try {
+ resource = createResource(client, "js-resource");
+ policy = createJSPolicy(client, name, Logic.POSITIVE);
+ permission = createResourcePermission(client, "javascript-permission", resource.getId(), policy.getId());
+
+ PolicyEvaluationResponse result = evaluate(client, marta.getId(), resource.getId());
+ Assertions.assertEquals(effect, result.getStatus());
+ } finally {
+ remove(client, permission);
+ remove(client, policy);
+ remove(client, resource);
+ }
+ }
+
+ @Test
+ public void testCheckUserInGroup() {
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-group-name-in-role-policy.js");
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-in-group-name-a-policy.js");
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-in-group-path-a-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-user-in-group-path-b-policy.js");
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-alice-in-group-child-e-policy.js");
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-alice-in-group-path-a-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-alice-in-group-path-a-no-parent-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-alice-in-group-path-e-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-alice-in-group-name-e-policy.js");
+ }
+
+ @Test
+ public void testCheckUserInRole() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-marta-in-role-a-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-marta-in-role-b-policy.js");
+ }
+
+ @Test
+ public void testCheckUserInClientRole() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-trinity-in-client-roles-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-trinity-in-client-role-b-policy.js");
+ }
+
+ @Test
+ public void testCheckGroupInRole() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-group-in-role-policy.js");
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-child-group-in-role-policy.js");
+ }
+
+ @Test
+ public void testCheckUserRealmRoles() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-realm-roles-policy.js");
+ }
+
+ @Test
+ public void testCheckUserClientRoles() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-client-roles-policy.js");
+ }
+
+ @Test
+ public void testCheckUserGroups() {
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-from-groups-policy.js");
+ }
+
+ @Test
+ public void testCheckUserAttributes() {
+ RealmResource realm = adminClient.realm("authz-test");
+
+ testJavaScriptPolicy(DecisionEffect.DENY, "script-scripts/allow-user-with-attributes.js");
+
+ UPConfig up = realm.users().userProfile().getConfiguration();
+ up.setUnmanagedAttributePolicy(UPConfig.UnmanagedAttributePolicy.ENABLED);
+ realm.users().userProfile().update(up);
+
+ try {
+ UserRepresentation jdoe = realm.users().search("jdoe").get(0);
+ Map> attrs = new HashMap<>();
+ attrs.put("a1", List.of("1", "2"));
+ attrs.put("a2", List.of("3"));
+ jdoe.setAttributes(attrs);
+ realm.users().get(jdoe.getId()).update(jdoe);
+
+ testJavaScriptPolicy(DecisionEffect.PERMIT, "script-scripts/allow-user-with-attributes.js");
+ } finally {
+ up.setUnmanagedAttributePolicy(null);
+ realm.users().userProfile().update(up);
+ }
+ }
+
+ @Test
+ public void testCheckResourceAttributes() {
+ RealmResource realm = adminClient.realm("authz-test");
+ ClientResource client = getClient(realm);
+ UserRepresentation marta = realm.users().search("marta").get(0);
+
+ ResourceRepresentation resource = null;
+ JSPolicyRepresentation policy = null;
+ ResourcePermissionRepresentation permission = null;
+
+ try {
+ // create a resource bur with the attributes list
+ resource = new ResourceRepresentation("js-resource");
+ Map> attrs = new HashMap<>();
+ attrs.put("a1", List.of("1", "2"));
+ attrs.put("a2", List.of("3"));
+ resource.setAttributes(attrs);
+ client.authorization().resources().create(resource).close();
+ resource.setId(client.authorization().resources().findByName(resource.getName()).iterator().next().getId());
+
+ policy = createJSPolicy(client, "script-scripts/allow-resources-with-attributes.js", Logic.POSITIVE);
+ permission = createResourcePermission(client, "javascript-permission", resource.getId(), policy.getId());
+
+ PolicyEvaluationResponse result = evaluate(client, marta.getId(), resource.getId());
+ Assertions.assertEquals(DecisionEffect.PERMIT, result.getStatus());
+ } finally {
+ remove(client, permission);
+ remove(client, policy);
+ remove(client, resource);
+ }
+ }
+
+ @Test
+ public void testCachedDecisionsWithNegativePolicies() {
+ RealmResource realm = adminClient.realm("authz-test");
+ ClientResource client = getClient(realm);
+ UserRepresentation marta = realm.users().search("marta").get(0);
+
+ ScopeRepresentation readScope = null;
+ ScopeRepresentation writeScope = null;
+ ResourceRepresentation resource = null;
+ JSPolicyRepresentation policy = null;
+ ScopePermissionRepresentation readPermission = null;
+ ScopePermissionRepresentation writePermission = null;
+
+ try {
+ readScope = createScope(client, "read");
+ writeScope = createScope(client, "write");
+ resource = createResource(client, "resource", readScope.getName(), writeScope.getName());
+ policy = createJSPolicy(client, "script-scripts/default-policy.js", Logic.NEGATIVE);
+ readPermission = createScopePermission(client, "read-premission", readScope.getId(), policy.getId());
+ writePermission = createScopePermission(client, "write-premission", writeScope.getId(), policy.getId());
+
+ PolicyEvaluationResponse result = evaluate(client, marta.getId(), resource.getId());
+ Assertions.assertEquals(DecisionEffect.DENY, result.getStatus());
+ } finally {
+ remove(client, readPermission);
+ remove(client, writePermission);
+ remove(client, policy);
+ remove(client, resource);
+ remove(client, readScope);
+ remove(client, writeScope);
+ }
+ }
+}