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