keycloak-aplcache
Changes
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java 4(+4 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java 9(+9 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java 4(+4 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java 4(+2 -2)
services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java 28(+18 -10)
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java 4(+4 -0)
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java 10(+9 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java 36(+30 -6)
themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html 2(+1 -1)
themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html 2(+1 -1)
themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html 2(+1 -1)
themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html 4(+2 -2)
themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-export.html 4(+2 -2)
themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-import.html 2(+1 -1)
themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html 4(+2 -2)
Details
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
index cc9e54b..a7ca83e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
@@ -65,6 +65,7 @@ public class ClientRepresentation {
private Boolean useTemplateScope;
private Boolean useTemplateMappers;
private ResourceServerRepresentation authorizationSettings;
+ private Map<String, Boolean> access;
public String getId() {
@@ -366,4 +367,12 @@ public class ClientRepresentation {
public void setAuthorizationSettings(ResourceServerRepresentation authorizationSettings) {
this.authorizationSettings = authorizationSettings;
}
+
+ public Map<String, Boolean> getAccess() {
+ return access;
+ }
+
+ public void setAccess(Map<String, Boolean> access) {
+ this.access = access;
+ }
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/GroupRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/GroupRepresentation.java
index 180db64..9c96970 100755
--- a/core/src/main/java/org/keycloak/representations/idm/GroupRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/GroupRepresentation.java
@@ -34,6 +34,7 @@ public class GroupRepresentation {
protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles;
protected List<GroupRepresentation> subGroups;
+ private Map<String, Boolean> access;
public String getId() {
return id;
@@ -97,4 +98,12 @@ public class GroupRepresentation {
public void setSubGroups(List<GroupRepresentation> subGroups) {
this.subGroups = subGroups;
}
+
+ public Map<String, Boolean> getAccess() {
+ return access;
+ }
+
+ public void setAccess(Map<String, Boolean> access) {
+ this.access = access;
+ }
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
index 2a4ec62..4dcea95 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
@@ -62,6 +62,7 @@ public class UserRepresentation {
protected List<SocialLinkRepresentation> socialLinks;
protected List<String> groups;
+ private Map<String, Boolean> access;
public String getSelf() {
return self;
@@ -264,4 +265,12 @@ public class UserRepresentation {
public void setDisableableCredentialTypes(Set<String> disableableCredentialTypes) {
this.disableableCredentialTypes = disableableCredentialTypes;
}
+
+ public Map<String, Boolean> getAccess() {
+ return access;
+ }
+
+ public void setAccess(Map<String, Boolean> access) {
+ this.access = access;
+ }
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
index 1a36d7a..4b620bc 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -34,6 +34,7 @@ import org.keycloak.migration.migrators.MigrateTo2_3_0;
import org.keycloak.migration.migrators.MigrateTo2_5_0;
import org.keycloak.migration.migrators.MigrateTo3_0_0;
import org.keycloak.migration.migrators.MigrateTo3_1_0;
+import org.keycloak.migration.migrators.MigrateTo3_2_0;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession;
@@ -60,7 +61,8 @@ public class MigrationModelManager {
new MigrateTo2_3_0(),
new MigrateTo2_5_0(),
new MigrateTo3_0_0(),
- new MigrateTo3_1_0()
+ new MigrateTo3_1_0(),
+ new MigrateTo3_2_0()
};
public static void migrate(KeycloakSession session) {
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java
new file mode 100644
index 0000000..0cb3eb6
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java
@@ -0,0 +1,70 @@
+/*
+ * 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.migration.migrators;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class MigrateTo3_2_0 implements Migration {
+ public static final ModelVersion VERSION = new ModelVersion("3.1.0");
+
+ @Override
+ public void migrate(KeycloakSession session) {
+ for (RealmModel realm : session.realms().getRealms()) {
+ ClientModel realmAccess = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+ if (realmAccess != null) {
+ addRoles(realmAccess);
+ }
+ ClientModel masterAdminClient = realm.getMasterAdminClient();
+ if (masterAdminClient != null) {
+ addRoles(masterAdminClient);
+
+ }
+
+ }
+ }
+
+ public void addRoles(ClientModel realmAccess) {
+ RoleModel queryClients = realmAccess.addRole(AdminRoles.QUERY_CLIENTS);
+ RoleModel queryUsers = realmAccess.addRole(AdminRoles.QUERY_USERS);
+ RoleModel queryGroups = realmAccess.addRole(AdminRoles.QUERY_GROUPS);
+
+ RoleModel viewClients = realmAccess.getRole(AdminRoles.VIEW_CLIENTS);
+ if (viewClients != null) {
+ viewClients.addCompositeRole(queryClients);
+ }
+ RoleModel viewUsers = realmAccess.getRole(AdminRoles.VIEW_USERS);
+ if (viewUsers != null) {
+ viewUsers.addCompositeRole(queryUsers);
+ viewUsers.addCompositeRole(queryGroups);
+ }
+ }
+
+ @Override
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java b/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
index 24455b8..cf605d1 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/AdminRoles.java
@@ -17,6 +17,8 @@
package org.keycloak.models;
+import java.util.Set;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -46,6 +48,11 @@ public class AdminRoles {
public static String MANAGE_EVENTS = "manage-events";
public static String MANAGE_AUTHORIZATION = "manage-authorization";
- public static String[] ALL_REALM_ROLES = {CREATE_CLIENT, VIEW_REALM, VIEW_USERS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, VIEW_AUTHORIZATION, MANAGE_REALM, MANAGE_USERS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS, MANAGE_AUTHORIZATION};
+ public static String QUERY_USERS = "query-users";
+ public static String QUERY_CLIENTS = "query-clients";
+ public static String QUERY_REALMS = "query-realms";
+ public static String QUERY_GROUPS = "query-groups";
+
+ public static String[] ALL_REALM_ROLES = {CREATE_CLIENT, VIEW_REALM, VIEW_USERS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, VIEW_AUTHORIZATION, MANAGE_REALM, MANAGE_USERS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS, MANAGE_AUTHORIZATION, QUERY_USERS, QUERY_CLIENTS, QUERY_REALMS, QUERY_GROUPS};
}
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 6637bd8..5ae5904 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -168,7 +168,6 @@ public class ModelToRepresentation {
return rep;
}
-
public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) {
UserRepresentation rep = new UserRepresentation();
rep.setId(user.getId());
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index e94ff3c..21df21f 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -198,6 +198,18 @@ public class RealmManager {
}
}
+ public void addQueryCompositeRoles(ClientModel realmAccess) {
+ RoleModel queryClients = realmAccess.getRole(AdminRoles.QUERY_CLIENTS);
+ RoleModel queryUsers = realmAccess.getRole(AdminRoles.QUERY_USERS);
+ RoleModel queryGroups = realmAccess.getRole(AdminRoles.QUERY_GROUPS);
+
+ RoleModel viewClients = realmAccess.getRole(AdminRoles.VIEW_CLIENTS);
+ viewClients.addCompositeRole(queryClients);
+ RoleModel viewUsers = realmAccess.getRole(AdminRoles.VIEW_USERS);
+ viewUsers.addCompositeRole(queryUsers);
+ viewUsers.addCompositeRole(queryGroups);
+ }
+
public String getRealmAdminClientId(RealmModel realm) {
return Constants.REALM_MANAGEMENT_CLIENT_ID;
@@ -327,6 +339,7 @@ public class RealmManager {
role.setScopeParamRequired(false);
adminRole.addCompositeRole(role);
}
+ addQueryCompositeRoles(realmAdminApp);
}
private void checkMasterAdminManagementRoles(RealmModel realm) {
@@ -340,6 +353,7 @@ public class RealmManager {
addAndSetAdminRole(r, masterAdminClient, adminRole);
}
}
+ addQueryCompositeRoles(masterAdminClient);
}
@@ -362,6 +376,7 @@ public class RealmManager {
for (String r : AdminRoles.ALL_REALM_ROLES) {
addAndSetAdminRole(r, realmAdminClient, adminRole);
}
+ addQueryCompositeRoles(realmAdminClient);
}
private void addAndSetAdminRole(String roleName, ClientModel parentClient, RoleModel parentRole) {
@@ -385,6 +400,7 @@ public class RealmManager {
addAndSetAdminRole(r, realmAdminClient, adminRole);
}
}
+ addQueryCompositeRoles(realmAdminClient);
}
@@ -502,7 +518,8 @@ public class RealmManager {
// I need to postpone impersonation because it needs "realm-management" client and its roles set
if (postponeImpersonationSetup) {
setupImpersonationService(realm);
- }
+ String realmAdminClientId = getRealmAdminClientId(realm);
+ }
if (postponeAdminCliSetup) {
setupAdminCli(realm);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index 36362cb..32a86be 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -195,6 +195,7 @@ public class ClientResource {
if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
representation.setAuthorizationServicesEnabled(authorization().isEnabled());
}
+ representation.setAccess(auth.clients().getAccess(client));
return representation;
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index 41b91be..88b5fdd 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -114,6 +114,7 @@ public class ClientsResource {
}
rep.add(representation);
+ representation.setAccess(auth.clients().getAccess(clientModel));
} else if (!viewableOnly) {
ClientRepresentation client = new ClientRepresentation();
client.setId(clientModel.getId());
@@ -126,7 +127,9 @@ public class ClientsResource {
ClientModel clientModel = realm.getClientByClientId(clientId);
if (clientModel != null) {
if (auth.clients().canView(clientModel)) {
- rep.add(ModelToRepresentation.toRepresentation(clientModel));
+ ClientRepresentation representation = ModelToRepresentation.toRepresentation(clientModel);
+ representation.setAccess(auth.clients().getAccess(clientModel));
+ rep.add(representation);
} else if (!viewableOnly && auth.clients().canList()){
ClientRepresentation client = new ClientRepresentation();
client.setId(clientModel.getId());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
index a5b7a6c..3de46b0 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
@@ -77,7 +77,7 @@ public class GroupResource {
@Context private UriInfo uriInfo;
- /**
+ /**
*
*
* @return
@@ -88,7 +88,11 @@ public class GroupResource {
public GroupRepresentation getGroup() {
this.auth.groups().requireView(group);
- return ModelToRepresentation.toGroupHierarchy(group, true);
+ GroupRepresentation rep = ModelToRepresentation.toGroupHierarchy(group, true);
+
+ rep.setAccess(auth.groups().getAccess(group));
+
+ return rep;
}
/**
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
index 51e26c0..25da468 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
@@ -19,6 +19,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
+import java.util.Map;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -73,4 +75,6 @@ public interface ClientPermissionEvaluator {
boolean canMapCompositeRoles(ClientModel client);
boolean canMapClientScopeRoles(ClientModel client);
+
+ Map<String, Boolean> getAccess(ClientModel client);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
index 06fa5d8..39f7b4d 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
@@ -492,4 +492,13 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
return root.evaluatePermission(resource, scope, server);
}
+ @Override
+ public Map<String, Boolean> getAccess(ClientModel client) {
+ Map<String, Boolean> map = new HashMap<>();
+ map.put("view", canView(client));
+ map.put("manage", canManage(client));
+ return map;
+ }
+
+
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
index 91ca5c5..450b074 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
@@ -18,6 +18,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.GroupModel;
+import java.util.Map;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -50,4 +52,6 @@ public interface GroupPermissionEvaluator {
boolean canManageMembers(GroupModel group);
void requireManageMembers(GroupModel group);
+
+ Map<String, Boolean> getAccess(GroupModel group);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
index a3277ba..5fcfbbb 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
@@ -33,8 +33,8 @@ public interface GroupPermissionManagement {
Policy viewMembersPermission(GroupModel group);
Policy manageMembersPermission(GroupModel group);
- Policy viewPermissionGroup(GroupModel group);
- Policy managePermissionGroup(GroupModel group);
+ Policy viewPermission(GroupModel group);
+ Policy managePermission(GroupModel group);
Resource resource(GroupModel group);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
index acf80c1..2223802 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
@@ -23,7 +23,6 @@ import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -125,7 +124,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override
public boolean canList() {
- return root.hasOneAdminRole(AdminRoles.VIEW_USERS, AdminRoles.MANAGE_USERS);
+ return root.hasOneAdminRole(AdminRoles.VIEW_USERS, AdminRoles.MANAGE_USERS, AdminRoles.QUERY_GROUPS);
}
@Override
@@ -164,11 +163,11 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
private void deletePermissions(GroupModel group) {
ResourceServer server = root.realmResourceServer();
if (server == null) return;
- Policy managePermission = managePermissionGroup(group);
+ Policy managePermission = managePermission(group);
if (managePermission != null) {
authz.getStoreFactory().getPolicyStore().delete(managePermission.getId());
}
- Policy viewPermission = viewPermissionGroup(group);
+ Policy viewPermission = viewPermission(group);
if (viewPermission != null) {
authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId());
}
@@ -201,7 +200,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
}
@Override
- public Policy viewPermissionGroup(GroupModel group) {
+ public Policy viewPermission(GroupModel group) {
ResourceServer server = root.realmResourceServer();
if (server == null) return null;
String viewPermissionName = getViewPermissionGroup(group);
@@ -209,7 +208,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
}
@Override
- public Policy managePermissionGroup(GroupModel group) {
+ public Policy managePermission(GroupModel group) {
ResourceServer server = root.realmResourceServer();
if (server == null) return null;
String managePermissionName = getManagePermissionGroup(group);
@@ -228,8 +227,8 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override
public Map<String, String> getPermissions(GroupModel group) {
Map<String, String> scopes = new HashMap<>();
- scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermissionGroup(group).getId());
- scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermissionGroup(group).getId());
+ scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(group).getId());
+ scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(group).getId());
scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
return scopes;
@@ -250,7 +249,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canManage();
- Policy policy = managePermissionGroup(group);
+ Policy policy = managePermission(group);
if (policy == null) {
return canManage();
}
@@ -283,7 +282,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canView();
- Policy policy = viewPermissionGroup(group);
+ Policy policy = viewPermission(group);
if (policy == null) {
return canView();
}
@@ -405,6 +404,15 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
}
}
+ @Override
+ public Map<String, Boolean> getAccess(GroupModel group) {
+ Map<String, Boolean> map = new HashMap<>();
+ map.put("view", canView(group));
+ map.put("manage", canManage(group));
+ return map;
+ }
+
+
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
index e276ae2..05ce719 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
@@ -18,6 +18,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.UserModel;
+import java.util.Map;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -47,4 +49,6 @@ public interface UserPermissionEvaluator {
boolean canImpersonate(UserModel user);
void requireImpersonate(UserModel user);
+
+ Map<String, Boolean> getAccess(UserModel user);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
index b095592..f8dd53b 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
@@ -281,7 +281,7 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
@Override
public boolean canQuery() {
- return canView();
+ return canView() || root.hasOneAdminRole(AdminRoles.QUERY_USERS);
}
@Override
@@ -392,6 +392,14 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
}
}
+ @Override
+ public Map<String, Boolean> getAccess(UserModel user) {
+ Map<String, Boolean> map = new HashMap<>();
+ map.put("view", canView(user));
+ map.put("manage", canManage(user));
+ return map;
+ }
+
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
index 44e4892..ca9d536 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
@@ -249,6 +249,7 @@ public class UserResource {
if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
rep.setEnabled(false);
}
+ rep.setAccess(auth.users().getAccess(user));
return rep;
}
@@ -761,6 +762,7 @@ public class UserResource {
if (group == null) {
throw new NotFoundException("Group not found");
}
+ auth.groups().requireManageMembers(group);
try {
if (user.isMemberOf(group)){
@@ -783,6 +785,7 @@ public class UserResource {
if (group == null) {
throw new NotFoundException("Group not found");
}
+ //auth.groups().requireManageMembers(group);
if (!user.isMemberOf(group)){
user.joinGroup(group);
adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index fc4bfee..6ed677f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -259,7 +259,9 @@ public class UsersResource {
boolean canViewGlobal = auth.users().canView();
for (UserModel user : userModels) {
if (!canViewGlobal && !auth.users().canView(user)) continue;
- results.add(ModelToRepresentation.toRepresentation(session, realm, user));
+ UserRepresentation userRep = ModelToRepresentation.toRepresentation(session, realm, user);
+ userRep.setAccess(auth.users().getAccess(user));
+ results.add(userRep);
}
return results;
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
index 72f3df9..d32ad79 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
@@ -56,6 +56,8 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
//@Ignore
public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
+ public static final String CLIENT_NAME = "application";
+
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation testRealmRep = new RealmRepresentation();
@@ -70,7 +72,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
RoleModel realmRole = realm.addRole("realm-role");
RoleModel realmRole2 = realm.addRole("realm-role2");
- ClientModel client1 = realm.addClient("role-namespace");
+ ClientModel client1 = realm.addClient(CLIENT_NAME);
RoleModel client1Role = client1.addRole("client-role");
GroupModel group = realm.createGroup("top");
@@ -80,7 +82,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
compositeRole.addCompositeRole(mapperRole);
compositeRole.addCompositeRole(managerRole);
- // realm-role and role-namespace.client-role will have a role policy associated with their map-role permission
+ // realm-role and application.client-role will have a role policy associated with their map-role permission
{
permissions.roles().setPermissionsEnabled(client1Role, true);
Policy mapRolePermission = permissions.roles().mapRolePermission(client1Role);
@@ -122,7 +124,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
public static void setupUsers(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
- ClientModel client = realm.getClientByClientId("role-namespace");
+ ClientModel client = realm.getClientByClientId(CLIENT_NAME);
RoleModel realmRole = realm.getRole("realm-role");
RoleModel realmRole2 = realm.getRole("realm-role2");
RoleModel clientRole = client.getRole("client-role");
@@ -131,6 +133,9 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleModel compositeRole = realm.getRole("composite-role");
ClientModel realmManagementClient = realm.getClientByClientId("realm-management");
RoleModel adminRole = realmManagementClient.getRole(AdminRoles.REALM_ADMIN);
+ RoleModel queryGroupsRole = realmManagementClient.getRole(AdminRoles.QUERY_GROUPS);
+ RoleModel queryUsersRole = realmManagementClient.getRole(AdminRoles.QUERY_USERS);
+ RoleModel queryClientsRole = realmManagementClient.getRole(AdminRoles.QUERY_CLIENTS);
UserModel nomapAdmin = session.users().addUser(realm, "nomap-admin");
nomapAdmin.setEnabled(true);
@@ -168,6 +173,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
groupMember.joinGroup(group);
groupMember.setEnabled(true);
UserModel groupManager = session.users().addUser(realm, "groupManager");
+ groupManager.grantRole(queryGroupsRole);
+ groupManager.grantRole(queryUsersRole);
groupManager.setEnabled(true);
groupManager.grantRole(mapperRole);
session.userCredentialManager().updateCredential(realm, groupManager, UserCredentialModel.password("password"));
@@ -175,6 +182,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
UserModel groupManagerNoMapper = session.users().addUser(realm, "noMapperGroupManager");
groupManagerNoMapper.setEnabled(true);
session.userCredentialManager().updateCredential(realm, groupManagerNoMapper, UserCredentialModel.password("password"));
+ groupManagerNoMapper.grantRole(queryGroupsRole);
+ groupManagerNoMapper.grantRole(queryUsersRole);
UserPolicyRepresentation groupManagerRep = new UserPolicyRepresentation();
groupManagerRep.setName("groupManagers");
@@ -184,10 +193,12 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
Policy groupManagerPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(groupManagerRep, server);
Policy groupManagerPermission = permissions.groups().manageMembersPermission(group);
groupManagerPermission.addAssociatedPolicy(groupManagerPolicy);
+ permissions.groups().viewPermission(group).addAssociatedPolicy(groupManagerPolicy);
UserModel clientMapper = session.users().addUser(realm, "clientMapper");
clientMapper.setEnabled(true);
clientMapper.grantRole(managerRole);
+ clientMapper.grantRole(queryUsersRole);
session.userCredentialManager().updateCredential(realm, clientMapper, UserCredentialModel.password("password"));
Policy clientMapperPolicy = permissions.clients().mapRolesPermission(client);
UserPolicyRepresentation userRep = new UserPolicyRepresentation();
@@ -196,6 +207,19 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
Policy userPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(userRep, permissions.clients().resourceServer(client));
clientMapperPolicy.addAssociatedPolicy(userPolicy);
+ UserModel clientManager = session.users().addUser(realm, "clientManager");
+ clientManager.setEnabled(true);
+ clientManager.grantRole(queryClientsRole);
+ session.userCredentialManager().updateCredential(realm, clientManager, UserCredentialModel.password("password"));
+
+ Policy clientManagerPolicy = permissions.clients().managePermission(client);
+ userRep = new UserPolicyRepresentation();
+ userRep.setName("clientManager");
+ userRep.addUser("clientManager");
+ userPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(userRep, permissions.clients().resourceServer(client));
+ clientManagerPolicy.addAssociatedPolicy(userPolicy);
+
+
@@ -206,7 +230,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RealmModel realm = session.realms().getRealmByName(TEST);
RoleModel realmRole = realm.getRole("realm-role");
RoleModel realmRole2 = realm.getRole("realm-role2");
- ClientModel client = realm.getClientByClientId("role-namespace");
+ ClientModel client = realm.getClientByClientId(CLIENT_NAME);
RoleModel clientRole = client.getRole("client-role");
// test authorized
@@ -309,7 +333,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
realmRole2Set.add(realmRole2);
- ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId("role-namespace").get(0);
+ ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId(CLIENT_NAME).get(0);
RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
List<RoleRepresentation> clientRoleSet = new LinkedList<>();
clientRoleSet.add(clientRole);
@@ -463,7 +487,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
realmRole2Set.add(realmRole);
- ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId("role-namespace").get(0);
+ ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId(CLIENT_NAME).get(0);
RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
List<RoleRepresentation> clientRoleSet = new LinkedList<>();
clientRoleSet.add(clientRole);
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/app.js b/themes/src/main/resources/theme/base/admin/resources/js/app.js
index 2864559..c4e870f 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -1398,9 +1398,6 @@ module.config([ '$routeProvider', function($routeProvider) {
realm : function(RealmLoader) {
return RealmLoader();
},
- clients : function(ClientListLoader) {
- return ClientListLoader();
- },
serverInfo : function(ServerInfoLoader) {
return ServerInfoLoader();
}
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 945fc5a..515eb99 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -728,9 +728,9 @@ module.controller('ClientImportCtrl', function($scope, $location, $upload, realm
});
-module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications, filterFilter) {
+module.controller('ClientListCtrl', function($scope, realm, Client, serverInfo, $route, Dialog, Notifications, filterFilter) {
$scope.realm = realm;
- $scope.clients = clients;
+ $scope.clients = Client.query({realm: realm.realm, viewableOnly: true});
$scope.currentPage = 1;
$scope.currentPageInput = 1;
$scope.pageSize = 20;
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index e3d3070..ab4e72a 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1,81 +1,95 @@
-module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications, ServerInfo) {
- $scope.authUrl = authUrl;
- $scope.resourceUrl = resourceUrl;
- $scope.auth = Auth;
- $scope.serverInfo = ServerInfo.get();
-
- function getAccess(role) {
- if (!Current.realm) {
- return false;
- }
-
- var realmAccess = Auth.user && Auth.user['realm_access'];
+function getAccess(Auth, Current, role) {
+ if (!Current.realm)return false;
+ var realmAccess = Auth.user && Auth.user['realm_access'];
+ if (realmAccess) {
+ realmAccess = realmAccess[Current.realm.realm];
if (realmAccess) {
- realmAccess = realmAccess[Current.realm.realm];
- if (realmAccess) {
- return realmAccess.indexOf(role) >= 0;
- }
+ return realmAccess.indexOf(role) >= 0;
}
- return false;
}
+ return false;
+}
- $scope.access = {
+function getAccessObject(Auth, Current) {
+ return {
get createRealm() {
return Auth.user && Auth.user.createRealm;
},
+ get queryUsers() {
+ return getAccess(Auth, Current, 'query-users') || this.viewUsers;
+ },
+
+ get queryGroups() {
+ return getAccess(Auth, Current, 'query-groups') || this.viewUsers;
+ },
+
+ get queryClients() {
+ return getAccess(Auth, Current, 'query-clients') || this.viewClients;
+ },
+
get viewRealm() {
- return getAccess('view-realm') || getAccess('manage-realm') || this.manageRealm;
+ return getAccess(Auth, Current, 'view-realm') || getAccess(Auth, Current, 'manage-realm') || this.manageRealm;
},
get viewClients() {
- return getAccess('view-clients') || getAccess('manage-clients') || this.manageClients;
+ return getAccess(Auth, Current, 'view-clients') || getAccess(Auth, Current, 'manage-clients') || this.manageClients;
},
get viewUsers() {
- return getAccess('view-users') || getAccess('manage-users') || this.manageClients;
+ return getAccess(Auth, Current, 'view-users') || getAccess(Auth, Current, 'manage-users') || this.manageClients;
},
get viewEvents() {
- return getAccess('view-events') || getAccess('manage-events') || this.manageClients;
+ return getAccess(Auth, Current, 'view-events') || getAccess(Auth, Current, 'manage-events') || this.manageClients;
},
get viewIdentityProviders() {
- return getAccess('view-identity-providers') || getAccess('manage-identity-providers') || this.manageIdentityProviders;
+ return getAccess(Auth, Current, 'view-identity-providers') || getAccess(Auth, Current, 'manage-identity-providers') || this.manageIdentityProviders;
},
get viewAuthorization() {
- return getAccess('view-authorization') || this.manageAuthorization;
+ return getAccess(Auth, Current, 'view-authorization') || this.manageAuthorization;
},
get manageRealm() {
- return getAccess('manage-realm');
+ return getAccess(Auth, Current, 'manage-realm');
},
get manageClients() {
- return getAccess('manage-clients');
+ return getAccess(Auth, Current, 'manage-clients');
},
get manageUsers() {
- return getAccess('manage-users');
+ return getAccess(Auth, Current, 'manage-users');
},
get manageEvents() {
- return getAccess('manage-events');
+ return getAccess(Auth, Current, 'manage-events');
},
get manageIdentityProviders() {
- return getAccess('manage-identity-providers');
+ return getAccess(Auth, Current, 'manage-identity-providers');
},
get manageAuthorization() {
- return getAccess('manage-authorization');
+ return getAccess(Auth, Current, 'manage-authorization');
},
get impersonation() {
- return getAccess('impersonation');
+ return getAccess(Auth, Current, 'impersonation');
}
};
+}
+
+
+module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications, ServerInfo) {
+ $scope.authUrl = authUrl;
+ $scope.resourceUrl = resourceUrl;
+ $scope.auth = Auth;
+ $scope.serverInfo = ServerInfo.get();
+
+ $scope.access = getAccessObject(Auth, Current);
$scope.$watch(function() {
return $location.path();
@@ -85,20 +99,36 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
});
});
-module.controller('HomeCtrl', function(Realm, Auth, $location) {
+module.controller('HomeCtrl', function(Realm, Auth, Current, $location) {
+
Realm.query(null, function(realms) {
var realm;
if (realms.length == 1) {
- realm = realms[0].realm;
+ realm = realms[0];
} else if (realms.length == 2) {
if (realms[0].realm == Auth.user.realm) {
- realm = realms[1].realm;
+ realm = realms[1];
} else if (realms[1].realm == Auth.user.realm) {
- realm = realms[0].realm;
+ realm = realms[0];
}
}
if (realm) {
- $location.url('/realms/' + realm);
+ Current.realms = realms;
+ Current.realm = realm;
+ var access = getAccessObject(Auth, Current);
+ if (access.viewRealm || access.manageRealm) {
+ $location.url('/realms/' + realm.realm );
+ } else if (access.queryClients) {
+ $location.url('/realms/' + realm.realm + "/clients");
+ } else if (access.viewIdentityProviders) {
+ $location.url('/realms/' + realm.realm + "/identity-provider-settings");
+ } else if (access.queryUsers) {
+ $location.url('/realms/' + realm.realm + "/users");
+ } else if (access.queryGroups) {
+ $location.url('/realms/' + realm.realm + "/groups");
+ } else if (access.viewEvents) {
+ $location.url('/realms/' + realm.realm + "/events");
+ }
} else {
$location.url('/realms');
}
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html
index 50241b2..bb6d7b6 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html
@@ -6,7 +6,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
+ <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!client.access.manage || !access.manageAuthorization">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
index 988c1fa..5b423d0 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
@@ -7,7 +7,7 @@
<kc-tabs-client-role></kc-tabs-client-role>
- <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
+ <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!client.access.manage || !access.manageAuthorization">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html
index 61770c9..897a0ed 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html
@@ -6,7 +6,7 @@
<kc-tabs-group></kc-tabs-group>
- <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
+ <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!group.access.manage || !access.manageAuthorization">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
index 4a6312b..e729582 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!client.access.manage">
<legend><span class="text">{{:: 'basic-configuration' | translate}}</span></legend>
<fieldset >
<div class="form-group clearfix">
@@ -31,7 +31,7 @@
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button data-kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button data-kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
@@ -43,7 +43,7 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
- <th class="kc-table-actions" colspan="5" data-ng-show="access.manageClients">
+ <th class="kc-table-actions" colspan="5" data-ng-show="client.access.manage">
<div class="pull-right">
<a class="btn btn-default" tooltip="Manually register cluster node. This is usually not needed as cluster node should be registered automatically by adapter"
tooltip-trigger="mouseover mouseout" tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'register-node-manually' | translate}}</a>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html
index 440994f..98820eb 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering-node.html
@@ -10,10 +10,10 @@
<h1 data-ng-show="create">{{:: 'add-node' | translate}}</h1>
<h1 data-ng-hide="create">
{{node.host|capitalize}}
- <i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="access.manageClients" data-ng-click="unregisterNode()"></i>
+ <i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="client.access.manage" data-ng-click="unregisterNode()"></i>
</h1>
- <form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageClients" data-ng-show="create || registered">
+ <form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!client.access.manage" data-ng-show="create || registered">
<div class="form-group">
<label class="col-md-2 control-label" for="host">{{:: 'host' | translate}}</label>
<div class="col-sm-6">
@@ -27,7 +27,7 @@
</div>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button data-kc-save data-ng-show="create">{{:: 'save' | translate}}</button>
</div>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
index b1b1062..3871774 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="clientAuthenticatorType"> {{:: 'client-authenticator' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html
index 1d59078..a2d59e1 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-generic.html
@@ -1,11 +1,11 @@
<div>
- <form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!access.manageClients" data-ng-show="currentAuthenticatorConfigProperties.length > 0" data-ng-controller="ClientGenericCredentialsCtrl">
+ <form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!client.access.manage" data-ng-show="currentAuthenticatorConfigProperties.length > 0" data-ng-controller="ClientGenericCredentialsCtrl">
<fieldset>
<kc-provider-config realm="realm" config="client.attributes" properties="currentAuthenticatorConfigProperties"></kc-provider-config>
</fieldset>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html
index 29f6524..8df035c 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt.html
@@ -1,4 +1,4 @@
- <div class="form-horizontal no-margin-top" name="keyForm" novalidate kc-read-only="!access.manageClients" data-ng-controller="ClientSignedJWTCtrl">
+ <div class="form-horizontal no-margin-top" name="keyForm" novalidate kc-read-only="!client.access.manage" data-ng-controller="ClientSignedJWTCtrl">
<div class="form-group">
<label class="col-md-2 control-label" for="useJwksUrl">{{:: 'use-jwks-url' | translate}}</label>
@@ -63,7 +63,7 @@
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button class="btn btn-default" type="submit" data-ng-click="generateSigningKey()">{{:: 'gen-new-keys-and-cert' | translate}}</button>
<button data-ng-disabled="useJwksUrl" class="btn btn-default" type="submit" data-ng-click="importCertificate()">{{:: 'import-certificate' | translate}}</button>
<button kc-save data-ng-disabled="!changed" data-ng-click="save()">{{:: 'save' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-export.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-export.html
index 382f612..8fbd079 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-export.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-export.html
@@ -9,7 +9,7 @@
<h1>{{:: 'generate-private-key' | translate}}</h1>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
@@ -48,7 +48,7 @@
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button class="btn btn-primary" type="submit" data-ng-click="download()">{{:: 'generate-and-download' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-import.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-import.html
index 9968a31..f96c4f0 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-import.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-jwt-key-import.html
@@ -9,7 +9,7 @@
<h1>{{:: 'import-client-certificate' | translate}}</h1>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html
index 744ea80..d4fb071 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-credentials-secret.html
@@ -1,5 +1,5 @@
<div>
- <form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!access.manageClients" data-ng-controller="ClientSecretCtrl">
+ <form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!client.access.manage" data-ng-controller="ClientSecretCtrl">
<div class="form-group">
<label class="col-md-2 control-label" for="secret">{{:: 'secret' | translate}}</label>
<div class="col-sm-6">
@@ -7,7 +7,7 @@
<div class="col-sm-6">
<input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret">
</div>
- <div class="col-sm-6" data-ng-show="access.manageClients">
+ <div class="col-sm-6" data-ng-show="client.access.manage">
<button type="submit" data-ng-click="changePassword()" class="btn btn-default">{{:: 'regenerate-secret' | translate}}</button>
</div>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index 3eb084f..5f24b21 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="clientForm" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="clientId">{{:: 'client-id' | translate}}</label>
@@ -391,7 +391,7 @@
</fieldset>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
index e2bc22e..e8d6259 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-keys.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
@@ -137,7 +137,7 @@
kc-select-action="click" readonly>{{keyInfo.certificate}}</textarea>
</div>
</div>
- <div class="form-group" data-ng-show="access.manageRealm">
+ <div class="form-group" data-ng-show="client.access.manage">
<div class="pull-right">
<button class="btn btn-primary" type="submit" data-ng-click="generate()">Generate new keys</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index 51aaa20..03ebf5c 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -42,7 +42,7 @@
</td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</td>
<td class="kc-action-cell" data-ng-click="exportClient(client)">{{:: 'export' | translate}}</td>
- <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
+ <td class="kc-action-cell" data-ng-show="client.access.manage" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
</tr>
<tr data-ng-show="(clients | filter:search).length == 0">
<td class="text-muted" colspan="4" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
index ba9b9bf..5648c19 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group" ng-show="client.clientTemplate">
<label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Mappers</label>
@@ -35,7 +35,7 @@
</div>
</div>
- <div class="pull-right" data-ng-show="access.manageClients">
+ <div class="pull-right" data-ng-show="client.access.manage">
<a class="btn btn-default" href="#/create/client/{{realm.realm}}/{{client.id}}/mappers">{{:: 'create' | translate}}</a>
<a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">{{:: 'add-builtin' | translate}}</a>
</div>
@@ -55,7 +55,7 @@
<td>{{mapperTypes[mapper.protocolMapper].category}}</td>
<td>{{mapperTypes[mapper.protocolMapper].name}}</td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">{{:: 'edit' | translate}}</td>
- <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeMapper(mapper)">{{:: 'delete' | translate}}</td>
+ <td class="kc-action-cell" data-ng-show="client.access.manage" data-ng-click="removeMapper(mapper)">{{:: 'delete' | translate}}</td>
</tr>
<tr data-ng-show="mappers.length == 0">
<td>{{:: 'no-mappers-available' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
index 04c2339..6537779 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html
@@ -45,7 +45,7 @@
</tbody>
</table>
- <div data-ng-show="access.manageRealm">
+ <div data-ng-show="client.access.manage">
<button class="btn btn-primary" data-ng-click="add()">{{:: 'add-selected' | translate}}</button>
</div>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
index 38560e8..761b337 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label>
@@ -18,7 +18,7 @@
</div>
</fieldset>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button type="submit" data-ng-click="clear()" class="btn btn-default">{{:: 'clear' | translate}}</button>
<button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">{{:: 'set-to-now' | translate}}</button>
<button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip-trigger="mouseover mouseout" tooltip="{{:: 'client-revoke.push.tooltip' | translate}}" tooltip-placement="bottom">{{:: 'push' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
index 9c3e215..d21d7ef 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-detail.html
@@ -10,7 +10,7 @@
<kc-tabs-client-role></kc-tabs-client-role>
- <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group">
@@ -47,13 +47,13 @@
</fieldset>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="create && client.access.manages">
<button kc-save>{{:: 'save' | translate}}</button>
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="!create && client.access.manage">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
index da4d49d..458b412 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
@@ -10,7 +10,7 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
- <th class="kc-table-actions" colspan="5" data-ng-show="access.manageClients">
+ <th class="kc-table-actions" colspan="5" data-ng-show="client.access.manage">
<div class="pull-right">
<a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">{{:: 'add-role' | translate}}</a>
</div>
@@ -29,7 +29,7 @@
<td translate="{{role.composite}}"></td>
<td>{{role.description}}</td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{:: 'edit' | translate}}</td>
- <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
+ <td class="kc-action-cell" data-ng-show="client.access.manage" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
</tr>
<tr data-ng-show="!roles || roles.length == 0">
<td>{{:: 'no-client-roles-available' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
index 2165165..753f564 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-export.html
@@ -9,7 +9,7 @@
<h1>{{:: 'export-saml-key' | translate}} {{client.clientId|capitalize}}</h1>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
@@ -55,7 +55,7 @@
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button class="btn btn-primary" type="submit" data-ng-click="download()">{{:: 'download' | translate}}</button>
</div>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
index dec13a8..b479058 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-key-import.html
@@ -9,7 +9,7 @@
<h1>{{:: 'import-saml-key' | translate}} {{client.clientId|capitalize}}</h1>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
index 52e5468..c5374bb 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
@@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client>
- <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
+ <form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.manage">
<fieldset class="form-group col-sm-10" data-ng-show="client.attributes['saml.client.signature'] == 'true'">
<legend uncollapsed><span class="text">{{:: 'signing-key' | translate}}</span> <kc-tooltip>{{:: 'saml-signing-key' | translate}}</kc-tooltip></legend>
<div class="form-group" data-ng-hide="!signingKeyInfo.privateKey">
@@ -27,7 +27,7 @@
</div>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button class="btn btn-default" type="submit" data-ng-click="generateSigningKey()">{{:: 'generate-new-keys' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-click="importSigningKey()">{{:: 'import' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">{{:: 'export' | translate}}</button>
@@ -53,7 +53,7 @@
</div>
</div>
<div class="form-group">
- <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="client.access.manage">
<button class="btn btn-default" type="submit" data-ng-click="generateEncryptionKey()">{{:: 'generate-new-keys' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-click="importEncryptionKey()">{{:: 'import' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">{{:: 'export' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
index fc10e6b..482ef5b 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-mappings.html
@@ -9,7 +9,7 @@
<h2><span>{{client.clientId}}</span> {{:: 'scope-mappings' | translate}} </h2>
<p class="subtitle"></p>
- <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageClients">
+ <form class="form-horizontal" name="allowScope" novalidate kc-read-only="!client.access.manage">
<fieldset class="border-top">
<div class="form-group" ng-show="client.clientTemplate">
<label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Scope</label>
@@ -41,7 +41,7 @@
</fieldset>
</form>
- <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-hide="hideRoleSelector()">
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.manage" data-ng-hide="hideRoleSelector()">
<div class="form-group">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
index 27f967d..24b2594 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
@@ -10,7 +10,7 @@
<h2><span>{{client.clientId}}</span> {{:: 'service-accounts' | translate}} </h2>
<p class="subtitle"></p>
- <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-show="client.serviceAccountsEnabled">
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.manage" data-ng-show="client.serviceAccountsEnabled">
<div class="form-group">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10">
@@ -102,7 +102,7 @@
</div>
</form>
- <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-show="!client.serviceAccountsEnabled">
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.manage" data-ng-show="!client.serviceAccountsEnabled">
<legend><span class="text" translate="service-account-is-not-enabled-for" translate-values="{client: client.clientId}"></span></legend>
</form>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-attributes.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-attributes.html
index 26d30e1..10e3d8f 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-attributes.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-attributes.html
@@ -6,7 +6,7 @@
<kc-tabs-user></kc-tabs-user>
- <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageUsers">
+ <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!user.access.manage">
<table class="table table-striped table-bordered">
<thead>
<tr>
@@ -29,7 +29,7 @@
</tbody>
</table>
- <div class="form-group" data-ng-show="access.manageUsers">
+ <div class="form-group" data-ng-show="user.access.manage">
<div class="col-md-12">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
index f1998f8..d7259fd 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
@@ -7,7 +7,7 @@
<kc-tabs-user></kc-tabs-user>
- <form class="form-horizontal" name="userForm" novalidate kc-read-only="!access.manageUsers">
+ <form class="form-horizontal" name="userForm" novalidate kc-read-only="!create && !user.access.manage">
<fieldset class="border-top">
<div class="form-group">
@@ -62,7 +62,7 @@
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="userEnabled">{{:: 'user-enabled' | translate}}</label>
<div class="col-md-6">
- <input ng-model="user.enabled" name="userEnabled" id="userEnabled" ng-disabled="!access.manageUsers" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
+ <input ng-model="user.enabled" name="userEnabled" id="userEnabled" ng-disabled="!create && !user.access.manage" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>{{:: 'user-enabled.tooltip' | translate}}</kc-tooltip>
</div>
@@ -93,7 +93,7 @@
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="emailVerified">{{:: 'email-verified' | translate}}</label>
<div class="col-md-6">
- <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" ng-disabled="!access.manageUsers" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
+ <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" ng-disabled="!create && !user.access.manage" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>{{:: 'email-verified.tooltip' | translate}}</kc-tooltip>
</div>
@@ -138,7 +138,7 @@
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
- <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
+ <div class="col-md-10 col-md-offset-2" data-ng-show="!create && !user.access.manage">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
index f1dd03b..569e1fc 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
@@ -55,7 +55,7 @@
<td class="clip">{{user.firstName}}</td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/users/{{user.id}}">{{:: 'edit' | translate}}</td>
<td data-ng-show="serverInfo.profileInfo.disabledFeatures.indexOf('IMPERSONATION') == -1 && access.impersonation" class="kc-action-cell" data-ng-click="impersonate(user.id)">{{:: 'impersonate' | translate}}</td>
- <td data-ng-show="access.manageUsers" class="kc-action-cell" data-ng-click="removeUser(user)">{{:: 'delete' | translate}}</td>
+ <td data-ng-show="user.access.manage" class="kc-action-cell" data-ng-click="removeUser(user)">{{:: 'delete' | translate}}</td>
</tr>
<tr data-ng-show="!users || users.length == 0">
<td class="text-muted" data-ng-show="!users">{{:: 'users.instruction' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
index 1fe11e9..02c1959 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
@@ -8,9 +8,9 @@
<table class="table table-striped table-bordered">
<thead>
- <tr data-ng-show="access.manageUsers">
+ <tr data-ng-show="user.access.manage">
<th class="kc-table-actions" colspan="6">
- <div class="pull-right" data-ng-show="access.manageUsers">
+ <div class="pull-right" data-ng-show="user.access.manage">
<a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">{{:: 'logout-all-sessions' | translate}}</a>
</div>
</th>
@@ -20,7 +20,7 @@
<th>{{:: 'started' | translate}}</th>
<th>{{:: 'last-access' | translate}}</th>
<th>{{:: 'clients' | translate}}</th>
- <th data-ng-show="access.manageUsers">{{:: 'action' | translate}}</th>
+ <th data-ng-show="user.access.manage">{{:: 'action' | translate}}</th>
</tr>
</thead>
<tbody>
@@ -34,7 +34,7 @@
</div>
</ul>
</td>
- <td class="kc-action-cell" data-ng-show="access.manageUsers" ng-click="logoutSession(session.id)">{{:: 'logout' | translate}}</td>
+ <td class="kc-action-cell" data-ng-show="user.access.manage" ng-click="logoutSession(session.id)">{{:: 'logout' | translate}}</td>
</tr>
</tbody>
</table>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
index 25d22d7..53b0a3d 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
@@ -16,7 +16,7 @@
</div>
</div>
- <div class="nav-category" data-ng-show="current.realm">
+ <div class="nav-category" data-ng-show="current.realm && (access.viewRealm || access.queryClients || access.viewIdentityProviders)">
<h2>{{:: 'configure' | translate}}</h2>
<ul class="nav nav-pills nav-stacked">
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2]
@@ -32,7 +32,7 @@
|| path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'clients') && 'active'">
<a href="#/realms/{{realm.realm}}"><span class="pficon pficon-settings"></span> {{:: 'realm-settings' | translate}}</a>
</li>
- <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'clients' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients"><i class="fa fa-cube"></i> {{:: 'clients' | translate}}</a></li>
+ <li data-ng-show="access.queryClients" data-ng-class="(path[2] == 'clients' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients"><i class="fa fa-cube"></i> {{:: 'clients' | translate}}</a></li>
<li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'client-templates' || path[3] == 'client-templates') && 'active'"><a href="#/realms/{{realm.realm}}/client-templates"><i class="fa fa-cubes"></i> {{:: 'client-templates' | translate}}</a></li>
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || path[2] == 'default-roles') && 'active'"><a href="#/realms/{{realm.realm}}/roles"><i class="fa fa-tasks"></i> {{:: 'roles' | translate}}</a></li>
<li data-ng-show="access.viewIdentityProviders" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> {{:: 'identity-providers' | translate}}</a></li>
@@ -45,12 +45,12 @@
</ul>
</div>
- <div class="nav-category" data-ng-show="current.realm">
+ <div class="nav-category" data-ng-show="current.realm && (access.viewRealm || access.queryGroups || access.queryUsers || access.viewEvents)">
<h2>{{:: 'manage' | translate}}</h2>
<ul class="nav nav-pills nav-stacked">
- <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'groups'
+ <li data-ng-show="access.queryGroups" data-ng-class="(path[2] == 'groups'
|| path[2] == 'default-groups') && 'active'"><a href="#/realms/{{realm.realm}}/groups"><span class="pficon pficon-users"></span> {{:: 'groups' | translate}}</a></li>
- <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users') && 'active'"><a href="#/realms/{{realm.realm}}/users"><span class="pficon pficon-user"></span> {{:: 'users' | translate}}</a></li>
+ <li data-ng-show="access.queryUsers" data-ng-class="(path[2] == 'users') && 'active'"><a href="#/realms/{{realm.realm}}/users"><span class="pficon pficon-user"></span> {{:: 'users' | translate}}</a></li>
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm"><i class="fa fa-clock-o"></i> {{:: 'sessions' | translate}}</a></li>
<li data-ng-show="access.viewEvents" data-ng-class="(path[2] == 'events'
|| path[2] == 'events-settings'
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
index a18c31f..cf46c2e 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
@@ -3,7 +3,7 @@
<h1 data-ng-show="create">{{:: 'add-client' | translate}}</h1>
<h1 data-ng-hide="create">
{{client.clientId|capitalize}}
- <i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="access.manageClients" data-ng-click="removeClient()"></i>
+ <i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="client.access.manage" data-ng-click="removeClient()"></i>
</h1>
<ul class="nav nav-tabs" data-ng-hide="create && !path[4]">
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html
index 66dad39..9c372e3 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html
@@ -8,7 +8,7 @@
<ul class="nav nav-tabs" data-ng-show="!create">
<li ng-class="{active: !path[4] && path[0] != 'create'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}">{{:: 'details' | translate}}</a></li>
<li ng-class="{active: path[4] == 'user-attributes'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/user-attributes">{{:: 'attributes' | translate}}</a></li>
- <li ng-class="{active: path[4] == 'user-credentials'}" data-ng-show="access.manageUsers"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/user-credentials">{{:: 'credentials' | translate}}</a></li>
+ <li ng-class="{active: path[4] == 'user-credentials'}" data-ng-show="user.access.manage"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/user-credentials">{{:: 'credentials' | translate}}</a></li>
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/users/{{user.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
<li ng-class="{active: path[4] == 'groups'}" ><a href="#/realms/{{realm.realm}}/users/{{user.id}}/groups">{{:: 'groups' | translate}}</a></li>
<li ng-class="{active: path[4] == 'consents'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/consents">{{:: 'consents' | translate}}</a></li>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-users.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-users.html
index 8cc17ea..1c9dc4a 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-users.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-users.html
@@ -3,7 +3,7 @@
<ul class="nav nav-tabs">
<li ng-class="{active: path[2] == 'users'}"><a href="#/realms/{{realm.realm}}/users">{{:: 'lookup' | translate}}</a></li>
- <li ng-class="{active: path[2] == 'users-permissions'}">
+ <li ng-class="{active: path[2] == 'users-permissions'}"data-ng-show="access.viewRealm">
<a href="#/realms/{{realm.realm}}/users-permissions">{{:: 'authz-permissions' | translate}}</a>
<kc-tooltip>{{:: 'manage-permissions-users.tooltip' | translate}}</kc-tooltip>
</li>