console work

This commit is contained in:
Bill Burke 2017-06-07 16:29:43 -04:00
parent 536a57a514
commit 94528976d4
56 changed files with 396 additions and 173 deletions

View file

@ -65,6 +65,7 @@ public class ClientRepresentation {
private Boolean useTemplateScope; private Boolean useTemplateScope;
private Boolean useTemplateMappers; private Boolean useTemplateMappers;
private ResourceServerRepresentation authorizationSettings; private ResourceServerRepresentation authorizationSettings;
private Map<String, Boolean> access;
public String getId() { public String getId() {
@ -366,4 +367,12 @@ public class ClientRepresentation {
public void setAuthorizationSettings(ResourceServerRepresentation authorizationSettings) { public void setAuthorizationSettings(ResourceServerRepresentation authorizationSettings) {
this.authorizationSettings = authorizationSettings; this.authorizationSettings = authorizationSettings;
} }
public Map<String, Boolean> getAccess() {
return access;
}
public void setAccess(Map<String, Boolean> access) {
this.access = access;
}
} }

View file

@ -34,6 +34,7 @@ public class GroupRepresentation {
protected List<String> realmRoles; protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles; protected Map<String, List<String>> clientRoles;
protected List<GroupRepresentation> subGroups; protected List<GroupRepresentation> subGroups;
private Map<String, Boolean> access;
public String getId() { public String getId() {
return id; return id;
@ -97,4 +98,12 @@ public class GroupRepresentation {
public void setSubGroups(List<GroupRepresentation> subGroups) { public void setSubGroups(List<GroupRepresentation> subGroups) {
this.subGroups = subGroups; this.subGroups = subGroups;
} }
public Map<String, Boolean> getAccess() {
return access;
}
public void setAccess(Map<String, Boolean> access) {
this.access = access;
}
} }

View file

@ -62,6 +62,7 @@ public class UserRepresentation {
protected List<SocialLinkRepresentation> socialLinks; protected List<SocialLinkRepresentation> socialLinks;
protected List<String> groups; protected List<String> groups;
private Map<String, Boolean> access;
public String getSelf() { public String getSelf() {
return self; return self;
@ -264,4 +265,12 @@ public class UserRepresentation {
public void setDisableableCredentialTypes(Set<String> disableableCredentialTypes) { public void setDisableableCredentialTypes(Set<String> disableableCredentialTypes) {
this.disableableCredentialTypes = disableableCredentialTypes; this.disableableCredentialTypes = disableableCredentialTypes;
} }
public Map<String, Boolean> getAccess() {
return access;
}
public void setAccess(Map<String, Boolean> access) {
this.access = access;
}
} }

View file

@ -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.MigrateTo2_5_0;
import org.keycloak.migration.migrators.MigrateTo3_0_0; import org.keycloak.migration.migrators.MigrateTo3_0_0;
import org.keycloak.migration.migrators.MigrateTo3_1_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.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -60,7 +61,8 @@ public class MigrationModelManager {
new MigrateTo2_3_0(), new MigrateTo2_3_0(),
new MigrateTo2_5_0(), new MigrateTo2_5_0(),
new MigrateTo3_0_0(), new MigrateTo3_0_0(),
new MigrateTo3_1_0() new MigrateTo3_1_0(),
new MigrateTo3_2_0()
}; };
public static void migrate(KeycloakSession session) { public static void migrate(KeycloakSession session) {

View file

@ -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;
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.models; package org.keycloak.models;
import java.util.Set;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @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_EVENTS = "manage-events";
public static String MANAGE_AUTHORIZATION = "manage-authorization"; 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};
} }

View file

@ -168,7 +168,6 @@ public class ModelToRepresentation {
return rep; return rep;
} }
public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) { public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) {
UserRepresentation rep = new UserRepresentation(); UserRepresentation rep = new UserRepresentation();
rep.setId(user.getId()); rep.setId(user.getId());

View file

@ -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) { public String getRealmAdminClientId(RealmModel realm) {
return Constants.REALM_MANAGEMENT_CLIENT_ID; return Constants.REALM_MANAGEMENT_CLIENT_ID;
@ -327,6 +339,7 @@ public class RealmManager {
role.setScopeParamRequired(false); role.setScopeParamRequired(false);
adminRole.addCompositeRole(role); adminRole.addCompositeRole(role);
} }
addQueryCompositeRoles(realmAdminApp);
} }
private void checkMasterAdminManagementRoles(RealmModel realm) { private void checkMasterAdminManagementRoles(RealmModel realm) {
@ -340,6 +353,7 @@ public class RealmManager {
addAndSetAdminRole(r, masterAdminClient, adminRole); addAndSetAdminRole(r, masterAdminClient, adminRole);
} }
} }
addQueryCompositeRoles(masterAdminClient);
} }
@ -362,6 +376,7 @@ public class RealmManager {
for (String r : AdminRoles.ALL_REALM_ROLES) { for (String r : AdminRoles.ALL_REALM_ROLES) {
addAndSetAdminRole(r, realmAdminClient, adminRole); addAndSetAdminRole(r, realmAdminClient, adminRole);
} }
addQueryCompositeRoles(realmAdminClient);
} }
private void addAndSetAdminRole(String roleName, ClientModel parentClient, RoleModel parentRole) { private void addAndSetAdminRole(String roleName, ClientModel parentClient, RoleModel parentRole) {
@ -385,6 +400,7 @@ public class RealmManager {
addAndSetAdminRole(r, realmAdminClient, adminRole); 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 // I need to postpone impersonation because it needs "realm-management" client and its roles set
if (postponeImpersonationSetup) { if (postponeImpersonationSetup) {
setupImpersonationService(realm); setupImpersonationService(realm);
} String realmAdminClientId = getRealmAdminClientId(realm);
}
if (postponeAdminCliSetup) { if (postponeAdminCliSetup) {
setupAdminCli(realm); setupAdminCli(realm);

View file

@ -195,6 +195,7 @@ public class ClientResource {
if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) { if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
representation.setAuthorizationServicesEnabled(authorization().isEnabled()); representation.setAuthorizationServicesEnabled(authorization().isEnabled());
} }
representation.setAccess(auth.clients().getAccess(client));
return representation; return representation;
} }

View file

@ -114,6 +114,7 @@ public class ClientsResource {
} }
rep.add(representation); rep.add(representation);
representation.setAccess(auth.clients().getAccess(clientModel));
} else if (!viewableOnly) { } else if (!viewableOnly) {
ClientRepresentation client = new ClientRepresentation(); ClientRepresentation client = new ClientRepresentation();
client.setId(clientModel.getId()); client.setId(clientModel.getId());
@ -126,7 +127,9 @@ public class ClientsResource {
ClientModel clientModel = realm.getClientByClientId(clientId); ClientModel clientModel = realm.getClientByClientId(clientId);
if (clientModel != null) { if (clientModel != null) {
if (auth.clients().canView(clientModel)) { 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()){ } else if (!viewableOnly && auth.clients().canList()){
ClientRepresentation client = new ClientRepresentation(); ClientRepresentation client = new ClientRepresentation();
client.setId(clientModel.getId()); client.setId(clientModel.getId());

View file

@ -77,7 +77,7 @@ public class GroupResource {
@Context private UriInfo uriInfo; @Context private UriInfo uriInfo;
/** /**
* *
* *
* @return * @return
@ -88,7 +88,11 @@ public class GroupResource {
public GroupRepresentation getGroup() { public GroupRepresentation getGroup() {
this.auth.groups().requireView(group); this.auth.groups().requireView(group);
return ModelToRepresentation.toGroupHierarchy(group, true); GroupRepresentation rep = ModelToRepresentation.toGroupHierarchy(group, true);
rep.setAccess(auth.groups().getAccess(group));
return rep;
} }
/** /**

View file

@ -249,6 +249,7 @@ public class UserResource {
if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) { if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
rep.setEnabled(false); rep.setEnabled(false);
} }
rep.setAccess(auth.users().getAccess(user));
return rep; return rep;
} }
@ -761,6 +762,7 @@ public class UserResource {
if (group == null) { if (group == null) {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
auth.groups().requireManageMembers(group);
try { try {
if (user.isMemberOf(group)){ if (user.isMemberOf(group)){
@ -783,6 +785,7 @@ public class UserResource {
if (group == null) { if (group == null) {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
//auth.groups().requireManageMembers(group);
if (!user.isMemberOf(group)){ if (!user.isMemberOf(group)){
user.joinGroup(group); user.joinGroup(group);
adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();

View file

@ -259,7 +259,9 @@ public class UsersResource {
boolean canViewGlobal = auth.users().canView(); boolean canViewGlobal = auth.users().canView();
for (UserModel user : userModels) { for (UserModel user : userModels) {
if (!canViewGlobal && !auth.users().canView(user)) continue; 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; return results;
} }

View file

@ -19,6 +19,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel; import org.keycloak.models.ClientTemplateModel;
import java.util.Map;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
@ -73,4 +75,6 @@ public interface ClientPermissionEvaluator {
boolean canMapCompositeRoles(ClientModel client); boolean canMapCompositeRoles(ClientModel client);
boolean canMapClientScopeRoles(ClientModel client); boolean canMapClientScopeRoles(ClientModel client);
Map<String, Boolean> getAccess(ClientModel client);
} }

View file

@ -492,4 +492,13 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
return root.evaluatePermission(resource, scope, server); 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;
}
} }

View file

@ -18,6 +18,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import java.util.Map;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
@ -50,4 +52,6 @@ public interface GroupPermissionEvaluator {
boolean canManageMembers(GroupModel group); boolean canManageMembers(GroupModel group);
void requireManageMembers(GroupModel group); void requireManageMembers(GroupModel group);
Map<String, Boolean> getAccess(GroupModel group);
} }

View file

@ -33,8 +33,8 @@ public interface GroupPermissionManagement {
Policy viewMembersPermission(GroupModel group); Policy viewMembersPermission(GroupModel group);
Policy manageMembersPermission(GroupModel group); Policy manageMembersPermission(GroupModel group);
Policy viewPermissionGroup(GroupModel group); Policy viewPermission(GroupModel group);
Policy managePermissionGroup(GroupModel group); Policy managePermission(GroupModel group);
Resource resource(GroupModel group); Resource resource(GroupModel group);

View file

@ -23,7 +23,6 @@ import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer; import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope; import org.keycloak.authorization.model.Scope;
import org.keycloak.models.AdminRoles; import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -125,7 +124,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override @Override
public boolean canList() { 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 @Override
@ -164,11 +163,11 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
private void deletePermissions(GroupModel group) { private void deletePermissions(GroupModel group) {
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return; if (server == null) return;
Policy managePermission = managePermissionGroup(group); Policy managePermission = managePermission(group);
if (managePermission != null) { if (managePermission != null) {
authz.getStoreFactory().getPolicyStore().delete(managePermission.getId()); authz.getStoreFactory().getPolicyStore().delete(managePermission.getId());
} }
Policy viewPermission = viewPermissionGroup(group); Policy viewPermission = viewPermission(group);
if (viewPermission != null) { if (viewPermission != null) {
authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId()); authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId());
} }
@ -201,7 +200,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
} }
@Override @Override
public Policy viewPermissionGroup(GroupModel group) { public Policy viewPermission(GroupModel group) {
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return null; if (server == null) return null;
String viewPermissionName = getViewPermissionGroup(group); String viewPermissionName = getViewPermissionGroup(group);
@ -209,7 +208,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
} }
@Override @Override
public Policy managePermissionGroup(GroupModel group) { public Policy managePermission(GroupModel group) {
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return null; if (server == null) return null;
String managePermissionName = getManagePermissionGroup(group); String managePermissionName = getManagePermissionGroup(group);
@ -228,8 +227,8 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
@Override @Override
public Map<String, String> getPermissions(GroupModel group) { public Map<String, String> getPermissions(GroupModel group) {
Map<String, String> scopes = new HashMap<>(); Map<String, String> scopes = new HashMap<>();
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermissionGroup(group).getId()); scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(group).getId());
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermissionGroup(group).getId()); scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(group).getId());
scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId()); scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId()); scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
return scopes; return scopes;
@ -250,7 +249,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canManage(); if (resource == null) return canManage();
Policy policy = managePermissionGroup(group); Policy policy = managePermission(group);
if (policy == null) { if (policy == null) {
return canManage(); return canManage();
} }
@ -283,7 +282,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId()); Resource resource = authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
if (resource == null) return canView(); if (resource == null) return canView();
Policy policy = viewPermissionGroup(group); Policy policy = viewPermission(group);
if (policy == null) { if (policy == null) {
return canView(); 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;
}
} }

View file

@ -18,6 +18,8 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import java.util.Map;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
@ -47,4 +49,6 @@ public interface UserPermissionEvaluator {
boolean canImpersonate(UserModel user); boolean canImpersonate(UserModel user);
void requireImpersonate(UserModel user); void requireImpersonate(UserModel user);
Map<String, Boolean> getAccess(UserModel user);
} }

View file

@ -281,7 +281,7 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
@Override @Override
public boolean canQuery() { public boolean canQuery() {
return canView(); return canView() || root.hasOneAdminRole(AdminRoles.QUERY_USERS);
} }
@Override @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;
}

View file

@ -56,6 +56,8 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
//@Ignore //@Ignore
public class FineGrainAdminUnitTest extends AbstractKeycloakTest { public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
public static final String CLIENT_NAME = "application";
@Override @Override
public void addTestRealms(List<RealmRepresentation> testRealms) { public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation testRealmRep = new RealmRepresentation(); RealmRepresentation testRealmRep = new RealmRepresentation();
@ -70,7 +72,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
AdminPermissionManagement permissions = AdminPermissions.management(session, realm); AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
RoleModel realmRole = realm.addRole("realm-role"); RoleModel realmRole = realm.addRole("realm-role");
RoleModel realmRole2 = realm.addRole("realm-role2"); RoleModel realmRole2 = realm.addRole("realm-role2");
ClientModel client1 = realm.addClient("role-namespace"); ClientModel client1 = realm.addClient(CLIENT_NAME);
RoleModel client1Role = client1.addRole("client-role"); RoleModel client1Role = client1.addRole("client-role");
GroupModel group = realm.createGroup("top"); GroupModel group = realm.createGroup("top");
@ -80,7 +82,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
compositeRole.addCompositeRole(mapperRole); compositeRole.addCompositeRole(mapperRole);
compositeRole.addCompositeRole(managerRole); 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); permissions.roles().setPermissionsEnabled(client1Role, true);
Policy mapRolePermission = permissions.roles().mapRolePermission(client1Role); Policy mapRolePermission = permissions.roles().mapRolePermission(client1Role);
@ -122,7 +124,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
public static void setupUsers(KeycloakSession session) { public static void setupUsers(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST); 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 realmRole = realm.getRole("realm-role");
RoleModel realmRole2 = realm.getRole("realm-role2"); RoleModel realmRole2 = realm.getRole("realm-role2");
RoleModel clientRole = client.getRole("client-role"); RoleModel clientRole = client.getRole("client-role");
@ -131,6 +133,9 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleModel compositeRole = realm.getRole("composite-role"); RoleModel compositeRole = realm.getRole("composite-role");
ClientModel realmManagementClient = realm.getClientByClientId("realm-management"); ClientModel realmManagementClient = realm.getClientByClientId("realm-management");
RoleModel adminRole = realmManagementClient.getRole(AdminRoles.REALM_ADMIN); 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"); UserModel nomapAdmin = session.users().addUser(realm, "nomap-admin");
nomapAdmin.setEnabled(true); nomapAdmin.setEnabled(true);
@ -168,6 +173,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
groupMember.joinGroup(group); groupMember.joinGroup(group);
groupMember.setEnabled(true); groupMember.setEnabled(true);
UserModel groupManager = session.users().addUser(realm, "groupManager"); UserModel groupManager = session.users().addUser(realm, "groupManager");
groupManager.grantRole(queryGroupsRole);
groupManager.grantRole(queryUsersRole);
groupManager.setEnabled(true); groupManager.setEnabled(true);
groupManager.grantRole(mapperRole); groupManager.grantRole(mapperRole);
session.userCredentialManager().updateCredential(realm, groupManager, UserCredentialModel.password("password")); session.userCredentialManager().updateCredential(realm, groupManager, UserCredentialModel.password("password"));
@ -175,6 +182,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
UserModel groupManagerNoMapper = session.users().addUser(realm, "noMapperGroupManager"); UserModel groupManagerNoMapper = session.users().addUser(realm, "noMapperGroupManager");
groupManagerNoMapper.setEnabled(true); groupManagerNoMapper.setEnabled(true);
session.userCredentialManager().updateCredential(realm, groupManagerNoMapper, UserCredentialModel.password("password")); session.userCredentialManager().updateCredential(realm, groupManagerNoMapper, UserCredentialModel.password("password"));
groupManagerNoMapper.grantRole(queryGroupsRole);
groupManagerNoMapper.grantRole(queryUsersRole);
UserPolicyRepresentation groupManagerRep = new UserPolicyRepresentation(); UserPolicyRepresentation groupManagerRep = new UserPolicyRepresentation();
groupManagerRep.setName("groupManagers"); groupManagerRep.setName("groupManagers");
@ -184,10 +193,12 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
Policy groupManagerPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(groupManagerRep, server); Policy groupManagerPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(groupManagerRep, server);
Policy groupManagerPermission = permissions.groups().manageMembersPermission(group); Policy groupManagerPermission = permissions.groups().manageMembersPermission(group);
groupManagerPermission.addAssociatedPolicy(groupManagerPolicy); groupManagerPermission.addAssociatedPolicy(groupManagerPolicy);
permissions.groups().viewPermission(group).addAssociatedPolicy(groupManagerPolicy);
UserModel clientMapper = session.users().addUser(realm, "clientMapper"); UserModel clientMapper = session.users().addUser(realm, "clientMapper");
clientMapper.setEnabled(true); clientMapper.setEnabled(true);
clientMapper.grantRole(managerRole); clientMapper.grantRole(managerRole);
clientMapper.grantRole(queryUsersRole);
session.userCredentialManager().updateCredential(realm, clientMapper, UserCredentialModel.password("password")); session.userCredentialManager().updateCredential(realm, clientMapper, UserCredentialModel.password("password"));
Policy clientMapperPolicy = permissions.clients().mapRolesPermission(client); Policy clientMapperPolicy = permissions.clients().mapRolesPermission(client);
UserPolicyRepresentation userRep = new UserPolicyRepresentation(); 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)); Policy userPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(userRep, permissions.clients().resourceServer(client));
clientMapperPolicy.addAssociatedPolicy(userPolicy); 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); RealmModel realm = session.realms().getRealmByName(TEST);
RoleModel realmRole = realm.getRole("realm-role"); RoleModel realmRole = realm.getRole("realm-role");
RoleModel realmRole2 = realm.getRole("realm-role2"); RoleModel realmRole2 = realm.getRole("realm-role2");
ClientModel client = realm.getClientByClientId("role-namespace"); ClientModel client = realm.getClientByClientId(CLIENT_NAME);
RoleModel clientRole = client.getRole("client-role"); RoleModel clientRole = client.getRole("client-role");
// test authorized // test authorized
@ -309,7 +333,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation(); RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
List<RoleRepresentation> realmRole2Set = new LinkedList<>(); List<RoleRepresentation> realmRole2Set = new LinkedList<>();
realmRole2Set.add(realmRole2); 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(); RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
List<RoleRepresentation> clientRoleSet = new LinkedList<>(); List<RoleRepresentation> clientRoleSet = new LinkedList<>();
clientRoleSet.add(clientRole); clientRoleSet.add(clientRole);
@ -463,7 +487,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation(); RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
List<RoleRepresentation> realmRole2Set = new LinkedList<>(); List<RoleRepresentation> realmRole2Set = new LinkedList<>();
realmRole2Set.add(realmRole); 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(); RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
List<RoleRepresentation> clientRoleSet = new LinkedList<>(); List<RoleRepresentation> clientRoleSet = new LinkedList<>();
clientRoleSet.add(clientRole); clientRoleSet.add(clientRole);

View file

@ -1398,9 +1398,6 @@ module.config([ '$routeProvider', function($routeProvider) {
realm : function(RealmLoader) { realm : function(RealmLoader) {
return RealmLoader(); return RealmLoader();
}, },
clients : function(ClientListLoader) {
return ClientListLoader();
},
serverInfo : function(ServerInfoLoader) { serverInfo : function(ServerInfoLoader) {
return ServerInfoLoader(); return ServerInfoLoader();
} }

View file

@ -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.realm = realm;
$scope.clients = clients; $scope.clients = Client.query({realm: realm.realm, viewableOnly: true});
$scope.currentPage = 1; $scope.currentPage = 1;
$scope.currentPageInput = 1; $scope.currentPageInput = 1;
$scope.pageSize = 20; $scope.pageSize = 20;

View file

@ -1,81 +1,95 @@
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) {
return realmAccess.indexOf(role) >= 0;
}
}
return false;
}
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(Auth, Current, 'view-realm') || getAccess(Auth, Current, 'manage-realm') || this.manageRealm;
},
get viewClients() {
return getAccess(Auth, Current, 'view-clients') || getAccess(Auth, Current, 'manage-clients') || this.manageClients;
},
get viewUsers() {
return getAccess(Auth, Current, 'view-users') || getAccess(Auth, Current, 'manage-users') || this.manageClients;
},
get viewEvents() {
return getAccess(Auth, Current, 'view-events') || getAccess(Auth, Current, 'manage-events') || this.manageClients;
},
get viewIdentityProviders() {
return getAccess(Auth, Current, 'view-identity-providers') || getAccess(Auth, Current, 'manage-identity-providers') || this.manageIdentityProviders;
},
get viewAuthorization() {
return getAccess(Auth, Current, 'view-authorization') || this.manageAuthorization;
},
get manageRealm() {
return getAccess(Auth, Current, 'manage-realm');
},
get manageClients() {
return getAccess(Auth, Current, 'manage-clients');
},
get manageUsers() {
return getAccess(Auth, Current, 'manage-users');
},
get manageEvents() {
return getAccess(Auth, Current, 'manage-events');
},
get manageIdentityProviders() {
return getAccess(Auth, Current, 'manage-identity-providers');
},
get manageAuthorization() {
return getAccess(Auth, Current, 'manage-authorization');
},
get impersonation() {
return getAccess(Auth, Current, 'impersonation');
}
};
}
module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications, ServerInfo) { module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications, ServerInfo) {
$scope.authUrl = authUrl; $scope.authUrl = authUrl;
$scope.resourceUrl = resourceUrl; $scope.resourceUrl = resourceUrl;
$scope.auth = Auth; $scope.auth = Auth;
$scope.serverInfo = ServerInfo.get(); $scope.serverInfo = ServerInfo.get();
function getAccess(role) { $scope.access = getAccessObject(Auth, Current);
if (!Current.realm) {
return false;
}
var realmAccess = Auth.user && Auth.user['realm_access'];
if (realmAccess) {
realmAccess = realmAccess[Current.realm.realm];
if (realmAccess) {
return realmAccess.indexOf(role) >= 0;
}
}
return false;
}
$scope.access = {
get createRealm() {
return Auth.user && Auth.user.createRealm;
},
get viewRealm() {
return getAccess('view-realm') || getAccess('manage-realm') || this.manageRealm;
},
get viewClients() {
return getAccess('view-clients') || getAccess('manage-clients') || this.manageClients;
},
get viewUsers() {
return getAccess('view-users') || getAccess('manage-users') || this.manageClients;
},
get viewEvents() {
return getAccess('view-events') || getAccess('manage-events') || this.manageClients;
},
get viewIdentityProviders() {
return getAccess('view-identity-providers') || getAccess('manage-identity-providers') || this.manageIdentityProviders;
},
get viewAuthorization() {
return getAccess('view-authorization') || this.manageAuthorization;
},
get manageRealm() {
return getAccess('manage-realm');
},
get manageClients() {
return getAccess('manage-clients');
},
get manageUsers() {
return getAccess('manage-users');
},
get manageEvents() {
return getAccess('manage-events');
},
get manageIdentityProviders() {
return getAccess('manage-identity-providers');
},
get manageAuthorization() {
return getAccess('manage-authorization');
},
get impersonation() {
return getAccess('impersonation');
}
};
$scope.$watch(function() { $scope.$watch(function() {
return $location.path(); 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) { Realm.query(null, function(realms) {
var realm; var realm;
if (realms.length == 1) { if (realms.length == 1) {
realm = realms[0].realm; realm = realms[0];
} else if (realms.length == 2) { } else if (realms.length == 2) {
if (realms[0].realm == Auth.user.realm) { if (realms[0].realm == Auth.user.realm) {
realm = realms[1].realm; realm = realms[1];
} else if (realms[1].realm == Auth.user.realm) { } else if (realms[1].realm == Auth.user.realm) {
realm = realms[0].realm; realm = realms[0];
} }
} }
if (realm) { 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 { } else {
$location.url('/realms'); $location.url('/realms');
} }

View file

@ -6,7 +6,7 @@
<kc-tabs-client></kc-tabs-client> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label> <label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>

View file

@ -7,7 +7,7 @@
<kc-tabs-client-role></kc-tabs-client-role> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label> <label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>

View file

@ -6,7 +6,7 @@
<kc-tabs-group></kc-tabs-group> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label> <label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>

View file

@ -10,10 +10,10 @@
<h1 data-ng-show="create">{{:: 'add-node' | translate}}</h1> <h1 data-ng-show="create">{{:: 'add-node' | translate}}</h1>
<h1 data-ng-hide="create"> <h1 data-ng-hide="create">
{{node.host|capitalize}} {{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> </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"> <div class="form-group">
<label class="col-md-2 control-label" for="host">{{:: 'host' | translate}}</label> <label class="col-md-2 control-label" for="host">{{:: 'host' | translate}}</label>
<div class="col-sm-6"> <div class="col-sm-6">
@ -27,7 +27,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <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> <button data-kc-save data-ng-show="create">{{:: 'save' | translate}}</button>
</div> </div>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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> <legend><span class="text">{{:: 'basic-configuration' | translate}}</span></legend>
<fieldset > <fieldset >
<div class="form-group clearfix"> <div class="form-group clearfix">
@ -31,7 +31,7 @@
</div> </div>
<div class="form-group"> <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-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button data-kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button data-kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>
@ -43,7 +43,7 @@
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <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"> <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" <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> tooltip-trigger="mouseover mouseout" tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'register-node-manually' | translate}}</a>

View file

@ -1,11 +1,11 @@
<div> <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> <fieldset>
<kc-provider-config realm="realm" config="client.attributes" properties="currentAuthenticatorConfigProperties"></kc-provider-config> <kc-provider-config realm="realm" config="client.attributes" properties="currentAuthenticatorConfigProperties"></kc-provider-config>
</fieldset> </fieldset>
<div class="form-group"> <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-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -9,7 +9,7 @@
<h1>{{:: 'generate-private-key' | translate}}</h1> <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="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;"> <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> <kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div> </div>
<div class="form-group"> <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-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> <button class="btn btn-default" type="submit" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -9,7 +9,7 @@
<h1>{{:: 'import-client-certificate' | translate}}</h1> <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="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;"> <input type="password" readonly value="this is not a login form" style="display: none;">

View file

@ -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"> <div class="form-group">
<label class="col-md-2 control-label" for="useJwksUrl">{{:: 'use-jwks-url' | translate}}</label> <label class="col-md-2 control-label" for="useJwksUrl">{{:: 'use-jwks-url' | translate}}</label>
@ -63,7 +63,7 @@
</div> </div>
<div class="form-group"> <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 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 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> <button kc-save data-ng-disabled="!changed" data-ng-click="save()">{{:: 'save' | translate}}</button>

View file

@ -1,5 +1,5 @@
<div> <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"> <div class="form-group">
<label class="col-md-2 control-label" for="secret">{{:: 'secret' | translate}}</label> <label class="col-md-2 control-label" for="secret">{{:: 'secret' | translate}}</label>
<div class="col-sm-6"> <div class="col-sm-6">
@ -7,7 +7,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret"> <input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret">
</div> </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> <button type="submit" data-ng-click="changePassword()" class="btn btn-default">{{:: 'regenerate-secret' | translate}}</button>
</div> </div>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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"> <fieldset class="border-top">
<div class="form-group clearfix"> <div class="form-group clearfix">
<label class="col-md-2 control-label" for="clientAuthenticatorType"> {{:: 'client-authenticator' | translate}}</label> <label class="col-md-2 control-label" for="clientAuthenticatorType"> {{:: 'client-authenticator' | translate}}</label>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="clientId">{{:: 'client-id' | translate}}</label> <label class="col-md-2 control-label" for="clientId">{{:: 'client-id' | translate}}</label>
@ -391,7 +391,7 @@
</fieldset> </fieldset>
<div class="form-group"> <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-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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="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;"> <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> kc-select-action="click" readonly>{{keyInfo.certificate}}</textarea>
</div> </div>
</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"> <div class="pull-right">
<button class="btn btn-primary" type="submit" data-ng-click="generate()">Generate new keys</button> <button class="btn btn-primary" type="submit" data-ng-click="generate()">Generate new keys</button>
</div> </div>

View file

@ -42,7 +42,7 @@
</td> </td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</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-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>
<tr data-ng-show="(clients | filter:search).length == 0"> <tr data-ng-show="(clients | filter:search).length == 0">
<td class="text-muted" colspan="4" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td> <td class="text-muted" colspan="4" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>

View file

@ -45,7 +45,7 @@
</tbody> </tbody>
</table> </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> <button class="btn btn-primary" data-ng-click="add()">{{:: 'add-selected' | translate}}</button>
</div> </div>
</div> </div>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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"> <fieldset class="border-top">
<div class="form-group" ng-show="client.clientTemplate"> <div class="form-group" ng-show="client.clientTemplate">
<label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Mappers</label> <label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Mappers</label>
@ -35,7 +35,7 @@
</div> </div>
</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="#/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> <a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">{{:: 'add-builtin' | translate}}</a>
</div> </div>
@ -55,7 +55,7 @@
<td>{{mapperTypes[mapper.protocolMapper].category}}</td> <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
<td>{{mapperTypes[mapper.protocolMapper].name}}</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" 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>
<tr data-ng-show="mappers.length == 0"> <tr data-ng-show="mappers.length == 0">
<td>{{:: 'no-mappers-available' | translate}}</td> <td>{{:: 'no-mappers-available' | translate}}</td>

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label> <label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label>
@ -18,7 +18,7 @@
</div> </div>
</fieldset> </fieldset>
<div class="form-group"> <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="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="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> <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>

View file

@ -10,7 +10,7 @@
<kc-tabs-client-role></kc-tabs-client-role> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
@ -47,13 +47,13 @@
</fieldset> </fieldset>
<div class="form-group"> <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-save>{{:: 'save' | translate}}</button>
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button> <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div> </div>
</div> </div>
<div class="form-group"> <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-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -10,7 +10,7 @@
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <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"> <div class="pull-right">
<a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">{{:: 'add-role' | translate}}</a> <a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">{{:: 'add-role' | translate}}</a>
</div> </div>
@ -29,7 +29,7 @@
<td translate="{{role.composite}}"></td> <td translate="{{role.composite}}"></td>
<td>{{role.description}}</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" 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>
<tr data-ng-show="!roles || roles.length == 0"> <tr data-ng-show="!roles || roles.length == 0">
<td>{{:: 'no-client-roles-available' | translate}}</td> <td>{{:: 'no-client-roles-available' | translate}}</td>

View file

@ -9,7 +9,7 @@
<h1>{{:: 'export-saml-key' | translate}} {{client.clientId|capitalize}}</h1> <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="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;"> <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> <kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div> </div>
<div class="form-group"> <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> <button class="btn btn-primary" type="submit" data-ng-click="download()">{{:: 'download' | translate}}</button>
</div> </div>
</div> </div>

View file

@ -9,7 +9,7 @@
<h1>{{:: 'import-saml-key' | translate}} {{client.clientId|capitalize}}</h1> <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="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;"> <input type="password" readonly value="this is not a login form" style="display: none;">

View file

@ -7,7 +7,7 @@
<kc-tabs-client></kc-tabs-client> <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'"> <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> <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"> <div class="form-group" data-ng-hide="!signingKeyInfo.privateKey">
@ -27,7 +27,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <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="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-click="importSigningKey()">{{:: 'import' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">{{:: 'export' | 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> </div>
<div class="form-group"> <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="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-click="importEncryptionKey()">{{:: 'import' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">{{:: 'export' | translate}}</button> <button class="btn btn-default" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">{{:: 'export' | translate}}</button>

View file

@ -9,7 +9,7 @@
<h2><span>{{client.clientId}}</span> {{:: 'scope-mappings' | translate}} </h2> <h2><span>{{client.clientId}}</span> {{:: 'scope-mappings' | translate}} </h2>
<p class="subtitle"></p> <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"> <fieldset class="border-top">
<div class="form-group" ng-show="client.clientTemplate"> <div class="form-group" ng-show="client.clientTemplate">
<label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Scope</label> <label class="col-md-2 control-label" for="useTemplateScope">Inherit Template Scope</label>
@ -41,7 +41,7 @@
</fieldset> </fieldset>
</form> </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"> <div class="form-group">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label> <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10"> <div class="col-md-10">

View file

@ -10,7 +10,7 @@
<h2><span>{{client.clientId}}</span> {{:: 'service-accounts' | translate}} </h2> <h2><span>{{client.clientId}}</span> {{:: 'service-accounts' | translate}} </h2>
<p class="subtitle"></p> <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"> <div class="form-group">
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label> <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10"> <div class="col-md-10">
@ -102,7 +102,7 @@
</div> </div>
</form> </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> <legend><span class="text" translate="service-account-is-not-enabled-for" translate-values="{client: client.clientId}"></span></legend>
</form> </form>

View file

@ -6,7 +6,7 @@
<kc-tabs-user></kc-tabs-user> <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"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <tr>
@ -29,7 +29,7 @@
</tbody> </tbody>
</table> </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"> <div class="col-md-12">
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button> <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>

View file

@ -7,7 +7,7 @@
<kc-tabs-user></kc-tabs-user> <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"> <fieldset class="border-top">
<div class="form-group"> <div class="form-group">
@ -62,7 +62,7 @@
<div class="form-group clearfix block"> <div class="form-group clearfix block">
<label class="col-md-2 control-label" for="userEnabled">{{:: 'user-enabled' | translate}}</label> <label class="col-md-2 control-label" for="userEnabled">{{:: 'user-enabled' | translate}}</label>
<div class="col-md-6"> <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> </div>
<kc-tooltip>{{:: 'user-enabled.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'user-enabled.tooltip' | translate}}</kc-tooltip>
</div> </div>
@ -93,7 +93,7 @@
<div class="form-group clearfix block"> <div class="form-group clearfix block">
<label class="col-md-2 control-label" for="emailVerified">{{:: 'email-verified' | translate}}</label> <label class="col-md-2 control-label" for="emailVerified">{{:: 'email-verified' | translate}}</label>
<div class="col-md-6"> <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> </div>
<kc-tooltip>{{:: 'email-verified.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'email-verified.tooltip' | translate}}</kc-tooltip>
</div> </div>
@ -138,7 +138,7 @@
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button> <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div> </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-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button> <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div> </div>

View file

@ -55,7 +55,7 @@
<td class="clip">{{user.firstName}}</td> <td class="clip">{{user.firstName}}</td>
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/users/{{user.id}}">{{:: 'edit' | translate}}</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="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>
<tr data-ng-show="!users || users.length == 0"> <tr data-ng-show="!users || users.length == 0">
<td class="text-muted" data-ng-show="!users">{{:: 'users.instruction' | translate}}</td> <td class="text-muted" data-ng-show="!users">{{:: 'users.instruction' | translate}}</td>

View file

@ -8,9 +8,9 @@
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr data-ng-show="access.manageUsers"> <tr data-ng-show="user.access.manage">
<th class="kc-table-actions" colspan="6"> <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> <a id="logoutAllSessions" class="btn btn-default" ng-click="logoutAll()">{{:: 'logout-all-sessions' | translate}}</a>
</div> </div>
</th> </th>
@ -20,7 +20,7 @@
<th>{{:: 'started' | translate}}</th> <th>{{:: 'started' | translate}}</th>
<th>{{:: 'last-access' | translate}}</th> <th>{{:: 'last-access' | translate}}</th>
<th>{{:: 'clients' | 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> </tr>
</thead> </thead>
<tbody> <tbody>
@ -34,7 +34,7 @@
</div> </div>
</ul> </ul>
</td> </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> </tr>
</tbody> </tbody>
</table> </table>

View file

@ -16,7 +16,7 @@
</div> </div>
</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> <h2>{{:: 'configure' | translate}}</h2>
<ul class="nav nav-pills nav-stacked"> <ul class="nav nav-pills nav-stacked">
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2] <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'"> || 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> <a href="#/realms/{{realm.realm}}"><span class="pficon pficon-settings"></span> {{:: 'realm-settings' | translate}}</a>
</li> </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.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.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> <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> </ul>
</div> </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> <h2>{{:: 'manage' | translate}}</h2>
<ul class="nav nav-pills nav-stacked"> <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> || 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.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' <li data-ng-show="access.viewEvents" data-ng-class="(path[2] == 'events'
|| path[2] == 'events-settings' || path[2] == 'events-settings'

View file

@ -3,7 +3,7 @@
<h1 data-ng-show="create">{{:: 'add-client' | translate}}</h1> <h1 data-ng-show="create">{{:: 'add-client' | translate}}</h1>
<h1 data-ng-hide="create"> <h1 data-ng-hide="create">
{{client.clientId|capitalize}} {{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> </h1>
<ul class="nav nav-tabs" data-ng-hide="create && !path[4]"> <ul class="nav nav-tabs" data-ng-hide="create && !path[4]">

View file

@ -8,7 +8,7 @@
<ul class="nav nav-tabs" data-ng-show="!create"> <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] && 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-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] == '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] == '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> <li ng-class="{active: path[4] == 'consents'}"><a href="#/realms/{{realm.realm}}/users/{{user.id}}/consents">{{:: 'consents' | translate}}</a></li>

View file

@ -3,7 +3,7 @@
<ul class="nav nav-tabs"> <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'}"><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> <a href="#/realms/{{realm.realm}}/users-permissions">{{:: 'authz-permissions' | translate}}</a>
<kc-tooltip>{{:: 'manage-permissions-users.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'manage-permissions-users.tooltip' | translate}}</kc-tooltip>
</li> </li>