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