keycloak-aplcache
Changes
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java 27(+16 -11)
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java 73(+67 -6)
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java 40(+20 -20)
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java 94(+43 -51)
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java 26(+15 -11)
authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java 51(+25 -26)
core/src/main/java/org/keycloak/representations/idm/authorization/ClientPolicyRepresentation.java 49(+49 -0)
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPoliciesResource.java 50(+50 -0)
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPolicyResource.java 69(+69 -0)
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java 7(+5 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzAdapterTest.java 4(+2 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java 103(+101 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractPolicyManagementTest.java 2(+1 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ClientPolicyManagementTest.java 172(+172 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java 5(+4 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/RolePolicyManagementTest.java 8(+4 -4)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/UserPolicyManagementTest.java 10(+5 -5)
testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json 14(+14 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java 41(+41 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java 114(+114 -0)
testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java 14(+14 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java 4(+2 -2)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ClientPolicyManagementTest.java 116(+116 -0)
testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java 4(+2 -2)
Details
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
index 5c778d8..ffd92bf 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
@@ -1,6 +1,6 @@
package org.keycloak.authorization.policy.provider.client;
-import static org.keycloak.authorization.policy.provider.client.ClientPolicyProviderFactory.getClients;
+import java.util.function.Function;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
@@ -9,24 +9,29 @@ import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
public class ClientPolicyProvider implements PolicyProvider {
+ private final Function<Policy, ClientPolicyRepresentation> representationFunction;
+
+ public ClientPolicyProvider(Function<Policy, ClientPolicyRepresentation> representationFunction) {
+ this.representationFunction = representationFunction;
+ }
+
@Override
public void evaluate(Evaluation evaluation) {
- Policy policy = evaluation.getPolicy();
- EvaluationContext context = evaluation.getContext();
- String[] clients = getClients(policy);
+ ClientPolicyRepresentation representation = representationFunction.apply(evaluation.getPolicy());
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
+ EvaluationContext context = evaluation.getContext();
+
+ for (String client : representation.getClients()) {
+ ClientModel clientModel = realm.getClientById(client);
- if (clients.length > 0) {
- for (String client : clients) {
- ClientModel clientModel = realm.getClientById(client);
- if (context.getAttributes().containsValue("kc.client.id", clientModel.getClientId())) {
- evaluation.grant();
- return;
- }
+ if (context.getAttributes().containsValue("kc.client.id", clientModel.getClientId())) {
+ evaluation.grant();
+ return;
}
}
}
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
index a0e7874..d061357 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
@@ -2,14 +2,17 @@ package org.keycloak.authorization.policy.provider.client;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.policy.provider.PolicyProvider;
-import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.ResourceServerStore;
@@ -17,12 +20,15 @@ import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmModel.ClientRemovedEvent;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.util.JsonSerialization;
-public class ClientPolicyProviderFactory implements PolicyProviderFactory {
+public class ClientPolicyProviderFactory implements PolicyProviderFactory<ClientPolicyRepresentation> {
- private ClientPolicyProvider provider = new ClientPolicyProvider();
+ private ClientPolicyProvider provider = new ClientPolicyProvider(policy -> toRepresentation(policy, new ClientPolicyRepresentation()));
@Override
public String getName() {
@@ -40,8 +46,29 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory {
}
@Override
- public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
- return null;
+ public ClientPolicyRepresentation toRepresentation(Policy policy, ClientPolicyRepresentation representation) {
+ representation.setClients(new HashSet<>(Arrays.asList(getClients(policy))));
+ return representation;
+ }
+
+ @Override
+ public Class<ClientPolicyRepresentation> getRepresentationType() {
+ return ClientPolicyRepresentation.class;
+ }
+
+ @Override
+ public void onCreate(Policy policy, ClientPolicyRepresentation representation, AuthorizationProvider authorization) {
+ updateClients(policy, representation.getClients(), authorization);
+ }
+
+ @Override
+ public void onUpdate(Policy policy, ClientPolicyRepresentation representation, AuthorizationProvider authorization) {
+ updateClients(policy, representation.getClients(), authorization);
+ }
+
+ @Override
+ public void onImport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
+ updateClients(policy, new HashSet<>(Arrays.asList(getClients(policy))), authorization);
}
@Override
@@ -101,7 +128,41 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory {
return "client";
}
- static String[] getClients(Policy policy) {
+ private void updateClients(Policy policy, Set<String> clients, AuthorizationProvider authorization) {
+ RealmModel realm = authorization.getKeycloakSession().getContext().getRealm();
+
+ if (clients == null || clients.isEmpty()) {
+ throw new RuntimeException("No client provided.");
+ }
+
+ Set<String> updatedClients = new HashSet<>();
+
+ for (String id : clients) {
+ ClientModel client = realm.getClientByClientId(id);
+
+ if (client == null) {
+ client = realm.getClientById(id);
+ }
+
+ if (client == null) {
+ throw new RuntimeException("Error while updating policy [" + policy.getName() + "]. Client [" + id + "] could not be found.");
+ }
+
+ updatedClients.add(client.getId());
+ }
+
+ try {
+ Map<String, String> config = policy.getConfig();
+
+ config.put("clients", JsonSerialization.writeValueAsString(updatedClients));
+
+ policy.setConfig(config);
+ } catch (IOException cause) {
+ throw new RuntimeException("Failed to serialize clients", cause);
+ }
+ }
+
+ private String[] getClients(Policy policy) {
String clients = policy.getConfig().get("clients");
if (clients != null) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
index 4aafedd..e88eed6 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
@@ -17,9 +17,9 @@
*/
package org.keycloak.authorization.policy.provider.role;
-import static org.keycloak.authorization.policy.provider.role.RolePolicyProviderFactory.getRoles;
-
import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.identity.Identity;
@@ -29,43 +29,43 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class RolePolicyProvider implements PolicyProvider {
+ private final Function<Policy, RolePolicyRepresentation> representationFunction;
+
+ public RolePolicyProvider(Function<Policy, RolePolicyRepresentation> representationFunction) {
+ this.representationFunction = representationFunction;
+ }
+
@Override
public void evaluate(Evaluation evaluation) {
Policy policy = evaluation.getPolicy();
- Map<String, Object>[] roleIds = getRoles(policy);
+ Set<RolePolicyRepresentation.RoleDefinition> roleIds = representationFunction.apply(policy).getRoles();
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
+ Identity identity = evaluation.getContext().getIdentity();
- if (roleIds.length > 0) {
- Identity identity = evaluation.getContext().getIdentity();
+ for (RolePolicyRepresentation.RoleDefinition roleDefinition : roleIds) {
+ RoleModel role = realm.getRoleById(roleDefinition.getId());
- for (Map<String, Object> current : roleIds) {
- RoleModel role = realm.getRoleById((String) current.get("id"));
+ if (role != null) {
+ boolean hasRole = hasRole(identity, role, realm);
- if (role != null) {
- boolean hasRole = hasRole(identity, role, realm);
-
- if (!hasRole && Boolean.valueOf(isRequired(current))) {
- evaluation.deny();
- return;
- } else if (hasRole) {
- evaluation.grant();
- }
+ if (!hasRole && roleDefinition.isRequired()) {
+ evaluation.deny();
+ return;
+ } else if (hasRole) {
+ evaluation.grant();
}
}
}
}
- private boolean isRequired(Map<String, Object> current) {
- return (boolean) current.getOrDefault("required", false);
- }
-
private boolean hasRole(Identity identity, RoleModel role, RealmModel realm) {
String roleName = role.getName();
if (role.isClientRole()) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
index d5d3917..03ea156 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
@@ -23,7 +23,6 @@ import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.policy.provider.PolicyProvider;
-import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.ResourceServerStore;
@@ -53,7 +52,7 @@ import java.util.Set;
*/
public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePolicyRepresentation> {
- private RolePolicyProvider provider = new RolePolicyProvider();
+ private RolePolicyProvider provider = new RolePolicyProvider(policy -> toRepresentation(policy, new RolePolicyRepresentation()));
@Override
public String getName() {
@@ -71,19 +70,14 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
}
@Override
- public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
- return null;
- }
-
- @Override
public PolicyProvider create(KeycloakSession session) {
- return new RolePolicyProvider();
+ return provider;
}
@Override
public RolePolicyRepresentation toRepresentation(Policy policy, RolePolicyRepresentation representation) {
try {
- representation.setRoles(JsonSerialization.readValue(policy.getConfig().get("roles"), Set.class));
+ representation.setRoles(new HashSet<>(Arrays.asList(JsonSerialization.readValue(policy.getConfig().get("roles"), RolePolicyRepresentation.RoleDefinition[].class))));
} catch (IOException cause) {
throw new RuntimeException("Failed to deserialize roles", cause);
}
@@ -119,65 +113,63 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
}
private void updateRoles(Policy policy, AuthorizationProvider authorization, Set<RolePolicyRepresentation.RoleDefinition> roles) {
- try {
- RealmModel realm = authorization.getRealm();
- Set<RolePolicyRepresentation.RoleDefinition> updatedRoles = new HashSet<>();
-
- if (roles != null) {
- for (RolePolicyRepresentation.RoleDefinition definition : roles) {
- String roleName = definition.getId();
- String clientId = null;
- int clientIdSeparator = roleName.indexOf("/");
-
- if (clientIdSeparator != -1) {
- clientId = roleName.substring(0, clientIdSeparator);
- roleName = roleName.substring(clientIdSeparator + 1);
- }
-
- RoleModel role;
+ RealmModel realm = authorization.getRealm();
+ Set<RolePolicyRepresentation.RoleDefinition> updatedRoles = new HashSet<>();
- if (clientId == null) {
- role = realm.getRole(roleName);
-
- if (role == null) {
- role = realm.getRoleById(roleName);
- }
- } else {
- ClientModel client = realm.getClientByClientId(clientId);
+ if (roles != null) {
+ for (RolePolicyRepresentation.RoleDefinition definition : roles) {
+ String roleName = definition.getId();
+ String clientId = null;
+ int clientIdSeparator = roleName.indexOf("/");
+
+ if (clientIdSeparator != -1) {
+ clientId = roleName.substring(0, clientIdSeparator);
+ roleName = roleName.substring(clientIdSeparator + 1);
+ }
- if (client == null) {
- throw new RuntimeException("Client with id [" + clientId + "] not found.");
- }
+ RoleModel role;
- role = client.getRole(roleName);
- }
+ if (clientId == null) {
+ role = realm.getRole(roleName);
- // fallback to find any client role with the given name
if (role == null) {
- String finalRoleName = roleName;
- role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
- .findFirst().orElse(null);
+ role = realm.getRoleById(roleName);
}
+ } else {
+ ClientModel client = realm.getClientByClientId(clientId);
- if (role == null) {
- throw new RuntimeException("Error while importing configuration. Role [" + roleName + "] could not be found.");
+ if (client == null) {
+ throw new RuntimeException("Client with id [" + clientId + "] not found.");
}
- definition.setId(role.getId());
+ role = client.getRole(roleName);
+ }
- updatedRoles.add(definition);
+ // fallback to find any client role with the given name
+ if (role == null) {
+ String finalRoleName = roleName;
+ role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
+ .findFirst().orElse(null);
}
- try {
- } catch (Exception e) {
- throw new RuntimeException("Error while updating policy [" + policy.getName() + "].", e);
+
+ if (role == null) {
+ throw new RuntimeException("Error while updating policy [" + policy.getName() + "]. Role [" + roleName + "] could not be found.");
}
+
+ definition.setId(role.getId());
+
+ updatedRoles.add(definition);
}
+ }
+ try {
Map<String, String> config = policy.getConfig();
+
config.put("roles", JsonSerialization.writeValueAsString(updatedRoles));
+
policy.setConfig(config);
} catch (IOException cause) {
- throw new RuntimeException("Failed to deserialize roles", cause);
+ throw new RuntimeException("Failed to serialize roles", cause);
}
}
@@ -253,7 +245,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
return "role";
}
- static Map<String, Object>[] getRoles(Policy policy) {
+ private Map<String, Object>[] getRoles(Policy policy) {
String roles = policy.getConfig().get("roles");
if (roles != null) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
index 2f77106..f891257 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
@@ -17,30 +17,34 @@
*/
package org.keycloak.authorization.policy.provider.user;
+import java.util.function.Function;
+
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.policy.evaluation.Evaluation;
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.authorization.policy.provider.PolicyProvider;
-
-import static org.keycloak.authorization.policy.provider.user.UserPolicyProviderFactory.getUsers;
+import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class UserPolicyProvider implements PolicyProvider {
+ private final Function<Policy, UserPolicyRepresentation> representationFunction;
+
+ public UserPolicyProvider(Function<Policy, UserPolicyRepresentation> representationFunction) {
+ this.representationFunction = representationFunction;
+ }
+
@Override
public void evaluate(Evaluation evaluation) {
- Policy policy = evaluation.getPolicy();
EvaluationContext context = evaluation.getContext();
- String[] userIds = getUsers(policy);
-
- if (userIds.length > 0) {
- for (String userId : userIds) {
- if (context.getIdentity().getId().equals(userId)) {
- evaluation.grant();
- break;
- }
+ UserPolicyRepresentation representation = representationFunction.apply(evaluation.getPolicy());
+
+ for (String userId : representation.getUsers()) {
+ if (context.getIdentity().getId().equals(userId)) {
+ evaluation.grant();
+ break;
}
}
}
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
index 0fd54df..e4bbaf9 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
@@ -49,7 +50,7 @@ import org.keycloak.util.JsonSerialization;
*/
public class UserPolicyProviderFactory implements PolicyProviderFactory<UserPolicyRepresentation> {
- private UserPolicyProvider provider = new UserPolicyProvider();
+ private UserPolicyProvider provider = new UserPolicyProvider((Function<Policy, UserPolicyRepresentation>) policy -> toRepresentation(policy, new UserPolicyRepresentation()));
@Override
public String getName() {
@@ -110,42 +111,40 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory<UserPoli
}
private void updateUsers(Policy policy, AuthorizationProvider authorization, Set<String> users) {
- try {
- KeycloakSession session = authorization.getKeycloakSession();
- RealmModel realm = authorization.getRealm();
- UserProvider userProvider = session.users();
- Set<String> updatedUsers = new HashSet<>();
-
- if (users != null) {
- try {
- for (String userId : users) {
- UserModel user = null;
+ KeycloakSession session = authorization.getKeycloakSession();
+ RealmModel realm = authorization.getRealm();
+ UserProvider userProvider = session.users();
+ Set<String> updatedUsers = new HashSet<>();
- try {
- user = userProvider.getUserByUsername(userId, realm);
- } catch (Exception ignore) {
- }
+ if (users != null) {
+ for (String userId : users) {
+ UserModel user = null;
- if (user == null) {
- user = userProvider.getUserById(userId, realm);
- }
+ try {
+ user = userProvider.getUserByUsername(userId, realm);
+ } catch (Exception ignore) {
+ }
- if (user == null) {
- throw new RuntimeException("Error while importing configuration. User [" + userId + "] could not be found.");
- }
+ if (user == null) {
+ user = userProvider.getUserById(userId, realm);
+ }
- updatedUsers.add(user.getId());
- }
- } catch (Exception e) {
- throw new RuntimeException("Error while updating policy [" + policy.getName() + "].", e);
+ if (user == null) {
+ throw new RuntimeException("Error while updating policy [" + policy.getName() + "]. User [" + userId + "] could not be found.");
}
+
+ updatedUsers.add(user.getId());
}
+ }
+ try {
Map<String, String> config = policy.getConfig();
+
config.put("users", JsonSerialization.writeValueAsString(updatedUsers));
+
policy.setConfig(config);
} catch (IOException cause) {
- throw new RuntimeException("Failed to deserialize roles", cause);
+ throw new RuntimeException("Failed to serialize users", cause);
}
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/ClientPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/ClientPolicyRepresentation.java
new file mode 100644
index 0000000..d922a8f
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/ClientPolicyRepresentation.java
@@ -0,0 +1,49 @@
+/*
+ * 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.representations.idm.authorization;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ClientPolicyRepresentation extends AbstractPolicyRepresentation {
+
+ private Set<String> clients;
+
+ @Override
+ public String getType() {
+ return "client";
+ }
+
+ public Set<String> getClients() {
+ return clients;
+ }
+
+ public void setClients(Set<String> clients) {
+ this.clients = clients;
+ }
+
+ public void addClient(String... id) {
+ if (this.clients == null) {
+ this.clients = new HashSet<>();
+ }
+ this.clients.addAll(Arrays.asList(id));
+ }
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPoliciesResource.java
new file mode 100644
index 0000000..3fd7778
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPoliciesResource.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.client.resource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ClientPoliciesResource {
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ Response create(ClientPolicyRepresentation representation);
+
+ @Path("{id}")
+ ClientPolicyResource findById(@PathParam("id") String id);
+
+ @Path("/search")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ ClientPolicyRepresentation findByName(@QueryParam("name") String name);
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPolicyResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPolicyResource.java
new file mode 100644
index 0000000..a944935
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientPolicyResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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.admin.client.resource;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public interface ClientPolicyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ ClientPolicyRepresentation toRepresentation();
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ void update(ClientPolicyRepresentation representation);
+
+ @DELETE
+ void remove();
+
+ @Path("/associatedPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List<PolicyRepresentation> associatedPolicies();
+
+ @Path("/dependentPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List<PolicyRepresentation> dependentPolicies();
+
+ @Path("/resources")
+ @GET
+ @Produces("application/json")
+ @NoCache
+ List<ResourceRepresentation> resources();
+
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
index 4ce362d..a0af5d4 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
@@ -70,10 +70,10 @@ public interface PoliciesResource {
PolicyEvaluationResponse evaluate(PolicyEvaluationRequest evaluationRequest);
@Path("role")
- RolePoliciesResource roles();
+ RolePoliciesResource role();
@Path("user")
- UserPoliciesResource users();
+ UserPoliciesResource user();
@Path("js")
JSPoliciesResource js();
@@ -86,4 +86,7 @@ public interface PoliciesResource {
@Path("rules")
RulePoliciesResource rule();
+
+ @Path("client")
+ ClientPoliciesResource client();
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzAdapterTest.java
index d61b077..5c3f1f1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzAdapterTest.java
@@ -103,7 +103,7 @@ public abstract class AbstractServletAuthzAdapterTest extends AbstractExampleAda
return getClientResource(RESOURCE_SERVER_ID).authorization();
}
- private ClientResource getClientResource(String clientId) {
+ protected ClientResource getClientResource(String clientId) {
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
return clients.get(resourceServer.getId());
@@ -199,7 +199,7 @@ public abstract class AbstractServletAuthzAdapterTest extends AbstractExampleAda
assertFalse(policy.getUsers().isEmpty());
- getAuthorizationResource().policies().users().create(policy);
+ getAuthorizationResource().policies().user().create(policy);
}
protected interface ExceptionRunnable {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java
index 3aef537..b37e9e6 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java
@@ -26,15 +26,19 @@ import java.util.List;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
-import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.admin.client.resource.ClientPoliciesResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.ResourcesResource;
+import org.keycloak.admin.client.resource.RolePoliciesResource;
+import org.keycloak.admin.client.resource.RoleScopeResource;
+import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
-import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
import org.keycloak.testsuite.util.WaitUtils;
/**
@@ -205,4 +209,99 @@ public abstract class AbstractServletAuthzFunctionalAdapterTest extends Abstract
assertTrue(hasText("This is public resource that should be accessible without login."));
});
}
+
+ @Test
+ public void testRequiredRole() throws Exception {
+ performTests(() -> {
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertFalse(wasDenied());
+
+ RolesResource rolesResource = getClientResource(RESOURCE_SERVER_ID).roles();
+
+ rolesResource.create(new RoleRepresentation("required-role", "", false));
+
+ RolePolicyRepresentation policy = new RolePolicyRepresentation();
+
+ policy.setName("Required Role Policy");
+ policy.addRole("user_premium", false);
+ policy.addRole("required-role", false);
+
+ RolePoliciesResource rolePolicy = getAuthorizationResource().policies().role();
+
+ rolePolicy.create(policy);
+ policy = rolePolicy.findByName(policy.getName());
+
+ updatePermissionPolicies("Premium Resource Permission", policy.getName());
+
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertFalse(wasDenied());
+
+ policy.getRoles().clear();
+ policy.addRole("user_premium", false);
+ policy.addRole("required-role", true);
+
+ rolePolicy.findById(policy.getId()).update(policy);
+
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertTrue(wasDenied());
+
+ UsersResource users = realmsResouce().realm(REALM_NAME).users();
+ UserRepresentation user = users.search("jdoe").get(0);
+
+ RoleScopeResource roleScopeResource = users.get(user.getId()).roles().clientLevel(getClientResource(RESOURCE_SERVER_ID).toRepresentation().getId());
+ RoleRepresentation requiredRole = rolesResource.get("required-role").toRepresentation();
+ roleScopeResource.add(Arrays.asList(requiredRole));
+
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertFalse(wasDenied());
+
+ policy.getRoles().clear();
+ policy.addRole("user_premium", false);
+ policy.addRole("required-role", false);
+
+ rolePolicy.findById(policy.getId()).update(policy);
+
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertFalse(wasDenied());
+
+ roleScopeResource.remove(Arrays.asList(requiredRole));
+
+ login("jdoe", "jdoe");
+ navigateToUserPremiumPage();
+ assertFalse(wasDenied());
+ });
+ }
+
+ @Test
+ public void testOnlySpecificClient() throws Exception {
+ performTests(() -> {
+ login("jdoe", "jdoe");
+ assertFalse(wasDenied());
+
+ ClientPolicyRepresentation policy = new ClientPolicyRepresentation();
+
+ policy.setName("Only Client Policy");
+ policy.addClient("admin-cli");
+
+ ClientPoliciesResource policyResource = getAuthorizationResource().policies().client();
+ policyResource.create(policy);
+ policy = policyResource.findByName(policy.getName());
+
+ updatePermissionPolicies("Protected Resource Permission", policy.getName());
+
+ login("jdoe", "jdoe");
+ assertTrue(wasDenied());
+
+ policy.addClient("servlet-authz-app");
+ policyResource.findById(policy.getId()).update(policy);
+
+ login("jdoe", "jdoe");
+ assertFalse(wasDenied());
+ });
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractPolicyManagementTest.java
index b1f0b24..e0a4c53 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractPolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/AbstractPolicyManagementTest.java
@@ -147,7 +147,7 @@ public abstract class AbstractPolicyManagementTest extends AbstractKeycloakTest
representation.setName(name);
representation.addUser(userId);
- client.authorization().policies().users().create(representation);
+ client.authorization().policies().user().create(representation);
}
protected ClientResource getClient() {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ClientPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ClientPolicyManagementTest.java
new file mode 100644
index 0000000..87848d9
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ClientPolicyManagementTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.testsuite.admin.client.authorization;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.ClientPoliciesResource;
+import org.keycloak.admin.client.resource.ClientPolicyResource;
+import org.keycloak.admin.client.resource.PolicyResource;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.RealmBuilder;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ClientPolicyManagementTest extends AbstractPolicyManagementTest {
+
+ @Override
+ protected RealmBuilder createTestRealm() {
+ return super.createTestRealm()
+ .client(ClientBuilder.create().clientId("Client A"))
+ .client(ClientBuilder.create().clientId("Client B"))
+ .client(ClientBuilder.create().clientId("Client C"));
+ }
+
+ @Test
+ public void testCreate() {
+ AuthorizationResource authorization = getClient().authorization();
+ ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
+
+ representation.setName("Realm Client Policy");
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.addClient("Client A");
+ representation.addClient("Client B");
+
+ assertCreated(authorization, representation);
+ }
+
+ @Test
+ public void testUpdate() {
+ AuthorizationResource authorization = getClient().authorization();
+ ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
+
+ representation.setName("Update Test Client Policy");
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.addClient("Client A");
+ representation.addClient("Client B");
+ representation.addClient("Client C");
+
+ assertCreated(authorization, representation);
+
+ representation.setName("changed");
+ representation.setDescription("changed");
+ representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
+ representation.setLogic(Logic.POSITIVE);
+ representation.setClients(representation.getClients().stream().filter(userName -> !userName.equals("Client A")).collect(Collectors.toSet()));
+
+ ClientPoliciesResource policies = authorization.policies().client();
+ ClientPolicyResource permission = policies.findById(representation.getId());
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+
+ representation.setClients(representation.getClients().stream().filter(userName -> !userName.equals("Client C")).collect(Collectors.toSet()));
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+ }
+
+ @Test
+ public void testDelete() {
+ AuthorizationResource authorization = getClient().authorization();
+ ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
+
+ representation.setName("Test Delete Permission");
+ representation.addClient("Client A");
+
+ ClientPoliciesResource policies = authorization.policies().client();
+ Response response = policies.create(representation);
+ ClientPolicyRepresentation created = response.readEntity(ClientPolicyRepresentation.class);
+
+ policies.findById(created.getId()).remove();
+
+ ClientPolicyResource removed = policies.findById(created.getId());
+
+ try {
+ removed.toRepresentation();
+ fail("Permission not removed");
+ } catch (NotFoundException ignore) {
+
+ }
+ }
+
+ @Test
+ public void testGenericConfig() {
+ AuthorizationResource authorization = getClient().authorization();
+ ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
+
+ representation.setName("Test Generic Config Permission");
+ representation.addClient("Client A");
+
+ ClientPoliciesResource policies = authorization.policies().client();
+ Response response = policies.create(representation);
+ ClientPolicyRepresentation created = response.readEntity(ClientPolicyRepresentation.class);
+
+ PolicyResource policy = authorization.policies().policy(created.getId());
+ PolicyRepresentation genericConfig = policy.toRepresentation();
+
+ assertNotNull(genericConfig.getConfig());
+ assertNotNull(genericConfig.getConfig().get("clients"));
+
+ ClientRepresentation user = getRealm().clients().findByClientId("Client A").get(0);
+
+ assertTrue(genericConfig.getConfig().get("clients").contains(user.getId()));
+ }
+
+ private void assertCreated(AuthorizationResource authorization, ClientPolicyRepresentation representation) {
+ ClientPoliciesResource permissions = authorization.policies().client();
+ Response response = permissions.create(representation);
+ ClientPolicyRepresentation created = response.readEntity(ClientPolicyRepresentation.class);
+ ClientPolicyResource permission = permissions.findById(created.getId());
+ assertRepresentation(representation, permission);
+ }
+
+ private void assertRepresentation(ClientPolicyRepresentation representation, ClientPolicyResource permission) {
+ ClientPolicyRepresentation actual = permission.toRepresentation();
+ assertRepresentation(representation, actual, () -> permission.resources(), () -> Collections.emptyList(), () -> permission.associatedPolicies());
+ assertEquals(representation.getClients().size(), actual.getClients().size());
+ assertEquals(0, actual.getClients().stream().filter(clientId -> !representation.getClients().stream()
+ .filter(userName -> getClientName(clientId).equalsIgnoreCase(userName))
+ .findFirst().isPresent())
+ .count());
+ }
+
+ private String getClientName(String id) {
+ return getRealm().clients().get(id).toRepresentation().getClientId();
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java
index 4b2168f..a308ec0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java
@@ -28,6 +28,7 @@ import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
+import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.util.JsonSerialization;
/**
@@ -43,6 +44,8 @@ public class ImportAuthorizationSettingsTest extends AbstractAuthorizationTest {
RoleRepresentation role = new RoleRepresentation();
role.setName("admin");
clientResource.roles().create(role);
+
+ testRealmResource().users().create(UserBuilder.create().username("alice").build());
}
@After
@@ -72,6 +75,6 @@ public class ImportAuthorizationSettingsTest extends AbstractAuthorizationTest {
authorizationResource.importSettings(toImport);
- assertEquals(13, authorizationResource.policies().policies().size());
+ assertEquals(15, authorizationResource.policies().policies().size());
}
}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/RolePolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/RolePolicyManagementTest.java
index c351ec3..f066c71 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/RolePolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/RolePolicyManagementTest.java
@@ -119,7 +119,7 @@ public class RolePolicyManagementTest extends AbstractPolicyManagementTest {
representation.setLogic(Logic.POSITIVE);
representation.setRoles(representation.getRoles().stream().filter(roleDefinition -> !roleDefinition.getId().equals("Resource A")).collect(Collectors.toSet()));
- RolePoliciesResource policies = authorization.policies().roles();
+ RolePoliciesResource policies = authorization.policies().role();
RolePolicyResource permission = policies.findById(representation.getId());
permission.update(representation);
@@ -146,7 +146,7 @@ public class RolePolicyManagementTest extends AbstractPolicyManagementTest {
representation.setName("Test Delete Permission");
representation.addRole("Role A", false);
- RolePoliciesResource policies = authorization.policies().roles();
+ RolePoliciesResource policies = authorization.policies().role();
Response response = policies.create(representation);
RolePolicyRepresentation created = response.readEntity(RolePolicyRepresentation.class);
@@ -170,7 +170,7 @@ public class RolePolicyManagementTest extends AbstractPolicyManagementTest {
representation.setName("Test Generic Config Permission");
representation.addRole("Role A", false);
- RolePoliciesResource policies = authorization.policies().roles();
+ RolePoliciesResource policies = authorization.policies().role();
Response response = policies.create(representation);
RolePolicyRepresentation created = response.readEntity(RolePolicyRepresentation.class);
@@ -186,7 +186,7 @@ public class RolePolicyManagementTest extends AbstractPolicyManagementTest {
}
private void assertCreated(AuthorizationResource authorization, RolePolicyRepresentation representation) {
- RolePoliciesResource permissions = authorization.policies().roles();
+ RolePoliciesResource permissions = authorization.policies().role();
Response response = permissions.create(representation);
RolePolicyRepresentation created = response.readEntity(RolePolicyRepresentation.class);
RolePolicyResource permission = permissions.findById(created.getId());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/UserPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/UserPolicyManagementTest.java
index 6628bca..b4f78e0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/UserPolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/UserPolicyManagementTest.java
@@ -54,7 +54,7 @@ public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
}
@Test
- public void testCreateUserPolicy() {
+ public void testCreate() {
AuthorizationResource authorization = getClient().authorization();
UserPolicyRepresentation representation = new UserPolicyRepresentation();
@@ -89,7 +89,7 @@ public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
representation.setLogic(Logic.POSITIVE);
representation.setUsers(representation.getUsers().stream().filter(userName -> !userName.equals("User A")).collect(Collectors.toSet()));
- UserPoliciesResource policies = authorization.policies().users();
+ UserPoliciesResource policies = authorization.policies().user();
UserPolicyResource permission = policies.findById(representation.getId());
permission.update(representation);
@@ -109,7 +109,7 @@ public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
representation.setName("Test Delete Permission");
representation.addUser("User A");
- UserPoliciesResource policies = authorization.policies().users();
+ UserPoliciesResource policies = authorization.policies().user();
Response response = policies.create(representation);
UserPolicyRepresentation created = response.readEntity(UserPolicyRepresentation.class);
@@ -133,7 +133,7 @@ public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
representation.setName("Test Generic Config Permission");
representation.addUser("User A");
- UserPoliciesResource policies = authorization.policies().users();
+ UserPoliciesResource policies = authorization.policies().user();
Response response = policies.create(representation);
UserPolicyRepresentation created = response.readEntity(UserPolicyRepresentation.class);
@@ -149,7 +149,7 @@ public class UserPolicyManagementTest extends AbstractPolicyManagementTest {
}
private void assertCreated(AuthorizationResource authorization, UserPolicyRepresentation representation) {
- UserPoliciesResource permissions = authorization.policies().users();
+ UserPoliciesResource permissions = authorization.policies().user();
Response response = permissions.create(representation);
UserPolicyRepresentation created = response.readEntity(UserPolicyRepresentation.class);
UserPolicyResource permission = permissions.findById(created.getId());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json
index 47b7d1b..8bdb635 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json
@@ -161,6 +161,20 @@
"config": {
"code": "var context = $evaluation.getContext();\nvar identity = context.getIdentity();\nvar attributes = identity.getAttributes();\nvar email = attributes.getValue('email').asString(0);\n\nif (identity.hasRole('admin') || email.endsWith('@keycloak.org')) {\n $evaluation.grant();\n}"
}
+ },
+ {
+ "name": "Test Client Policy",
+ "type": "client",
+ "config": {
+ "clients": "[\"admin-cli\"]"
+ }
+ },
+ {
+ "name": "Test User Policy",
+ "type": "user",
+ "config": {
+ "users": "[\"alice\"]"
+ }
}
],
"scopes": [
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java
new file mode 100644
index 0000000..fe85623
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicy.java
@@ -0,0 +1,41 @@
+/*
+ * 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.testsuite.console.page.clients.authorization.policy;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ClientPolicy implements PolicyTypeUI {
+
+ @Page
+ private ClientPolicyForm form;
+
+ public ClientPolicyForm form() {
+ return form;
+ }
+
+ public ClientPolicyRepresentation toRepresentation() {
+ return form.toRepresentation();
+ }
+
+ public void update(ClientPolicyRepresentation expected) {
+ form().populate(expected);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java
new file mode 100644
index 0000000..9095a32
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/ClientPolicyForm.java
@@ -0,0 +1,114 @@
+/*
+ * 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.testsuite.console.page.clients.authorization.policy;
+
+import static org.openqa.selenium.By.tagName;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.console.page.fragment.MultipleStringSelect2;
+import org.keycloak.testsuite.page.Form;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.ui.Select;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ClientPolicyForm extends Form {
+
+ @FindBy(id = "name")
+ private WebElement name;
+
+ @FindBy(id = "description")
+ private WebElement description;
+
+ @FindBy(id = "logic")
+ private Select logic;
+
+ @FindBy(xpath = "//i[contains(@class,'pficon-delete')]")
+ private WebElement deleteButton;
+
+ @FindBy(id = "s2id_clients")
+ private ClientSelect clientsInput;
+
+ @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Delete']")
+ private WebElement confirmDelete;
+
+ public void populate(ClientPolicyRepresentation expected) {
+ setInputValue(name, expected.getName());
+ setInputValue(description, expected.getDescription());
+ logic.selectByValue(expected.getLogic().name());
+
+ clientsInput.update(expected.getClients());
+
+ save();
+ }
+
+ public void delete() {
+ deleteButton.click();
+ confirmDelete.click();
+ }
+
+ public ClientPolicyRepresentation toRepresentation() {
+ ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
+
+ representation.setName(getInputValue(name));
+ representation.setDescription(getInputValue(description));
+ representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
+ representation.setClients(clientsInput.getSelected());
+
+ return representation;
+ }
+
+ public class ClientSelect extends MultipleStringSelect2 {
+
+ @Override
+ protected List<WebElement> getSelectedElements() {
+ return getRoot().findElements(By.xpath("(//table[@id='selected-clients'])/tbody/tr")).stream()
+ .filter(webElement -> webElement.findElements(tagName("td")).size() > 1)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ protected BiFunction<WebElement, String, Boolean> deselect() {
+ return (webElement, name) -> {
+ List<WebElement> tds = webElement.findElements(tagName("td"));
+
+ if (!tds.get(0).getText().isEmpty()) {
+ if (tds.get(0).getText().equals(name)) {
+ tds.get(1).findElement(By.tagName("button")).click();
+ return true;
+ }
+ }
+
+ return false;
+ };
+ }
+
+ @Override
+ protected Function<WebElement, String> representation() {
+ return webElement -> webElement.findElements(tagName("td")).get(0).getText();
+ }
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
index 37777aa..af2a540 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java
@@ -21,6 +21,7 @@ import static org.openqa.selenium.By.tagName;
import org.jboss.arquillian.graphene.page.Page;
import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
@@ -62,6 +63,9 @@ public class Policies extends Form {
@Page
private RulePolicy rulePolicy;
+ @Page
+ private ClientPolicy clientPolicy;
+
public PoliciesTable policies() {
return table;
}
@@ -95,6 +99,10 @@ public class Policies extends Form {
rulePolicy.form().populate((RulePolicyRepresentation) expected);
rulePolicy.form().save();
return (P) rulePolicy;
+ } else if ("client".equals(type)) {
+ clientPolicy.form().populate((ClientPolicyRepresentation) expected);
+ clientPolicy.form().save();
+ return (P) clientPolicy;
}
return null;
@@ -120,6 +128,8 @@ public class Policies extends Form {
timePolicy.form().populate((TimePolicyRepresentation) representation);
} else if ("rules".equals(type)) {
rulePolicy.form().populate((RulePolicyRepresentation) representation);
+ } else if ("client".equals(type)) {
+ clientPolicy.form().populate((ClientPolicyRepresentation) representation);
}
return;
@@ -146,6 +156,8 @@ public class Policies extends Form {
return (P) timePolicy;
} else if ("rules".equals(type)) {
return (P) rulePolicy;
+ } else if ("client".equals(type)) {
+ return (P) clientPolicy;
}
}
}
@@ -173,6 +185,8 @@ public class Policies extends Form {
timePolicy.form().delete();
} else if ("rules".equals(type)) {
rulePolicy.form().delete();
+ } else if ("client".equals(type)) {
+ clientPolicy.form().delete();
}
return;
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java
index 2299200..f1bba0d 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/AggregatePolicyManagementTest.java
@@ -55,7 +55,7 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings
AuthorizationResource authorization = testRealmResource().clients().get(newClient.getId()).authorization();
PoliciesResource policies = authorization.policies();
- RolePoliciesResource roles = policies.roles();
+ RolePoliciesResource roles = policies.role();
roles.create(policyA);
@@ -71,7 +71,7 @@ public class AggregatePolicyManagementTest extends AbstractAuthorizationSettings
policyC.setName("Policy C");
policyC.addUser("test");
- policies.users().create(policyC);
+ policies.user().create(policyC);
}
@Test
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ClientPolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ClientPolicyManagementTest.java
new file mode 100644
index 0000000..2c95b83
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ClientPolicyManagementTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.testsuite.console.authorization;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+import org.keycloak.testsuite.console.page.clients.authorization.policy.ClientPolicy;
+import org.keycloak.testsuite.util.ClientBuilder;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ClientPolicyManagementTest extends AbstractAuthorizationSettingsTest {
+
+ @Before
+ public void configureTest() {
+ super.configureTest();
+ ClientsResource clients = testRealmResource().clients();
+ clients.create(ClientBuilder.create().clientId("client a").build());
+ clients.create(ClientBuilder.create().clientId("client b").build());
+ clients.create(ClientBuilder.create().clientId("client c").build());
+ }
+
+ @Test
+ public void testUpdate() throws InterruptedException {
+ authorizationPage.navigateTo();
+ ClientPolicyRepresentation expected = new ClientPolicyRepresentation();
+
+ expected.setName("Test Client Policy");
+ expected.setDescription("description");
+ expected.addClient("client a");
+ expected.addClient("client b");
+ expected.addClient("client c");
+
+ expected = createPolicy(expected);
+
+ String previousName = expected.getName();
+
+ expected.setName("Changed Test Client Policy");
+ expected.setDescription("Changed description");
+ expected.setLogic(Logic.NEGATIVE);
+
+ expected.setClients(expected.getClients().stream().filter(client -> !client.equals("client b")).collect(Collectors.toSet()));
+
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().update(previousName, expected);
+ assertAlertSuccess();
+
+ authorizationPage.navigateTo();
+ ClientPolicy actual = authorizationPage.authorizationTabs().policies().name(expected.getName());
+
+ assertPolicy(expected, actual);
+ }
+
+ @Test
+ public void testDeletePolicy() throws InterruptedException {
+ authorizationPage.navigateTo();
+ ClientPolicyRepresentation expected = new ClientPolicyRepresentation();
+
+ expected.setName("Test Client Policy");
+ expected.setDescription("description");
+ expected.addClient("client c");
+
+ expected = createPolicy(expected);
+ authorizationPage.navigateTo();
+ authorizationPage.authorizationTabs().policies().delete(expected.getName());
+ assertAlertSuccess();
+ authorizationPage.navigateTo();
+ assertNull(authorizationPage.authorizationTabs().policies().policies().findByName(expected.getName()));
+ }
+
+ private ClientPolicyRepresentation createPolicy(ClientPolicyRepresentation expected) {
+ ClientPolicy policy = authorizationPage.authorizationTabs().policies().create(expected);
+ assertAlertSuccess();
+ return assertPolicy(expected, policy);
+ }
+
+ private ClientPolicyRepresentation assertPolicy(ClientPolicyRepresentation expected, ClientPolicy policy) {
+ ClientPolicyRepresentation actual = policy.toRepresentation();
+
+ assertEquals(expected.getName(), actual.getName());
+ assertEquals(expected.getDescription(), actual.getDescription());
+ assertEquals(expected.getLogic(), actual.getLogic());
+
+ assertNotNull(actual.getClients());
+ assertEquals(expected.getClients().size(), actual.getClients().size());
+ assertEquals(0, actual.getClients().stream().filter(actualClient -> !expected.getClients().stream()
+ .filter(expectedClient -> actualClient.equals(expectedClient))
+ .findFirst().isPresent())
+ .count());
+ return actual;
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java
index 7eb6a94..4ff011a 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ResourcePermissionManagementTest.java
@@ -56,7 +56,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
AuthorizationResource authorization = testRealmResource().clients().get(newClient.getId()).authorization();
PoliciesResource policies = authorization.policies();
- RolePoliciesResource roles = policies.roles();
+ RolePoliciesResource roles = policies.role();
roles.create(policyA);
@@ -72,7 +72,7 @@ public class ResourcePermissionManagementTest extends AbstractAuthorizationSetti
policyC.setName("Policy C");
policyC.addUser("test");
- policies.users().create(policyC);
+ policies.user().create(policyC);
ResourcesResource resources = authorization.resources();
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java
index 7852c20..3dfd0c8 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/ScopePermissionManagementTest.java
@@ -55,7 +55,7 @@ public class ScopePermissionManagementTest extends AbstractAuthorizationSettings
AuthorizationResource authorization = testRealmResource().clients().get(newClient.getId()).authorization();
PoliciesResource policies = authorization.policies();
- RolePoliciesResource roles = policies.roles();
+ RolePoliciesResource roles = policies.role();
roles.create(policyA);
@@ -71,7 +71,7 @@ public class ScopePermissionManagementTest extends AbstractAuthorizationSettings
policyC.setName("Policy C");
policyC.addUser("test");
- policies.users().create(policyC);
+ policies.user().create(policyC);
authorization.scopes().create(new ScopeRepresentation("Scope A"));
authorization.scopes().create(new ScopeRepresentation("Scope B"));
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index aed7cbb..5d8d462 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -1434,8 +1434,8 @@ module.controller('ResourceServerPolicyClientDetailCtrl', function($scope, $rout
onInitUpdate : function(policy) {
var selectedClients = [];
- if (policy.config.clients) {
- var clients = eval(policy.config.clients);
+ if (policy.clients) {
+ var clients = policy.clients;
for (var i = 0; i < clients.length; i++) {
Client.get({realm: $route.current.params.realm, client: clients[i]}, function(data) {
@@ -1461,7 +1461,8 @@ module.controller('ResourceServerPolicyClientDetailCtrl', function($scope, $rout
clients.push($scope.selectedClients[i].id);
}
- $scope.policy.config.clients = JSON.stringify(clients);
+ $scope.policy.clients = clients;
+ delete $scope.policy.config;
},
onInitCreate : function() {
@@ -1481,7 +1482,8 @@ module.controller('ResourceServerPolicyClientDetailCtrl', function($scope, $rout
clients.push($scope.selectedClients[i].id);
}
- $scope.policy.config.clients = JSON.stringify(clients);
+ $scope.policy.clients = clients;
+ delete $scope.policy.config;
}
}, realm, client, $scope);
});
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html
index dda34a2..de2da05 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-client-detail.html
@@ -42,7 +42,7 @@
<div class="form-group clearfix" style="margin-top: -15px;">
<label class="col-md-2 control-label"></label>
<div class="col-sm-3">
- <table class="table table-striped table-bordered">
+ <table class="table table-striped table-bordered" id="selected-clients">
<thead>
<tr data-ng-hide="!selectedClients.length">
<th>{{:: 'clientId' | translate}}</th>
@@ -64,10 +64,10 @@
</div>
</div>
<div class="form-group clearfix">
- <label class="col-md-2 control-label" for="policy.logic">{{:: 'authz-policy-logic' | translate}}</label>
+ <label class="col-md-2 control-label" for="logic">{{:: 'authz-policy-logic' | translate}}</label>
<div class="col-sm-1">
- <select class="form-control" id="policy.logic"
+ <select class="form-control" id="logic"
data-ng-model="policy.logic">
<option value="POSITIVE">{{:: 'authz-policy-logic-positive' | translate}}</option>
<option value="NEGATIVE">{{:: 'authz-policy-logic-negative' | translate}}</option>