keycloak-aplcache

role selector

7/8/2015 8:18:11 PM

Changes

Details

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 31684a0..6eb4db9 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 564ac9c..60f0d1b 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 f5bf539..0b93a3a 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 9c37dd8..c90b0b2 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 6a97f7c..f205ab0 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 f3c4475..3107101 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 d6f3700..6345f3a 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 @@
                 </div>
                 <kc-tooltip>Name of the configuration.</kc-tooltip>
             </div>
-            <kc-provider-config config="config.config" properties="configType.properties"></kc-provider-config>
+            <kc-provider-config realm="realm" config="config.config" properties="configType.properties"></kc-provider-config>
         </fieldset>
 
         <div class="form-group">
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 80b8d45..ad89039 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 @@
                 </div>
                 <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
             </div>
-            <kc-provider-config config="mapper.config" properties="mapperType.properties"></kc-provider-config>
+            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
         </fieldset>
         <div class="pull-right form-actions" data-ng-show="create && access.manageRealm">
             <button kc-cancel data-ng-click="cancel()">Cancel</button>
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 0000000..be2f42c
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
@@ -0,0 +1,40 @@
+<div style="padding: 15px 60px 75px 60px">
+    <h2>Role Selector</h2>
+    <form>
+        <div data-ng-show="realmRoles.length > 0">
+        <label class="control-label" for="available">Realm Roles</label>
+        <kc-tooltip>Realm roles that can be selected.</kc-tooltip>
+        <select id="available" class="form-control" size="5"
+                ng-dblclick="selectRealmRole()"
+                ng-model="selectedRealmRole.role"
+                ng-options="r.name for r in realmRoles | orderBy:'toString()'">
+            <option style="display:none" value="">Select a role</option>
+        </select>
+        <button class="btn btn-default" type="submit" ng-click="selectRealmRole()" tooltip="Select realm role" tooltip-placement="right">
+            Select Realm Role</i>
+        </button>
+        </div>
+        <br>
+        <br>
+        <div data-ng-show="clients.length > 0">
+        <label class="control-label">
+            <span>Client Roles</span>
+            <kc-tooltip>Client roles that can be selected.</kc-tooltip>
+            <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client.selected" ng-options="a.clientId for a in clients" ng-disabled="false">
+            </select>
+        </label>
+        <select id="available-client" class="form-control" size="5"
+                ng-dblclick="selectClientRole()"
+                ng-model="selectedClientRole.role"
+                ng-options="r.name for r in clientRoles | orderBy:'toString()'">
+            <option style="display:none" value="">Select a role</option>
+        </select>
+        <button class="btn btn-default" type="submit" ng-click="selectClientRole()" tooltip="Select client role" tooltip-placement="right">
+            Select Client Role
+        </button>
+        </div>
+    </form>
+    <div class="modal-footer">
+        <button type="button" data-ng-class="btns.cancel.cssClass" ng-click="cancel()">Cancel</button>
+    </div>
+</div>
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 4697245..9b9e33a 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 @@
                 </div>
                 <kc-tooltip>{{mapperType.helpText}}</kc-tooltip>
             </div>
-            <kc-provider-config config="mapper.config" properties="mapperType.properties"></kc-provider-config>
+            <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
         </fieldset>
 
         <div class="form-group">
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 31ac3be..0dd4f95 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 @@
 <div data-ng-repeat="option in properties" class="form-group">
     <label class="col-md-2 control-label">{{option.label}}</label>
 
-    <div class="col-sm-6" data-ng-hide="option.type == 'boolean' || option.type == 'List'">
+    <div class="col-sm-6" data-ng-hide="option.type == 'boolean' || option.type == 'List' || option.type == 'Role'">
         <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
     </div>
     <div class="col-sm-6" data-ng-show="option.type == 'boolean'">
@@ -12,5 +12,12 @@
             <option value="" selected> Select one... </option>
         </select>
     </div>
+    <div class="col-sm-6" data-ng-show="option.type == 'Role'">
+        <input class="form-control" type="text" data-ng-model="config[ option.name ]" >
+    </div>
+    <div class="col-sm-4" data-ng-show="option.type == 'Role'">
+        <button type="submit" data-ng-click="openRoleSelector(option.name)" class="btn btn-default" tooltip="Enter role in the textbox to the left, or click this button to browse and select the role you want">Select Role</button>
+    </div>
+
     <kc-tooltip>{{option.helpText}}</kc-tooltip>
 </div>
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 fad9d6c..69e1d16 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 321727a..a4ac579 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 e47ca3d..38a42ad 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/oidc/mappers/HardcodedRole.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
index fd1910f..66ef2db 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 35bb712..ac79736 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();
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
index 457084a..fecd27f 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);