From e78615807137af75dddc584a00a4d4ecc87bda3f Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Wed, 8 Jul 2015 19:18:11 -0400 Subject: [PATCH] role selector --- .../broker/provider/HardcodedRoleMapper.java | 6 +- .../oidc/mappers/ClaimToRoleMapper.java | 4 +- .../ExternalKeycloakRoleToRoleMapper.java | 4 +- .../saml/mappers/AttributeToRoleMapper.java | 4 +- .../theme/base/admin/resources/js/app.js | 77 ++++++++++++++- .../theme/base/admin/resources/js/services.js | 94 +++++++++++++++++++ .../partials/authenticator-config.html | 2 +- .../identity-provider-mapper-detail.html | 2 +- .../partials/modal/role-selector.html | 40 ++++++++ .../partials/protocol-mapper-detail.html | 2 +- .../templates/kc-provider-config.html | 9 +- .../provider/ProviderConfigProperty.java | 1 + .../protocol/saml/mappers/HardcodedRole.java | 4 +- .../protocol/saml/mappers/RoleNameMapper.java | 4 +- .../protocol/ProtocolMapperUtils.java | 2 +- .../protocol/oidc/mappers/HardcodedRole.java | 4 +- .../protocol/oidc/mappers/RoleNameMapper.java | 2 +- 17 files changed, 238 insertions(+), 23 deletions(-) create mode 100755 forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java index 31684a097b..6eb4db9b66 100755 --- a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java +++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java @@ -27,15 +27,15 @@ public class HardcodedRoleMapper extends AbstractIdentityProviderMapper { property = new ProviderConfigProperty(); property.setName(ROLE); property.setLabel("Role"); - property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } public static String[] parseRole(String role) { - int scopeIndex = role.indexOf('.'); + int scopeIndex = role.lastIndexOf('.'); if (scopeIndex > -1) { String appName = role.substring(0, scopeIndex); role = role.substring(scopeIndex + 1); diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java index 564ac9c743..60f0d1bb7b 100755 --- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java +++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java @@ -43,8 +43,8 @@ public class ClaimToRoleMapper extends AbstractClaimMapper { property = new ProviderConfigProperty(); property.setName(HardcodedRoleMapper.ROLE); property.setLabel("Role"); - property.setHelpText("Role to grant to user if claim is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role to grant to user if claim is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java index f5bf539d47..0b93a3a53d 100755 --- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java +++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java @@ -40,8 +40,8 @@ public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper { property = new ProviderConfigProperty(); property.setName(HardcodedRoleMapper.ROLE); property.setLabel("Role"); - property.setHelpText("Role to grant to user if external role is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role to grant to user if external role is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java index 9c37dd8c98..c90b0b2302 100755 --- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java @@ -59,8 +59,8 @@ public class AttributeToRoleMapper extends AbstractIdentityProviderMapper { property = new ProviderConfigProperty(); property.setName(HardcodedRoleMapper.ROLE); property.setLabel("Role"); - property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js index 6a97f7cb24..f205ab0973 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js @@ -1579,14 +1579,87 @@ module.directive('kcNavigationUser', function () { } }); -module.directive('kcProviderConfig', function () { +module.controller('RoleSelectorModalCtrl', function($scope, realm, config, configName, RealmRoles, Client, ClientRole, $modalInstance) { + console.log('realm: ' + realm.realm); + $scope.selectedRealmRole = { + role: undefined + }; + $scope.selectedClientRole = { + role: undefined + }; + $scope.client = { + selected: undefined + }; + + $scope.selectRealmRole = function() { + config[configName] = $scope.selectedRealmRole.role.name; + $modalInstance.close(); + } + + $scope.selectClientRole = function() { + config[configName] = $scope.client.selected.clientId + "." + $scope.selectedClientRole.role.name; + $modalInstance.close(); + } + + $scope.cancel = function() { + $modalInstance.dismiss(); + } + + $scope.changeClient = function() { + if ($scope.client.selected) { + ClientRole.query({realm: realm.realm, client: $scope.client.selected.id}, function (data) { + $scope.clientRoles = data; + }); + } else { + console.log('selected client was null'); + $scope.clientRoles = null; + } + + } + RealmRoles.query({realm: realm.realm}, function(data) { + $scope.realmRoles = data; + }) + Client.query({realm: realm.realm}, function(data) { + $scope.clients = data; + if (data.length > 0) { + $scope.client.selected = data[0]; + $scope.changeClient(); + } + }) +}); + + +module.directive('kcProviderConfig', function ($modal) { return { scope: { config: '=', - properties: '=' + properties: '=', + realm: '=' }, restrict: 'E', replace: true, + link: function(scope, element, attrs) { + scope.openRoleSelector = function(configName) { + $modal.open({ + templateUrl: resourceUrl + '/partials/modal/role-selector.html', + controller: 'RoleSelectorModalCtrl', + resolve: { + realm: function () { + return scope.realm; + }, + config: function() { + return scope.config; + }, + configName: function() { + + return configName; + } + } + }) + + }; + + }, templateUrl: resourceUrl + '/templates/kc-provider-config.html' } }); diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js index f3c4475495..31071017a9 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js @@ -1118,4 +1118,98 @@ module.factory('AuthenticationExecutionConfig', function($resource) { }); }); +module.service('SelectRoleDialog', function($modal) { + var dialog = {}; + + var openDialog = function(title, message, btns) { + var controller = function($scope, $modalInstance, title, message, btns) { + $scope.title = title; + $scope.message = message; + $scope.btns = btns; + + $scope.ok = function () { + $modalInstance.close(); + }; + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; + }; + + return $modal.open({ + templateUrl: resourceUrl + '/templates/kc-modal.html', + controller: controller, + resolve: { + title: function() { + return title; + }, + message: function() { + return message; + }, + btns: function() { + return btns; + } + } + }).result; + } + + var escapeHtml = function(str) { + var div = document.createElement('div'); + div.appendChild(document.createTextNode(str)); + return div.innerHTML; + }; + + dialog.confirmDelete = function(name, type, success) { + var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1)); + var msg = 'Are you sure you want to permanently delete the ' + type + ' ' + name + '?'; + var btns = { + ok: { + label: 'Delete', + cssClass: 'btn btn-danger' + }, + cancel: { + label: 'Cancel', + cssClass: 'btn btn-default' + } + } + + openDialog(title, msg, btns).then(success); + } + + dialog.confirmGenerateKeys = function(name, type, success) { + var title = 'Generate new keys for realm'; + var msg = 'Are you sure you want to permanently generate new keys for ' + name + '?'; + var btns = { + ok: { + label: 'Generate Keys', + cssClass: 'btn btn-danger' + }, + cancel: { + label: 'Cancel', + cssClass: 'btn btn-default' + } + } + + openDialog(title, msg, btns).then(success); + } + + dialog.confirm = function(title, message, success, cancel) { + var btns = { + ok: { + label: title, + cssClass: 'btn btn-danger' + }, + cancel: { + label: 'Cancel', + cssClass: 'btn btn-default' + } + } + + openDialog(title, message, btns).then(success, cancel); + } + + return dialog +}); + + + diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html index d6f3700083..6345f3ab63 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html @@ -26,7 +26,7 @@ Name of the configuration. - +
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html index 80b8d45432..ad89039aed 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html @@ -45,7 +45,7 @@
{{mapperType.helpText}} - +
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html new file mode 100755 index 0000000000..be2f42c5c2 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html @@ -0,0 +1,40 @@ +
+

Role Selector

+
+
+ + Realm roles that can be selected. + + +
+
+
+
+ + + +
+
+ +
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html index 4697245cac..9b9e33a6d2 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html @@ -69,7 +69,7 @@
{{mapperType.helpText}} - +
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html index 31ac3be50c..0dd4f950ba 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html @@ -1,7 +1,7 @@
-
+
@@ -12,5 +12,12 @@
+
+ +
+
+ +
+ {{option.helpText}}
diff --git a/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java b/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java index fad9d6cf43..69e1d1673a 100755 --- a/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java +++ b/model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java @@ -7,6 +7,7 @@ package org.keycloak.provider; public class ProviderConfigProperty { public static final String BOOLEAN_TYPE="boolean"; public static final String STRING_TYPE="String"; + public static final String ROLE_TYPE="Role"; public static final String LIST_TYPE="List"; public static final String CLIENT_LIST_TYPE="ClientList"; diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java index 321727a4f2..a4ac579b7b 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedRole.java @@ -25,8 +25,8 @@ public class HardcodedRole extends AbstractSAMLProtocolMapper { property = new ProviderConfigProperty(); property.setName("role"); property.setLabel("Role"); - property.setHelpText("Role name you want to hardcode."); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Arbitrary role name you want to hardcode. This role does not have to exist in current realm and can be just any string you need"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java index e47ca3d12b..38a42ada30 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java @@ -31,8 +31,8 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRo property = new ProviderConfigProperty(); property.setName(ROLE_CONFIG); property.setLabel("Role"); - property.setHelpText("Role name you want changed. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role name you want changed. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); property = new ProviderConfigProperty(); property.setName(NEW_ROLE_NAME); diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java index 457084ac57..fecd27fae7 100755 --- a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java +++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java @@ -47,7 +47,7 @@ public class ProtocolMapperUtils { } public static String[] parseRole(String role) { - int scopeIndex = role.indexOf('.'); + int scopeIndex = role.lastIndexOf('.'); if (scopeIndex > -1) { String appName = role.substring(0, scopeIndex); role = role.substring(scopeIndex + 1); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java index fd1910fda8..66ef2db2a3 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java @@ -31,8 +31,8 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc property = new ProviderConfigProperty(); property.setName(ROLE_CONFIG); property.setLabel("Role"); - property.setHelpText("Role you want added to the token. To specify an application role the syntax is appname.approle, i.e. myapp.myrole"); - property.setType(ProviderConfigProperty.STRING_TYPE); + property.setHelpText("Role you want added to the token. Click 'Select Role' button to browse roles, or just type it in the textbox. To specify an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.ROLE_TYPE); configProperties.add(property); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java index 35bb712eb5..ac79736e9f 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java @@ -34,7 +34,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc property = new ProviderConfigProperty(); property.setName(ROLE_CONFIG); property.setLabel("Role"); - property.setHelpText("Role name you want changed. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setHelpText("Role name you want changed. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); property.setType(ProviderConfigProperty.STRING_TYPE); configProperties.add(property); property = new ProviderConfigProperty();