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 31684a097b6..6eb4db9b662 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 564ac9c7433..60f0d1bb7bc 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 f5bf539d475..0b93a3a53db 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 9c37dd8c985..c90b0b23024 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 6a97f7cb243..f205ab0973d 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 f3c44754958..31071017a91 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 d6f3700083a..6345f3ab63f 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 80b8d454327..ad89039aedd 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 00000000000..be2f42c5c20 --- /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 4697245cac0..9b9e33a6d22 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 31ac3be50c0..0dd4f950baf 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 fad9d6cf43e..69e1d1673a0 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 321727a4f22..a4ac579b7b1 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 e47ca3d12b8..38a42ada300 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 457084ac57f..fecd27fae75 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 fd1910fda87..66ef2db2a3c 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 35bb712eb5f..ac79736e9f9 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();