admin console work
This commit is contained in:
parent
f1807aead4
commit
28b3ef9aa9
38 changed files with 251 additions and 87 deletions
|
@ -234,13 +234,16 @@ public class RSAVerifierTest {
|
||||||
public void testTokenAuth() throws Exception {
|
public void testTokenAuth() throws Exception {
|
||||||
token = new AccessToken();
|
token = new AccessToken();
|
||||||
token.subject("CN=Client")
|
token.subject("CN=Client")
|
||||||
.issuer("domain")
|
.issuer("http://localhost:8080/auth/realms/demo")
|
||||||
.addAccess("service").addRole("admin").verifyCaller(true);
|
.addAccess("service").addRole("admin").verifyCaller(true);
|
||||||
|
token.setEmail("bill@jboss.org");
|
||||||
|
|
||||||
String encoded = new JWSBuilder()
|
String encoded = new JWSBuilder()
|
||||||
.jsonContent(token)
|
.jsonContent(token)
|
||||||
.rsa256(idpPair.getPrivate());
|
.rsa256(idpPair.getPrivate());
|
||||||
|
|
||||||
|
System.out.println("token size: " + encoded.length());
|
||||||
|
|
||||||
AccessToken v = null;
|
AccessToken v = null;
|
||||||
try {
|
try {
|
||||||
v = verifySkeletonKeyToken(encoded);
|
v = verifySkeletonKeyToken(encoded);
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class AuthenticationManagementResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public List<Map<String, Object>> getClientAuthenticatorProviders() {
|
public List<Map<String, Object>> getClientAuthenticatorProviders() {
|
||||||
auth.realm().requireViewRealm();
|
auth.requireAnyAdminRole();
|
||||||
|
|
||||||
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
|
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
|
||||||
return buildProviderMetadata(factories);
|
return buildProviderMetadata(factories);
|
||||||
|
@ -959,7 +959,7 @@ public class AuthenticationManagementResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@NoCache
|
@NoCache
|
||||||
public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
|
public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
|
||||||
auth.realm().requireViewRealm();
|
auth.requireAnyAdminRole();
|
||||||
|
|
||||||
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
|
List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class ClientAttributeCertificateResource {
|
||||||
@Path("generate")
|
@Path("generate")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public CertificateRepresentation generate() {
|
public CertificateRepresentation generate() {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ public class ClientAttributeCertificateResource {
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public CertificateRepresentation uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
public CertificateRepresentation uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CertificateRepresentation info = getCertFromRequest(input);
|
CertificateRepresentation info = getCertFromRequest(input);
|
||||||
|
@ -165,7 +165,7 @@ public class ClientAttributeCertificateResource {
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public CertificateRepresentation uploadJksCertificate(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
public CertificateRepresentation uploadJksCertificate(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CertificateRepresentation info = getCertFromRequest(input);
|
CertificateRepresentation info = getCertFromRequest(input);
|
||||||
|
@ -306,7 +306,7 @@ public class ClientAttributeCertificateResource {
|
||||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public byte[] generateAndGetKeystore(final KeyStoreConfig config) {
|
public byte[] generateAndGetKeystore(final KeyStoreConfig config) {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
|
if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
|
||||||
throw new NotAcceptableException("Only support jks or pkcs12 format.");
|
throw new NotAcceptableException("Only support jks or pkcs12 format.");
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.keycloak.events.admin.OperationType;
|
||||||
import org.keycloak.events.admin.ResourceType;
|
import org.keycloak.events.admin.ResourceType;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientTemplateModel;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
@ -41,6 +42,7 @@ import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.protocol.ClientInstallationProvider;
|
import org.keycloak.protocol.ClientInstallationProvider;
|
||||||
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ClientTemplateRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.ManagementPermissionReference;
|
import org.keycloak.representations.idm.ManagementPermissionReference;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
@ -134,7 +136,7 @@ public class ClientResource {
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response update(final ClientRepresentation rep) {
|
public Response update(final ClientRepresentation rep) {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
ValidationMessages validationMessages = new ValidationMessages();
|
ValidationMessages validationMessages = new ValidationMessages();
|
||||||
if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
|
if (!ClientValidator.validate(rep, validationMessages) || !PairwiseClientValidator.validate(session, rep, validationMessages)) {
|
||||||
|
@ -227,7 +229,7 @@ public class ClientResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public CredentialRepresentation regenerateSecret() {
|
public CredentialRepresentation regenerateSecret() {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
logger.debug("regenerateSecret");
|
logger.debug("regenerateSecret");
|
||||||
UserCredentialModel cred = KeycloakModelUtils.generateSecret(client);
|
UserCredentialModel cred = KeycloakModelUtils.generateSecret(client);
|
||||||
|
@ -326,7 +328,7 @@ public class ClientResource {
|
||||||
@POST
|
@POST
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public GlobalRequestResult pushRevocation() {
|
public GlobalRequestResult pushRevocation() {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).resource(ResourceType.CLIENT).success();
|
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).resource(ResourceType.CLIENT).success();
|
||||||
return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
|
return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
|
||||||
|
@ -456,7 +458,7 @@ public class ClientResource {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void registerNode(Map<String, String> formParams) {
|
public void registerNode(Map<String, String> formParams) {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
String node = formParams.get("node");
|
String node = formParams.get("node");
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
|
@ -476,7 +478,7 @@ public class ClientResource {
|
||||||
@DELETE
|
@DELETE
|
||||||
@NoCache
|
@NoCache
|
||||||
public void unregisterNode(final @PathParam("node") String node) {
|
public void unregisterNode(final @PathParam("node") String node) {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
|
if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
|
||||||
|
|
||||||
|
@ -500,7 +502,7 @@ public class ClientResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public GlobalRequestResult testNodesAvailable() {
|
public GlobalRequestResult testNodesAvailable() {
|
||||||
auth.clients().requireManage(client);
|
auth.clients().requireConfigure(client);
|
||||||
|
|
||||||
logger.debug("Test availability of cluster nodes");
|
logger.debug("Test availability of cluster nodes");
|
||||||
GlobalRequestResult result = new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
|
GlobalRequestResult result = new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
|
||||||
|
@ -583,6 +585,30 @@ public class ClientResource {
|
||||||
new ClientManager(new RealmManager(session)).clientIdChanged(client, rep.getClientId());
|
new ClientManager(new RealmManager(session)).clientIdChanged(client, rep.getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rep.isFullScopeAllowed() != null && rep.isFullScopeAllowed().booleanValue() != client.isFullScopeAllowed()) {
|
||||||
|
auth.clients().requireManage(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rep.getClientTemplate() != null) {
|
||||||
|
ClientTemplateModel currTemplate = client.getClientTemplate();
|
||||||
|
if (currTemplate == null) {
|
||||||
|
if (!rep.getClientTemplate().equals(ClientTemplateRepresentation.NONE)) {
|
||||||
|
auth.clients().requireManage(client);
|
||||||
|
}
|
||||||
|
} else if (!rep.getClientTemplate().equals(currTemplate.getName())){
|
||||||
|
auth.clients().requireManage(client);
|
||||||
|
}
|
||||||
|
if ((rep.isUseTemplateConfig() != null && rep.isUseTemplateConfig().booleanValue() != client.useTemplateConfig())
|
||||||
|
|| (rep.isUseTemplateScope() != null && rep.isUseTemplateScope().booleanValue() != client.useTemplateScope())
|
||||||
|
|| (rep.isUseTemplateMappers() != null && rep.isUseTemplateMappers().booleanValue() != client.useTemplateMappers())
|
||||||
|
|
||||||
|
) {
|
||||||
|
auth.clients().requireManage(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RepresentationToModel.updateClient(rep, client);
|
RepresentationToModel.updateClient(rep, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,10 @@ public interface ClientPermissionEvaluator {
|
||||||
|
|
||||||
boolean canManage(ClientModel client);
|
boolean canManage(ClientModel client);
|
||||||
|
|
||||||
|
boolean canConfigure(ClientModel client);
|
||||||
|
|
||||||
|
void requireConfigure(ClientModel client);
|
||||||
|
|
||||||
void requireManage(ClientModel client);
|
void requireManage(ClientModel client);
|
||||||
|
|
||||||
boolean canView(ClientModel client);
|
boolean canView(ClientModel client);
|
||||||
|
|
|
@ -31,6 +31,7 @@ public interface ClientPermissionManagement {
|
||||||
public static final String MAP_ROLES_SCOPE = "map-roles";
|
public static final String MAP_ROLES_SCOPE = "map-roles";
|
||||||
public static final String MAP_ROLES_CLIENT_SCOPE = "map-roles-client-scope";
|
public static final String MAP_ROLES_CLIENT_SCOPE = "map-roles-client-scope";
|
||||||
public static final String MAP_ROLES_COMPOSITE_SCOPE = "map-roles-composite";
|
public static final String MAP_ROLES_COMPOSITE_SCOPE = "map-roles-composite";
|
||||||
|
public static final String CONFIGURE_SCOPE = "configure";
|
||||||
|
|
||||||
boolean isPermissionsEnabled(ClientModel client);
|
boolean isPermissionsEnabled(ClientModel client);
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ public interface ClientPermissionManagement {
|
||||||
|
|
||||||
Policy managePermission(ClientModel client);
|
Policy managePermission(ClientModel client);
|
||||||
|
|
||||||
|
Policy configurePermission(ClientModel client);
|
||||||
|
|
||||||
Policy viewPermission(ClientModel client);
|
Policy viewPermission(ClientModel client);
|
||||||
|
|
||||||
ResourceServer resourceServer(ClientModel client);
|
ResourceServer resourceServer(ClientModel client);
|
||||||
|
|
|
@ -63,6 +63,9 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
private String getManagePermissionName(ClientModel client) {
|
private String getManagePermissionName(ClientModel client) {
|
||||||
return "manage.permission.client." + client.getId();
|
return "manage.permission.client." + client.getId();
|
||||||
}
|
}
|
||||||
|
private String getConfigurePermissionName(ClientModel client) {
|
||||||
|
return "configure.permission.client." + client.getId();
|
||||||
|
}
|
||||||
private String getViewPermissionName(ClientModel client) {
|
private String getViewPermissionName(ClientModel client) {
|
||||||
return "view.permission.client." + client.getId();
|
return "view.permission.client." + client.getId();
|
||||||
}
|
}
|
||||||
|
@ -98,6 +101,10 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
if (mapRoleCompositeScope == null) {
|
if (mapRoleCompositeScope == null) {
|
||||||
mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_COMPOSITE_SCOPE, server);
|
mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_COMPOSITE_SCOPE, server);
|
||||||
}
|
}
|
||||||
|
Scope configureScope = authz.getStoreFactory().getScopeStore().findByName(CONFIGURE_SCOPE, server.getId());
|
||||||
|
if (configureScope == null) {
|
||||||
|
configureScope = authz.getStoreFactory().getScopeStore().create(CONFIGURE_SCOPE, server);
|
||||||
|
}
|
||||||
|
|
||||||
String resourceName = getResourceName(client);
|
String resourceName = getResourceName(client);
|
||||||
Resource resource = authz.getStoreFactory().getResourceStore().findByName(resourceName, server.getId());
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(resourceName, server.getId());
|
||||||
|
@ -105,6 +112,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
resource = authz.getStoreFactory().getResourceStore().create(resourceName, server, server.getClientId());
|
resource = authz.getStoreFactory().getResourceStore().create(resourceName, server, server.getClientId());
|
||||||
resource.setType("Client");
|
resource.setType("Client");
|
||||||
Set<Scope> scopeset = new HashSet<>();
|
Set<Scope> scopeset = new HashSet<>();
|
||||||
|
scopeset.add(configureScope);
|
||||||
scopeset.add(manageScope);
|
scopeset.add(manageScope);
|
||||||
scopeset.add(viewScope);
|
scopeset.add(viewScope);
|
||||||
scopeset.add(mapRoleScope);
|
scopeset.add(mapRoleScope);
|
||||||
|
@ -117,6 +125,11 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
if (managePermission == null) {
|
if (managePermission == null) {
|
||||||
Helper.addEmptyScopePermission(authz, server, managePermissionName, resource, manageScope);
|
Helper.addEmptyScopePermission(authz, server, managePermissionName, resource, manageScope);
|
||||||
}
|
}
|
||||||
|
String configurePermissionName = getConfigurePermissionName(client);
|
||||||
|
Policy configurePermission = authz.getStoreFactory().getPolicyStore().findByName(configurePermissionName, server.getId());
|
||||||
|
if (configurePermission == null) {
|
||||||
|
Helper.addEmptyScopePermission(authz, server, configurePermissionName, resource, configureScope);
|
||||||
|
}
|
||||||
String viewPermissionName = getViewPermissionName(client);
|
String viewPermissionName = getViewPermissionName(client);
|
||||||
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
|
Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
|
||||||
if (viewPermission == null) {
|
if (viewPermission == null) {
|
||||||
|
@ -139,8 +152,8 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deletePolicy(String name, ClientModel client, ResourceServer server) {
|
private void deletePolicy(String name, ResourceServer server) {
|
||||||
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
|
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(name, server.getId());
|
||||||
if (policy != null) {
|
if (policy != null) {
|
||||||
authz.getStoreFactory().getPolicyStore().delete(policy.getId());
|
authz.getStoreFactory().getPolicyStore().delete(policy.getId());
|
||||||
}
|
}
|
||||||
|
@ -150,11 +163,12 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
private void deletePermissions(ClientModel client) {
|
private void deletePermissions(ClientModel client) {
|
||||||
ResourceServer server = resourceServer(client);
|
ResourceServer server = resourceServer(client);
|
||||||
if (server == null) return;
|
if (server == null) return;
|
||||||
deletePolicy(getManagePermissionName(client), client, server);
|
deletePolicy(getManagePermissionName(client), server);
|
||||||
deletePolicy(getViewPermissionName(client), client, server);
|
deletePolicy(getViewPermissionName(client), server);
|
||||||
deletePolicy(getMapRolesPermissionName(client), client, server);
|
deletePolicy(getMapRolesPermissionName(client), server);
|
||||||
deletePolicy(getMapRolesClientScopePermissionName(client), client, server);
|
deletePolicy(getMapRolesClientScopePermissionName(client), server);
|
||||||
deletePolicy(getMapRolesCompositePermissionName(client), client, server);
|
deletePolicy(getMapRolesCompositePermissionName(client), server);
|
||||||
|
deletePolicy(getConfigurePermissionName(client), server);
|
||||||
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
|
||||||
if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
|
if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
|
||||||
}
|
}
|
||||||
|
@ -182,6 +196,10 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.MANAGE_SCOPE, server.getId());
|
return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.MANAGE_SCOPE, server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Scope configureScope(ResourceServer server) {
|
||||||
|
return authz.getStoreFactory().getScopeStore().findByName(CONFIGURE_SCOPE, server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
private Scope viewScope(ResourceServer server) {
|
private Scope viewScope(ResourceServer server) {
|
||||||
return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.VIEW_SCOPE, server.getId());
|
return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.VIEW_SCOPE, server.getId());
|
||||||
}
|
}
|
||||||
|
@ -259,6 +277,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
scopes.put(MAP_ROLES_COMPOSITE_SCOPE, mapRolesCompositePermission(client).getId());
|
scopes.put(MAP_ROLES_COMPOSITE_SCOPE, mapRolesCompositePermission(client).getId());
|
||||||
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(client).getId());
|
scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(client).getId());
|
||||||
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(client).getId());
|
scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(client).getId());
|
||||||
|
scopes.put(CONFIGURE_SCOPE, configurePermission(client).getId());
|
||||||
return scopes;
|
return scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +310,41 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return root.evaluatePermission(resource, scope, server);
|
return root.evaluatePermission(resource, scope, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canConfigure(ClientModel client) {
|
||||||
|
if (canManage(client)) return true;
|
||||||
|
if (!root.isAdminSameRealm()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return false;
|
||||||
|
|
||||||
|
Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
|
||||||
|
if (resource == null) return false;
|
||||||
|
|
||||||
|
Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getConfigurePermissionName(client), server.getId());
|
||||||
|
if (policy == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
|
||||||
|
// if no policies attached to permission then just do default behavior
|
||||||
|
if (associatedPolicies == null || associatedPolicies.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope scope = configureScope(server);
|
||||||
|
return root.evaluatePermission(resource, scope, server);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void requireConfigure(ClientModel client) {
|
||||||
|
if (!canConfigure(client)) {
|
||||||
|
throw new ForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requireManage(ClientModel client) {
|
public void requireManage(ClientModel client) {
|
||||||
if (!canManage(client)) {
|
if (!canManage(client)) {
|
||||||
|
@ -300,7 +354,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canView(ClientModel client) {
|
public boolean canView(ClientModel client) {
|
||||||
return hasView(client) || canManage(client);
|
return hasView(client) || canConfigure(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasView(ClientModel client) {
|
private boolean hasView(ClientModel client) {
|
||||||
|
@ -437,6 +491,13 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
return authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
|
return authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Policy configurePermission(ClientModel client) {
|
||||||
|
ResourceServer server = resourceServer(client);
|
||||||
|
if (server == null) return null;
|
||||||
|
return authz.getStoreFactory().getPolicyStore().findByName(getConfigurePermissionName(client), server.getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Policy viewPermission(ClientModel client) {
|
public Policy viewPermission(ClientModel client) {
|
||||||
ResourceServer server = resourceServer(client);
|
ResourceServer server = resourceServer(client);
|
||||||
|
@ -499,6 +560,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
|
||||||
Map<String, Boolean> map = new HashMap<>();
|
Map<String, Boolean> map = new HashMap<>();
|
||||||
map.put("view", canView(client));
|
map.put("view", canView(client));
|
||||||
map.put("manage", canManage(client));
|
map.put("manage", canManage(client));
|
||||||
|
map.put("configure", canConfigure(client));
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ import java.util.Set;
|
||||||
class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement {
|
class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement {
|
||||||
private static final Logger logger = Logger.getLogger(GroupPermissions.class);
|
private static final Logger logger = Logger.getLogger(GroupPermissions.class);
|
||||||
public static final String MAP_ROLE_SCOPE = "map-role";
|
public static final String MAP_ROLE_SCOPE = "map-role";
|
||||||
public static final String MANAGE_MEMBERSHIP_SCOPE = "manage.membership";
|
public static final String MANAGE_MEMBERSHIP_SCOPE = "manage-membership";
|
||||||
public static final String MANAGE_MEMBERS_SCOPE = "manage.members";
|
public static final String MANAGE_MEMBERS_SCOPE = "manage-members";
|
||||||
public static final String VIEW_MEMBERS_SCOPE = "view.members";
|
public static final String VIEW_MEMBERS_SCOPE = "view-members";
|
||||||
protected final KeycloakSession session;
|
protected final KeycloakSession session;
|
||||||
protected final RealmModel realm;
|
protected final RealmModel realm;
|
||||||
protected final AuthorizationProvider authz;
|
protected final AuthorizationProvider authz;
|
||||||
|
|
|
@ -319,7 +319,7 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
|
||||||
if (container instanceof RealmModel) {
|
if (container instanceof RealmModel) {
|
||||||
return root.realm().canManageRealm();
|
return root.realm().canManageRealm();
|
||||||
} else {
|
} else {
|
||||||
return root.clients().canManage((ClientModel)container);
|
return root.clients().canConfigure((ClientModel)container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
|
||||||
scopes.put(MAP_ROLES_SCOPE, mapRolesPermission().getId());
|
scopes.put(MAP_ROLES_SCOPE, mapRolesPermission().getId());
|
||||||
scopes.put(MANAGE_GROUP_MEMBERSHIP_SCOPE, manageGroupMembershipPermission().getId());
|
scopes.put(MANAGE_GROUP_MEMBERSHIP_SCOPE, manageGroupMembershipPermission().getId());
|
||||||
scopes.put(IMPERSONATE_SCOPE, adminImpersonatingPermission().getId());
|
scopes.put(IMPERSONATE_SCOPE, adminImpersonatingPermission().getId());
|
||||||
|
scopes.put(USER_IMPERSONATED_SCOPE, userImpersonatedPermission().getId());
|
||||||
return scopes;
|
return scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,11 @@ import org.keycloak.admin.client.Keycloak;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.AuthorizationProviderFactory;
|
import org.keycloak.authorization.AuthorizationProviderFactory;
|
||||||
import org.keycloak.authorization.model.Resource;
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
import org.keycloak.models.ClientTemplateModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.RepresentationToModel;
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
|
import org.keycloak.representations.idm.ClientTemplateRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.Logic;
|
import org.keycloak.representations.idm.authorization.Logic;
|
||||||
import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
|
||||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||||
|
@ -85,6 +87,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
RoleModel salesAppsAdminRole = realm.addRole("sales-apps-admin");
|
RoleModel salesAppsAdminRole = realm.addRole("sales-apps-admin");
|
||||||
salesAppsAdminRole.addCompositeRole(clientAdmin);
|
salesAppsAdminRole.addCompositeRole(clientAdmin);
|
||||||
salesAppsAdminRole.addCompositeRole(client2Admin);
|
salesAppsAdminRole.addCompositeRole(client2Admin);
|
||||||
|
ClientModel realmManagementClient = realm.getClientByClientId("realm-management");
|
||||||
|
RoleModel queryClient = realmManagementClient.getRole(AdminRoles.QUERY_CLIENTS);
|
||||||
|
|
||||||
|
|
||||||
UserModel admin = session.users().addUser(realm, "salesManager");
|
UserModel admin = session.users().addUser(realm, "salesManager");
|
||||||
|
@ -99,6 +103,10 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
admin = session.users().addUser(realm, "sales-pipeline-admin");
|
admin = session.users().addUser(realm, "sales-pipeline-admin");
|
||||||
admin.setEnabled(true);
|
admin.setEnabled(true);
|
||||||
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
|
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
|
||||||
|
admin = session.users().addUser(realm, "client-admin");
|
||||||
|
admin.setEnabled(true);
|
||||||
|
admin.grantRole(queryClient);
|
||||||
|
session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
|
||||||
|
|
||||||
UserModel user = session.users().addUser(realm, "salesman");
|
UserModel user = session.users().addUser(realm, "salesman");
|
||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
|
@ -115,6 +123,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
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(CLIENT_NAME);
|
ClientModel client1 = realm.addClient(CLIENT_NAME);
|
||||||
|
ClientTemplateModel template = realm.addClientTemplate("template");
|
||||||
|
client1.setFullScopeAllowed(false);
|
||||||
RoleModel client1Role = client1.addRole("client-role");
|
RoleModel client1Role = client1.addRole("client-role");
|
||||||
GroupModel group = realm.createGroup("top");
|
GroupModel group = realm.createGroup("top");
|
||||||
|
|
||||||
|
@ -280,6 +290,19 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
clientManagerPolicy.addAssociatedPolicy(userPolicy);
|
clientManagerPolicy.addAssociatedPolicy(userPolicy);
|
||||||
|
|
||||||
|
|
||||||
|
UserModel clientConfigurer = session.users().addUser(realm, "clientConfigurer");
|
||||||
|
clientConfigurer.setEnabled(true);
|
||||||
|
clientConfigurer.grantRole(queryClientsRole);
|
||||||
|
session.userCredentialManager().updateCredential(realm, clientConfigurer, UserCredentialModel.password("password"));
|
||||||
|
|
||||||
|
Policy clientConfigurePolicy = permissions.clients().configurePermission(client);
|
||||||
|
userRep = new UserPolicyRepresentation();
|
||||||
|
userRep.setName("clientConfigure");
|
||||||
|
userRep.addUser("clientConfigurer");
|
||||||
|
userPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(userRep, permissions.clients().resourceServer(client));
|
||||||
|
clientConfigurePolicy.addAssociatedPolicy(userPolicy);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -364,20 +387,13 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
protected boolean isImportAfterEachMethod() {
|
protected boolean isImportAfterEachMethod() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//@Test
|
@Test
|
||||||
public void testDemo() throws Exception {
|
public void testDemo() throws Exception {
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupDemo);
|
testingClient.server().run(FineGrainAdminUnitTest::setupDemo);
|
||||||
Thread.sleep(1000000000);
|
Thread.sleep(1000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//@Test
|
|
||||||
public void testUI() throws Exception {
|
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
|
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
|
|
||||||
Thread.sleep(1000000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluationLocal() throws Exception {
|
public void testEvaluationLocal() throws Exception {
|
||||||
testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
|
testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
|
||||||
|
@ -400,10 +416,48 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
||||||
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
|
List<RoleRepresentation> realmRole2Set = new LinkedList<>();
|
||||||
realmRole2Set.add(realmRole2);
|
realmRole2Set.add(realmRole2);
|
||||||
ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId(CLIENT_NAME).get(0);
|
ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId(CLIENT_NAME).get(0);
|
||||||
|
ClientTemplateRepresentation template = adminClient.realm(TEST).clientTemplates().findAll().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);
|
||||||
|
|
||||||
|
// test configure client
|
||||||
|
{
|
||||||
|
Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
|
||||||
|
TEST, "clientConfigurer", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
|
||||||
|
client.setAdminUrl("http://nowhere");
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).update(client);
|
||||||
|
client.setFullScopeAllowed(true);
|
||||||
|
try {
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).update(client);
|
||||||
|
Assert.fail("should fail with forbidden exception");
|
||||||
|
} catch (ClientErrorException e) {
|
||||||
|
Assert.assertEquals(e.getResponse().getStatus(), 403);
|
||||||
|
|
||||||
|
}
|
||||||
|
client.setFullScopeAllowed(false);
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).update(client);
|
||||||
|
|
||||||
|
client.setClientTemplate(template.getName());
|
||||||
|
try {
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).update(client);
|
||||||
|
Assert.fail("should fail with forbidden exception");
|
||||||
|
} catch (ClientErrorException e) {
|
||||||
|
Assert.assertEquals(e.getResponse().getStatus(), 403);
|
||||||
|
|
||||||
|
}
|
||||||
|
client.setClientTemplate(null);
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).update(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
realmClient.realm(TEST).clients().get(client.getId()).getScopeMappings().realmLevel().add(realmRoleSet);
|
||||||
|
Assert.fail("should fail with forbidden exception");
|
||||||
|
} catch (ClientErrorException e) {
|
||||||
|
Assert.assertEquals(e.getResponse().getStatus(), 403);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test illegal impersonation
|
// test illegal impersonation
|
||||||
{
|
{
|
||||||
Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
|
Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
|
||||||
|
|
|
@ -1326,9 +1326,9 @@ manage-permissions-client.tooltip=Fine grain permssions for admins that want to
|
||||||
manage-permissions-group.tooltip=Fine grain permssions for admins that want to manage this group or the members of this group.
|
manage-permissions-group.tooltip=Fine grain permssions for admins that want to manage this group or the members of this group.
|
||||||
manage-authz-group-scope-description=Policies that decide if an admin can manage this group
|
manage-authz-group-scope-description=Policies that decide if an admin can manage this group
|
||||||
view-authz-group-scope-description=Policies that decide if an admin can view this group
|
view-authz-group-scope-description=Policies that decide if an admin can view this group
|
||||||
view.members-authz-group-scope-description=Policies that decide if an admin can manage the members of this group
|
view-members-authz-group-scope-description=Policies that decide if an admin can manage the members of this group
|
||||||
manage.members-authz-group-scope-description=Policies that decide if an admin can view the members of this group
|
|
||||||
manage-authz-client-scope-description=Policies that decide if an admin can manage this client
|
manage-authz-client-scope-description=Policies that decide if an admin can manage this client
|
||||||
|
configure-authz-client-scope-description=Reduced management permissions for admin. Cannot set scope, template, or protocol mappers.
|
||||||
view-authz-client-scope-description=Policies that decide if an admin can view this client
|
view-authz-client-scope-description=Policies that decide if an admin can view this client
|
||||||
map-roles-authz-client-scope-description=Policies that decide if an admin can map roles defined by this client
|
map-roles-authz-client-scope-description=Policies that decide if an admin can map roles defined by this client
|
||||||
map-roles-client-scope-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client to the client scope of another client
|
map-roles-client-scope-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client to the client scope of another client
|
||||||
|
@ -1336,6 +1336,11 @@ map-roles-composite-authz-client-scope-description=Policies that decide if an ad
|
||||||
map-role-authz-role-scope-description=Policies that decide if an admin can map role this role to a user or group
|
map-role-authz-role-scope-description=Policies that decide if an admin can map role this role to a user or group
|
||||||
map-role-client-scope-authz-role-scope-description=Policies that decide if an admin can apply this role to the client scope of a client
|
map-role-client-scope-authz-role-scope-description=Policies that decide if an admin can apply this role to the client scope of a client
|
||||||
map-role-composite-authz-role-scope-description=Policies that decide if an admin can apply this role as a composite to another role
|
map-role-composite-authz-role-scope-description=Policies that decide if an admin can apply this role as a composite to another role
|
||||||
|
manage-group-membership-authz-users-scope-description=Policies that decide if an admin can manage group membership for all users in the realm. This is used in conjunction with specific group policy
|
||||||
|
impersonate-authz-users-scope-description=Policies that decide if admin can impersonate other users
|
||||||
|
map-roles-authz-users-scope-description=Policies that decide if admin can map roles for all users
|
||||||
|
user-impersonated-authz-users-scope-description=Policies that decide which users can be impersonated. These policies are applied to the user being impersonated.
|
||||||
|
manage-membership-authz-group-scope-description=Policies that decide if admin can add or remove users from this group
|
||||||
|
manage-members-authz-group-scope-description=Policies that decide if an admin can manage the members of this group
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2507,7 +2507,7 @@ module.controller('RealmRolePermissionsCtrl', function($scope, $http, $route, $l
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
module.controller('ClientRolePermissionsCtrl', function($scope, $http, $route, $location, realm, client, role, RoleManagementPermissions, Client, Notifications) {
|
module.controller('ClientRolePermissionsCtrl', function($scope, $http, $route, $location, realm, client, role, Client, RoleManagementPermissions, Client, Notifications) {
|
||||||
console.log('RealmRolePermissionsCtrl');
|
console.log('RealmRolePermissionsCtrl');
|
||||||
$scope.client = client;
|
$scope.client = client;
|
||||||
$scope.role = role;
|
$scope.role = role;
|
||||||
|
@ -2515,6 +2515,9 @@ module.controller('ClientRolePermissionsCtrl', function($scope, $http, $route, $
|
||||||
RoleManagementPermissions.get({realm: realm.realm, role: role.id}, function(data) {
|
RoleManagementPermissions.get({realm: realm.realm, role: role.id}, function(data) {
|
||||||
$scope.permissions = data;
|
$scope.permissions = data;
|
||||||
});
|
});
|
||||||
|
Client.query({realm: realm.realm, clientId: getManageClientId(realm)}, function(data) {
|
||||||
|
$scope.realmManagementClientId = data[0].id;
|
||||||
|
});
|
||||||
$scope.setEnabled = function() {
|
$scope.setEnabled = function() {
|
||||||
console.log('perssions enabled: ' + $scope.permissions.enabled);
|
console.log('perssions enabled: ' + $scope.permissions.enabled);
|
||||||
var param = { enabled: $scope.permissions.enabled};
|
var param = { enabled: $scope.permissions.enabled};
|
||||||
|
@ -2542,12 +2545,15 @@ module.controller('UsersPermissionsCtrl', function($scope, $http, $route, $locat
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('ClientPermissionsCtrl', function($scope, $http, $route, $location, realm, client, ClientManagementPermissions, Notifications) {
|
module.controller('ClientPermissionsCtrl', function($scope, $http, $route, $location, realm, client, Client, ClientManagementPermissions, Notifications) {
|
||||||
$scope.client = client;
|
$scope.client = client;
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
ClientManagementPermissions.get({realm: realm.realm, client: client.id}, function(data) {
|
ClientManagementPermissions.get({realm: realm.realm, client: client.id}, function(data) {
|
||||||
$scope.permissions = data;
|
$scope.permissions = data;
|
||||||
});
|
});
|
||||||
|
Client.query({realm: realm.realm, clientId: getManageClientId(realm)}, function(data) {
|
||||||
|
$scope.realmManagementClientId = data[0].id;
|
||||||
|
});
|
||||||
$scope.setEnabled = function() {
|
$scope.setEnabled = function() {
|
||||||
var param = { enabled: $scope.permissions.enabled};
|
var param = { enabled: $scope.permissions.enabled};
|
||||||
$scope.permissions = ClientManagementPermissions.update({realm: realm.realm, client: client.id}, param);
|
$scope.permissions = ClientManagementPermissions.update({realm: realm.realm, client: client.id}, param);
|
||||||
|
|
|
@ -27,9 +27,9 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
<td translate="{{scopeName}}-authz-client-scope-description"></td>
|
<td translate="{{scopeName}}-authz-client-scope-description"></td>
|
||||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -28,9 +28,9 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
<tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
|
||||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
<td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
|
||||||
<td translate="{{scopeName}}-authz-role-scope-description"></td>
|
<td translate="{{scopeName}}-authz-role-scope-description"></td>
|
||||||
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
<td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -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="client.access.manage" data-ng-click="unregisterNode()"></i>
|
<i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="client.access.configure" data-ng-click="unregisterNode()"></i>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!client.access.manage" data-ng-show="create || registered">
|
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!client.access.configure" 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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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="client.access.manage">
|
<th class="kc-table-actions" colspan="5" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<div>
|
<div>
|
||||||
<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">
|
<form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!client.access.configure" 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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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;">
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="form-horizontal no-margin-top" name="keyForm" novalidate kc-read-only="!client.access.manage" data-ng-controller="ClientSignedJWTCtrl">
|
<div class="form-horizontal no-margin-top" name="keyForm" novalidate kc-read-only="!client.access.configure" 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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div>
|
<div>
|
||||||
<form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!client.access.manage" data-ng-controller="ClientSecretCtrl">
|
<form class="form-horizontal no-margin-top" name="credentialForm" novalidate kc-read-only="!client.access.configure" 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="client.access.manage">
|
<div class="col-sm-6" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="clientForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="clientForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</div>
|
</div>
|
||||||
<kc-tooltip>{{:: 'client-protocol.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'client-protocol.tooltip' | translate}}</kc-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group" kc-read-only="!client.access.manage">
|
||||||
<label class="col-md-2 control-label" for="protocol">{{:: 'client-template' | translate}}</label>
|
<label class="col-md-2 control-label" for="protocol">{{:: 'client-template' | translate}}</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div>
|
<div>
|
||||||
|
@ -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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="form-group" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div>
|
<div>
|
||||||
<form class="form-horizontal" name="registrationAccessTokenForm" novalidate kc-read-only="!access.manageClients">
|
<form class="form-horizontal" name="registrationAccessTokenForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label" for="registrationAccessToken">{{:: 'registrationAccessToken' | translate}}</label>
|
<label class="col-md-2 control-label" for="registrationAccessToken">{{:: 'registrationAccessToken' | 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="registrationAccessToken" name="registrationAccessToken" data-ng-model="client.registrationAccessToken">
|
<input readonly kc-select-action="click" class="form-control" type="text" id="registrationAccessToken" name="registrationAccessToken" data-ng-model="client.registrationAccessToken">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6" data-ng-show="access.manageClients">
|
<div class="col-sm-6" data-ng-show="client.access.configure">
|
||||||
<button type="submit" data-ng-click="regenerateRegistrationAccessToken()" class="btn btn-default">{{:: 'registrationAccessToken.regenerate' | translate}}</button>
|
<button type="submit" data-ng-click="regenerateRegistrationAccessToken()" class="btn btn-default">{{:: 'registrationAccessToken.regenerate' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.configure">
|
||||||
|
|
||||||
<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 && client.access.manages">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="create && client.access.configure">
|
||||||
<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 && client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="!create && client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="client.access.manage">
|
<th class="kc-table-actions" colspan="5" data-ng-show="client.access.configure">
|
||||||
<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="client.access.manage" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
|
<td class="kc-action-cell" data-ng-show="client.access.configure" 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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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;">
|
||||||
|
|
||||||
|
|
|
@ -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="!client.access.manage">
|
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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="client.access.manage">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<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>
|
||||||
|
|
|
@ -25,14 +25,14 @@
|
||||||
<label class="col-md-2 control-label" for="fullScopeAllowed">{{:: 'full-scope-allowed' | translate}}</label>
|
<label class="col-md-2 control-label" for="fullScopeAllowed">{{:: 'full-scope-allowed' | translate}}</label>
|
||||||
<kc-tooltip>{{:: 'full-scope-allowed.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'full-scope-allowed.tooltip' | translate}}</kc-tooltip>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input ng-model="client.fullScopeAllowed" ng-click="changeFlag()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
|
<input kc-read-only="!client.access.manage" ng-model="client.fullScopeAllowed" ng-click="changeFlag()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" ng-show="client.useTemplateScope && template && template.fullScopeAllowed">
|
<div class="form-group" ng-show="client.useTemplateScope && template && template.fullScopeAllowed">
|
||||||
<label class="col-md-2 control-label" for="fullScopeAllowed">{{:: 'full-scope-allowed' | translate}}</label>
|
<label class="col-md-2 control-label" for="fullScopeAllowed">{{:: 'full-scope-allowed' | translate}}</label>
|
||||||
<kc-tooltip>Client template has full scope allowed, which means this client will have the full scope of all roles.</kc-tooltip>
|
<kc-tooltip>Client template has full scope allowed, which means this client will have the full scope of all roles.</kc-tooltip>
|
||||||
<div class="col-md-1">
|
<div class="col-md-1">
|
||||||
<input ng-model="template.fullScopeAllowed" name="fullScopeAllowed" id="fullScopeAllowed" ng-disabled="true" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
|
<input kc-read-only="!client.access.manage" ng-model="template.fullScopeAllowed" name="fullScopeAllowed" id="fullScopeAllowed" ng-disabled="true" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-1">
|
<div class="col-md-1">
|
||||||
<i>inherited</i>
|
<i>inherited</i>
|
||||||
|
|
|
@ -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="!client.access.manage" data-ng-show="client.serviceAccountsEnabled">
|
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.configure" 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="!client.access.manage" data-ng-show="!client.serviceAccountsEnabled">
|
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!client.access.configure" 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>
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/service-account-roles">{{:: 'service-account-roles' | translate}}</a>
|
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/service-account-roles">{{:: 'service-account-roles' | translate}}</a>
|
||||||
<kc-tooltip>{{:: 'service-account-roles.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'service-account-roles.tooltip' | translate}}</kc-tooltip>
|
||||||
</li>
|
</li>
|
||||||
<li ng-class="{active: path[4] == 'permissions'}">
|
<li ng-class="{active: path[4] == 'permissions'}" data-ng-show="client.access.manage && access.manageAuthorization">
|
||||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
||||||
<kc-tooltip>{{:: 'manage-permissions-client.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'manage-permissions-client.tooltip' | translate}}</kc-tooltip>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div data-ng-controller="GroupTabCtrl">
|
<div data-ng-controller="GroupTabCtrl">
|
||||||
<h1>
|
<h1>
|
||||||
{{group.name|capitalize}}
|
{{group.name|capitalize}}
|
||||||
<i id="removeGroup" class="pficon pficon-delete clickable" data-ng-show="access.manageUsers" data-ng-click="removeGroup()"></i>
|
<i id="removeGroup" class="pficon pficon-delete clickable" data-ng-show="group.access.manage" data-ng-click="removeGroup()"></i>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
<li ng-class="{active: path[4] == 'attributes'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/attributes">{{:: 'attributes' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'attributes'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/attributes">{{:: 'attributes' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'members'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/members">{{:: 'members' | translate}}</a></li>
|
<li ng-class="{active: path[4] == 'members'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/members">{{:: 'members' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'permissions'}">
|
<li ng-class="{active: path[4] == 'permissions'}" data-ng-show="group.access.manage && access.manageAuthorization">
|
||||||
<a href="#/realms/{{realm.realm}}/groups/{{group.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
<a href="#/realms/{{realm.realm}}/groups/{{group.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
||||||
<kc-tooltip>{{:: 'manage-permissions-group.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'manage-permissions-group.tooltip' | translate}}</kc-tooltip>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -5,7 +5,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]}"><a href="#/realms/{{realm.realm}}/roles/{{role.id}}">{{:: 'details' | translate}}</a></li>
|
<li ng-class="{active: !path[4]}"><a href="#/realms/{{realm.realm}}/roles/{{role.id}}">{{:: 'details' | translate}}</a></li>
|
||||||
<li ng-class="{active: path[4] == 'permissions'}">
|
<li ng-class="{active: path[4] == 'permissions'}" data-ng-show="access.manageRealm && access.manageAuthorization">
|
||||||
<a href="#/realms/{{realm.realm}}/roles/{{role.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
<a href="#/realms/{{realm.realm}}/roles/{{role.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
|
||||||
<kc-tooltip>{{:: 'manage-permissions-role.tooltip' | translate}}</kc-tooltip>
|
<kc-tooltip>{{:: 'manage-permissions-role.tooltip' | translate}}</kc-tooltip>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -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'}"data-ng-show="access.viewRealm">
|
<li ng-class="{active: path[2] == 'users-permissions'}" data-ng-show="access.manageUsers && access.manageAuthorization">
|
||||||
<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>
|
||||||
|
|
Loading…
Reference in a new issue