keycloak-memoizeit

Details

diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
index 2a2bf46..114595c 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js
@@ -58,9 +58,12 @@ module.config([ '$routeProvider', function($routeProvider) {
                 },
                 user : function(UserLoader) {
                     return UserLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
                 }
             },
-            controller : 'UserDetailCtrl'
+            controller : 'UserRoleMappingCtrl'
         }).when('/realms/:realm/users', {
 		templateUrl : 'partials/user-list.html',
 		resolve : {
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
index 9147e17..6c00e6a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js
@@ -192,6 +192,71 @@ module.controller('UserListCtrl', function($scope, realm, User) {
     };
 });
 
+Array.prototype.remove = function(from, to) {
+    var rest = this.slice((to || from) + 1 || this.length);
+    this.length = from < 0 ? this.length + from : from;
+    return this.push.apply(this, rest);
+};
+
+module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, roles, RealmRoleMapping) {
+    $scope.realm = realm;
+    $scope.user = user;
+    $scope.realmRoles = angular.copy(roles);
+    $scope.selectedRealmRoles = [];
+    $scope.selectedRealmMappings = [];
+    $scope.realmMappings = [];
+
+    $scope.realmMappings = RealmRoleMapping.query({realm : realm.id, userId : user.username}, function(){
+       for (var i = 0; i < $scope.realmMappings.length; i++) {
+           var role = $scope.realmMappings[i];
+           for (var j = 0; j < $scope.realmRoles.length; j++) {
+               var realmRole = $scope.realmRoles[j];
+               if (realmRole.id == role.id) {
+                   var idx = $scope.realmRoles.indexOf(realmRole);
+                   if (idx != -1) {
+                       $scope.realmRoles.splice(idx, 1);
+                       break;
+                   }
+               }
+           }
+       }
+    });
+
+    $scope.addRealmRole = function() {
+        $http.post('/auth-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/realm',
+                   $scope.selectedRealmRoles).success(function() {
+                for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
+                    var role = $scope.selectedRealmRoles[i];
+                    var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
+                    if (idx != -1) {
+                        $scope.realmRoles.splice(idx, 1);
+                        $scope.realmMappings.push(role);
+                    }
+                }
+                $scope.selectRealmRoles = [];
+            });
+    };
+
+    $scope.deleteRealmRole = function() {
+        console.log('deleteRealmRole');
+        $http.delete('/auth-server/rest/saas/admin/realms/' + realm.id + '/users/' + user.username + '/role-mappings/realm',
+                {data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
+                    var role = $scope.selectedRealmMappings[i];
+                    var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
+                    if (idx != -1) {
+                        $scope.realmMappings.splice(idx, 1);
+                        $scope.realmRoles.push(role);
+                    }
+                }
+                $scope.selectedRealmMappings = [];
+            });
+    };
+
+
+
+});
+
 module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
 	$scope.realm = realm;
 	$scope.user = angular.copy(user);
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
index 1b70951..3ee65ad 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js
@@ -83,10 +83,6 @@ module.factory('Notifications', function($rootScope, $timeout) {
 	return notifications;
 });
 
-module.factory('Provider', function($resource) {
-	return $resource('/ejs-identity/api/admin/providers');
-});
-
 module.factory('Realm', function($resource) {
 	return $resource('/auth-server/rest/saas/admin/realms/:id', {
 		id : '@id'
@@ -97,18 +93,6 @@ module.factory('Realm', function($resource) {
 	});
 });
 
-module.factory('RoleMapping', function($resource) {
-	return $resource('/keycloak-server/ui/api/roles/:realm/:role/:userId', {
-		realm : '@realm',
-		role : '@role',
-		userId : '@userId'
-	}, {
-		save : {
-			method : 'PUT'
-		}
-	});
-});
-
 module.factory('User', function($resource) {
 	return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId', {
 		realm : '@realm',
@@ -120,6 +104,21 @@ module.factory('User', function($resource) {
 	});
 });
 
+module.factory('RealmRoleMapping', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId/role-mappings/realm', {
+        realm : '@realm',
+        userId : '@userId'
+    });
+});
+
+module.factory('RealmRoles', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/roles', {
+        realm : '@realm'
+    });
+});
+
+
+
 module.factory('Role', function($resource) {
     return $resource('/auth-server/rest/saas/admin/realms/:realm/roles/:roleId', {
         realm : '@realm',
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-mappings.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-mappings.html
index 311afc0..d0cb06a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-mappings.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-mappings.html
@@ -6,7 +6,7 @@
                 <ul class="rcue-tabs" >
                     <li><a href="#/create/user/{{realm.id}}">New User</a></li>
                     <li><a href="#/realms/{{realm.id}}/users">Query Users</a></li>
-                    <li><a href="#">Attributes</a></li>
+                    <li><a href="#/realms/{{realm.id}}/users/{{user.username}}">Attributes</a></li>
                     <li><a href="#">Credentials</a></li>
                     <li class="active"><a href="#">Role Mappings</a></li>
                 </ul>
@@ -19,19 +19,17 @@
                         <legend uncollapsed><span class="text">Realm Roles</span> </legend>
                         <div class="form-group">
                             <div class="controls">
-                                <select multiple size=5>
-                                    <option value="role1">role1</option>
-                                    <option value="role2">role2</option>
-                                    <option value="role3">role3</option>
-                                    <option value="role4">role4</option>
+                                <select multiple size="5"
+                                        ng-multiple="true"
+                                        ng-model="selectedRealmRoles"
+                                        ng-options="r.name for r in realmRoles">
                                 </select>
-                                <button type="submit">---&gt;</button>
-                                <button type="submit">&lt;---</button>
-                                <select multiple size=5>
-                                    <option value="role1">role1</option>
-                                    <option disabled="disabled" value="role2">role2</option>
-                                    <option value="role3">role3</option>
-                                    <option value="role4">role4</option>
+                                <button type="submit" ng-click="addRealmRole()">---&gt;</button>
+                                <button type="submit" ng-click="deleteRealmRole()">&lt;---</button>
+                                <select multiple size=5
+                                        ng-multiple="true"
+                                        ng-model="selectedRealmMappings"
+                                        ng-options="r.name for r in realmMappings">
                                 </select>
                             </div>
                         </div>
@@ -57,26 +55,6 @@
                             </div>
                         </div>
                     </fieldset>
-
-                    <div class="form-actions" data-ng-show="createRealm">
-                        <button type="submit" data-ng-click="save()" class="primary" data-ng-show="changed">Save
-                        </button>
-                        <button type="submit" data-ng-click="cancel()" data-ng-click="cancel()"
-                                data-ng-show="changed">Cancel
-                        </button>
-                    </div>
-
-                    <div class="form-actions" data-ng-show="!createRealm">
-                        <button type="submit" data-ng-click="save()" class="primary" data-ng-show="changed">Save
-                            changes
-                        </button>
-                        <button type="submit" data-ng-click="reset()" data-ng-show="changed">Clear changes
-                        </button>
-                        <button type="submit" data-ng-click="remove()" class="danger" data-ng-hide="changed">
-                            Delete
-                        </button>
-                    </div>
-
                 </form>
             </div>
         </div>
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index eedcd86..709c638 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -1,6 +1,7 @@
 package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.logging.Logger;
 import org.keycloak.representations.idm.*;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.models.*;
@@ -8,6 +9,7 @@ import org.keycloak.services.models.*;
 import javax.ws.rs.*;
 import javax.ws.rs.container.ResourceContext;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.ArrayList;
@@ -20,6 +22,7 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class UsersResource {
+    protected static final Logger logger = Logger.getLogger(UsersResource.class);
 
     protected RealmModel realm;
 
@@ -123,6 +126,8 @@ public class UsersResource {
 
     @Path("{username}/role-mappings")
     @GET
+    @Produces("application/json")
+    @NoCache
     public AllRoleMappingsRepresentation getRoleMappings(@PathParam("username") String username) {
         UserModel user = realm.getUser(username);
         if (user == null) {
@@ -168,7 +173,9 @@ public class UsersResource {
 
     @Path("{username}/role-mappings/realm")
     @GET
-    public RealmRoleMappingsRepresentation getRealmRoleMappings(@PathParam("username") String username) {
+    @Produces("application/json")
+    @NoCache
+    public List<RoleRepresentation> getRealmRoleMappings(@PathParam("username") String username) {
         UserModel user = realm.getUser(username);
         if (user == null) {
             throw new NotFoundException();
@@ -176,20 +183,19 @@ public class UsersResource {
 
         RealmRoleMappingsRepresentation rep = new RealmRoleMappingsRepresentation();
         List<RoleModel> realmMappings = realm.getRoleMappings(user);
-        if (realmMappings.size() > 0) {
-            RealmManager manager = new RealmManager(session);
-            List<RoleRepresentation> realmRep = new ArrayList<RoleRepresentation>();
-            for (RoleModel roleModel : realmMappings) {
-                realmRep.add(manager.toRepresentation(roleModel));
-            }
-            rep.setMappings(realmRep);
+        List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
+        RealmManager manager = new RealmManager(session);
+        for (RoleModel roleModel : realmMappings) {
+            realmMappingsRep.add(manager.toRepresentation(roleModel));
         }
-        return rep;
+        return realmMappingsRep;
     }
 
     @Path("{username}/role-mappings/realm")
     @POST
+    @Consumes("application/json")
     public void addRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
+        logger.info("** addRealmRoleMappings: " + roles);
         UserModel user = realm.getUser(username);
         if (user == null) {
             throw new NotFoundException();
@@ -208,7 +214,9 @@ public class UsersResource {
 
     @Path("{username}/role-mappings/realm")
     @DELETE
-    public void deleteRoleMapping(@PathParam("username") String username, List<RoleRepresentation> roles) {
+    @Consumes("application/json")
+    public void deleteRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
+        logger.info("deleteRealmRoleMappings");
         UserModel user = realm.getUser(username);
         if (user == null) {
             throw new NotFoundException();
@@ -229,12 +237,13 @@ public class UsersResource {
                 realm.deleteRoleMapping(user, roleModel);
             }
         }
-
     }
 
     @Path("{username}/role-mappings/applications/{appId}")
     @GET
-    public ApplicationRoleMappings getApplicationRoleMappings(@PathParam("username") String username, @PathParam("appId") String appId) {
+    @Produces("application/json")
+    @NoCache
+    public List<RoleRepresentation> getApplicationRoleMappings(@PathParam("username") String username, @PathParam("appId") String appId) {
         UserModel user = realm.getUser(username);
         if (user == null) {
             throw new NotFoundException();
@@ -248,19 +257,17 @@ public class UsersResource {
 
         ApplicationRoleMappings rep = new ApplicationRoleMappings();
         List<RoleModel> mappings = application.getRoleMappings(user);
-        if (mappings.size() > 0) {
-            RealmManager manager = new RealmManager(session);
-            List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
-            for (RoleModel roleModel : mappings) {
-                mapRep.add(manager.toRepresentation(roleModel));
-            }
-            rep.setMappings(mapRep);
+        List<RoleRepresentation> mapRep = new ArrayList<RoleRepresentation>();
+        RealmManager manager = new RealmManager(session);
+        for (RoleModel roleModel : mappings) {
+            mapRep.add(manager.toRepresentation(roleModel));
         }
-        return rep;
+        return mapRep;
     }
 
     @Path("{username}/role-mappings/applications/{appId}")
     @POST
+    @Consumes("application/json")
     public void addApplicationRoleMapping(@PathParam("username") String username, @PathParam("appId") String appId, List<RoleRepresentation> roles) {
         UserModel user = realm.getUser(username);
         if (user == null) {
@@ -278,6 +285,7 @@ public class UsersResource {
 
     @Path("{username}/role-mappings/applications/{appId}")
     @DELETE
+    @Consumes("application/json")
     public void deleteApplicationRoleMapping(@PathParam("username") String username, @PathParam("appId") String appId, List<RoleRepresentation> roles) {
         UserModel user = realm.getUser(username);
         if (user == null) {