keycloak-aplcache

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
index 60fbc6b..4a16101 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -5,6 +5,7 @@ package org.keycloak.representations.idm;
  * @version $Revision: 1 $
  */
 public class RoleRepresentation {
+    protected String id;
     protected String name;
     protected String description;
 
@@ -16,6 +17,14 @@ public class RoleRepresentation {
         this.description = description;
     }
 
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
     public String getName() {
         return name;
     }
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 8e5a3c0..ac6333a 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
@@ -92,43 +92,42 @@ module.config([ '$routeProvider', function($routeProvider) {
 		},
 		controller : 'UserListCtrl'
 	})
-	
-	.when('/realms/:realm/roles', {
-		templateUrl : 'partials/role-mapping.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return RealmLoader();
-			},
-			application : function() {
-				return null;
-			},
-			users : function() {
-				return null;
-			},
-			role : function() {
-				return null;
-			}
-		},
-		controller : 'RoleMappingCtrl'
-	}).when('/realms/:realm/roles/:role', {
-		templateUrl : 'partials/role-mapping.html',
-		resolve : {
-			realm : function(RealmLoader) {
-				return RealmLoader();
-			},
-			application : function() {
-				return null;
-			},
-			role : function($route) {
-				return $route.current.params.role;
-			},
-			users : function(RoleMappingLoader) {
-				return RoleMappingLoader();
-			}
-		},
-		controller : 'RoleMappingCtrl'
-	})
-	
+
+        .when('/create/role/:realm', {
+            templateUrl : 'partials/role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                role : function() {
+                    return {};
+                }
+            },
+            controller : 'RoleDetailCtrl'
+        }).when('/realms/:realm/roles/:role', {
+            templateUrl : 'partials/role-detail.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                role : function(RoleLoader) {
+                    return RoleLoader();
+                }
+            },
+            controller : 'RoleDetailCtrl'
+        }).when('/realms/:realm/roles', {
+            templateUrl : 'partials/role-list.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                roles : function(RoleListLoader) {
+                    return RoleListLoader();
+                }
+            },
+            controller : 'RoleListCtrl'
+        })
+
 	.when('/applications/:application/roles', {
 		templateUrl : 'partials/role-mapping.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 8224fe4..a3ed7c2 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
@@ -2,7 +2,9 @@
 
 var module = angular.module('keycloak.controllers', [ 'keycloak.services' ]);
 
-module.controller('GlobalCtrl', function($scope, Auth, $location, Notifications) {
+var realmslist = {};
+
+module.controller('GlobalCtrl', function($scope, $http, Auth, $location, Notifications) {
 	$scope.addMessage = function() {
 		Notifications.success("test");
 	};
@@ -14,6 +16,28 @@ module.controller('GlobalCtrl', function($scope, Auth, $location, Notifications)
 	}, function() {
 		$scope.path = $location.path().substring(1).split("/");
 	});
+
+    $http.get('/auth-server/rest/saas/admin/realms').success(function(data) {
+        var count = 0;
+        var showrealm = false;
+        var id = null;
+        for (var key in data) {
+            if (count > 0) {
+                showrealm = false;
+                break;
+            }
+            id = key;
+            showrealm = true;
+            count++;
+        }
+
+        if (showrealm) {
+            console.log('redirecting');
+            $location.url("/realms/" + id);
+        } else {
+            console.log('not redirecting');
+        }
+    });
 });
 
 module.controller('ApplicationListCtrl', function($scope, Application) {
@@ -130,13 +154,22 @@ module.controller('ApplicationDetailCtrl', function($scope, application, Applica
 
 module.controller('RealmListCtrl', function($scope, Realm) {
 	$scope.realms = Realm.get();
+    realmslist = $scope.realms;
+});
+
+module.controller('RealmDropdownCtrl', function($scope, Realm) {
+    console.log('test log writing');
+    realmslist = Realm.get();
+    $scope.realmslist = function() {
+        return realmslist;
+    };
 });
 
 module.controller('RealmDetailCtrl', function($scope, Realm, realm, $location, Dialog, Notifications) {
 	$scope.realm = angular.copy(realm);
-	$scope.create = !realm.id;
+	$scope.createRealm = !realm.id;
 
-    if ($scope.create) {
+    if ($scope.createRealm) {
         $scope.realm.enabled = true;
         $scope.realm.requireSsl = true;
         $scope.realm.cookieLoginAllowed = true;
@@ -223,15 +256,17 @@ module.controller('RealmDetailCtrl', function($scope, Realm, realm, $location, D
 
             };
 
-            if ($scope.create) {
+            if ($scope.createRealm) {
 				Realm.save(realmCopy, function(data, headers) {
 					var l = headers().location;
 					var id = l.substring(l.lastIndexOf("/") + 1);
+                    realmslist = Realm.get();
 					$location.url("/realms/" + id);
 					Notifications.success("Created realm");
 				});
 			} else {
 				Realm.update(realmCopy, function() {
+                    realmslist = Realm.get();
 					$scope.changed = false;
 					realm = angular.copy($scope.realm);
 					Notifications.success("Saved changes to realm");
@@ -255,6 +290,7 @@ module.controller('RealmDetailCtrl', function($scope, Realm, realm, $location, D
 	$scope.remove = function() {
 		Dialog.confirmDelete($scope.realm.name, 'realm', function() {
 			Realm.remove($scope.realm, function() {
+                realmslist = Realm.get();
 				$location.url("/realms");
 				Notifications.success("Deleted realm");
 			});
@@ -283,6 +319,9 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
 
 	$scope.save = function() {
 		if ($scope.userForm.$valid) {
+
+
+
 			User.save({
 				realm : realm.id
 			}, $scope.user, function() {
@@ -324,6 +363,79 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
 	};
 });
 
+module.controller('RoleListCtrl', function($scope, realm, roles) {
+    $scope.realm = realm;
+    $scope.roles = roles;
+});
+
+module.controller('RoleDetailCtrl', function($scope, realm, role, Role, $location, Dialog, Notifications) {
+    $scope.realm = realm;
+    $scope.role = angular.copy(role);
+    $scope.create = !role.name;
+
+    $scope.changed = $scope.create;
+
+    $scope.$watch('role', function() {
+        if (!angular.equals($scope.role, role)) {
+            $scope.changed = true;
+        }
+    }, true);
+
+    $scope.save = function() {
+        if ($scope.roleForm.$valid) {
+
+            if ($scope.create) {
+                Role.save({
+                    realm: realm.id
+                }, $scope.role, function (data, headers) {
+                    $scope.changed = false;
+                    role = angular.copy($scope.role);
+
+                    var l = headers().location;
+                    var id = l.substring(l.lastIndexOf("/") + 1);
+                    $location.url("/realms/" + realm.id + "/roles/" + id);
+                    Notifications.success("Created role");
+
+                });
+            } else {
+                Role.update({
+                    realm : realm.id,
+                    roleId : role.id
+                }, $scope.role, function() {
+                    $scope.changed = false;
+                    role = angular.copy($scope.role);
+                    Notifications.success("Saved changes to role");
+                });
+            }
+
+         } else {
+            $scope.roleForm.showErrors = true;
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.role = angular.copy(user);
+        $scope.changed = false;
+        $scope.roleForm.showErrors = false;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.id + "/roles");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.role.name, 'role', function() {
+            $scope.role.$remove({
+                realm : realm.id,
+                role : $scope.role.name
+            }, function() {
+                $location.url("/realms/" + realm.id + "/roles");
+                Notifications.success("Deleted role");
+            });
+        });
+    };
+});
+
 module.controller('RoleMappingCtrl', function($scope, realm, User, users, role, RoleMapping, Notifications) {
 	$scope.realm = realm;
 	$scope.realmId = realm.realm || realm.id;
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
index fae62e8..2b6f5bf 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/loaders.js
@@ -72,6 +72,24 @@ module.factory('UserLoader', function(Loader, User, $route, $q) {
 	});
 });
 
+module.factory('RoleLoader', function(Loader, Role, $route, $q) {
+    return Loader.get(Role, function() {
+        return {
+            realm : $route.current.params.realm,
+            roleId : $route.current.params.role
+        }
+    });
+});
+
+module.factory('RoleListLoader', function(Loader, Role, $route, $q) {
+    return Loader.query(Role, function() {
+        return {
+            realm : $route.current.params.realm
+        }
+    });
+});
+
+
 module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) {
 	var realm = $route.current.params.realm || $route.current.params.application;
 
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 458981d..ba3a26a 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
@@ -146,4 +146,15 @@ module.factory('User', function($resource) {
 			method : 'PUT'
 		}
 	});
+});
+
+module.factory('Role', function($resource) {
+    return $resource('/auth-server/rest/saas/admin/realms/:realm/roles/:roleId', {
+        realm : '@realm',
+        roleId : '@roleId'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
 });
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
index c46189d..effc324 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/menu.html
@@ -3,23 +3,29 @@
         <div class="container">
             <div class="nav-collapse">
                 <nav id="global-nav">
+                    <div data-ng-controller="RealmDropdownCtrl">
+                        <ul class="nav pull-left" data-ng-show="auth.loggedIn">
+                            <li class="dropdown"><a data-toggle="dropdown" class="dropdown-toggle" href="#"> Realms <i class="caret"></i></a>
+                                <ul class="dropdown-menu">
+                                    <li ng-repeat="(id, name) in realmslist()"><a href="#/realms/{{id}}">{{name}}</a>
+                                    </li>
+                                </ul>
+                            </li>
+                        </ul>
+                    </div>
                     <ul class="nav">
-                        <li class="divider-vertical-left" data-ng-class="path[0] == '' && 'active'"><a href="#">Home</a>
-                        </li>
-                        <li class="divider-vertical-left" data-ng-class="path[0] == 'applications' && 'active'"
-                            data-ng-show="auth.loggedIn"><a href="#/applications">Applications</a></li>
                         <li class="divider-vertical-left" data-ng-class="path[0] == 'realms' && 'active'"
-                            data-ng-show="auth.loggedIn"><a href="#/realms">Realms</a></li>
+                            data-ng-show="auth.loggedIn"><a href="#/create/realm">New Realm</a></li>
                     </ul>
                     <ul class="nav pull-right" data-ng-hide="auth.loggedIn">
                         <li><a href="/auth-server/saas/saas-login.jsp">Login</a></li>
-                        <li><a href="/ejs-identity/api/register/system">Register</a></li>
+                        <li><a href="/auth-server/saas/saas-register.jsp">Register</a></li>
                     </ul>
                     <ul class="nav pull-right" data-ng-show="auth.loggedIn">
                         <li class="dropdown"><a data-toggle="dropdown" class="dropdown-toggle" href="#"><i
-                                class="icon-user icon-gray"></i> {{auth.user.displayName}} <i class="caret"></i></a>
+                                class="icon-user icon-gray"></i> Welcome: <b>{{auth.user.displayName}}</b> <i class="caret"></i></a>
                             <ul class="dropdown-menu">
-                                <li><a href="/auth-server/rest/saas/logout" >Sign Out</a></li>  <!--data-ng-click="auth.logout()" -->
+                                <li><a href="/auth-server/rest/saas/logout">Sign Out</a></li>
                             </ul>
                         </li>
                     </ul>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-detail.html
index d604f19..7a841a1 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-detail.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-detail.html
@@ -4,10 +4,10 @@
         <div id="actions-bg"></div>
 
         <div id="container-right" class="span9">
-            <h1 data-ng-show="create"><span class="gray">New Realm</span></h1>
+            <h1 data-ng-show="createRealm"><span class="gray">New Realm</span></h1>
 
-            <h1 data-ng-hide="create">
-                <span class="gray">{{realm.realm}}</span> configuration
+            <h1 data-ng-hide="createRealm">
+                <span class="gray">{{realm.realm}}</span>
             </h1>
 
             <div data-ng-show="realmForm.showErrors && realmForm.$error.required" class="alert alert-error">Please fill
@@ -82,47 +82,7 @@
                         </div>
                     </div>
                 </fieldset>
-
-                <fieldset>
-                    <legend>Roles</legend>
-
-                    <div class="control-group">
-                        <label class="control-label">Roles</label>
-
-                        <div class="controls">
-                            <span class="label" style="margin-right: 1em;"
-                                  data-ng-repeat="r in (realm.roles|orderBy:'toString()')">{{r}} <button
-                                    data-ng-click="removeRole(r)"><i class="icon-remove icon-white"></i></button></span>
-
-                            <div class="input-append">
-                                <input class="input-small" type="text" data-ng-model="newRole" placeHolder="Role"
-                                       data-kc-enter="addRole()"/>
-                                <button class="btn" type="button" data-ng-click="addRole()">Add</button>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="control-group">
-                        <label class="control-label">Initial Roles</label>
-
-                        <div class="controls">
-                            <span class="label" style="margin-right: 1em;"
-                                  data-ng-repeat="r in (realm.initialRoles|orderBy:'toString()')">{{r}} <button
-                                    data-ng-click="removeInitialRole(r)"><i class="icon-remove icon-white"></i></button></span>
-
-                            <div class="input-append">
-                                <select style="width: auto;" data-ng-model="newInitialRole"
-                                        data-ng-click="addInitialRole()">
-                                    <option data-ng-repeat="r in (realm.roles|remove:realm.initialRoles|orderBy:'toString()')"
-                                            value="{{r}}">{{r}}
-                                    </option>
-                                </select>
-                            </div>
-                        </div>
-                    </div>
-                </fieldset>
-
-                <div class="form-actions" data-ng-show="create">
+                <div class="form-actions" data-ng-show="createRealm">
                     <button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
                     </button>
                     <button type="submit" data-ng-click="cancel()" class="btn" data-ng-click="cancel()"
@@ -130,7 +90,7 @@
                     </button>
                 </div>
 
-                <div class="form-actions" data-ng-show="!create">
+                <div class="form-actions" data-ng-show="!createRealm">
                     <button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
                         changes
                     </button>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
index a70c236..d72e57a 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html
@@ -1,21 +1,21 @@
-<nav id="local-nav" data-ng-controller="RealmListCtrl">
-    <ul class="nav nav-list">
-        <li>
-            <div>
-                <span class="toggle">Realms</span>
-            </div>
-            <ul>
-                <li data-ng-repeat="r in realms" data-ng-class="path[1] == r.id && 'active'">
-                    <a href=#/realms/{{r.id}}>{{r.name}}</a>
-                    <ul class="sub-items" data-ng-show="path[1] == r.id">
-                        <li data-ng-class="!path[2] && 'active'"><a href="#/realms/{{r.id}}">Configuration</a></li>
-                        <li data-ng-class="path[2] == 'users' && 'active'"><a href="#/realms/{{r.id}}/users">Users</a>
-                        </li>
-                        <li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{r.id}}/roles">Role
-                            mapping</a></li>
-                    </ul>
-                </li>
-            </ul>
-        </li>
-    </ul>
-</nav>
\ No newline at end of file
+<div data-ng-hide="createRealm">
+    <nav id="local-nav">
+        <ul class="nav nav-list">
+            <li>
+                <div>
+                    <span class="toggle">Realm: </span> {{realm.realm}}
+                </div>
+                <ul>
+                    <li>
+                        <ul class="sub-items">
+                            <li data-ng-class="!path[2] && 'active'"><a href="#/realms/{{realm.id}}">Settings</a>
+                            </li>
+                            <li data-ng-class="path[2] == 'users' && 'active'"><a href="#/realms/{{realm.id}}/users">Users</a>
+                            </li>
+                            <li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
+                        </ul>
+                    </li>
+                </ul>
+        </ul>
+    </nav>
+</div>
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html
new file mode 100755
index 0000000..39686d6
--- /dev/null
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html
@@ -0,0 +1,62 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <aside class="span3" data-ng-include data-src="'partials/realm-menu.html'"></aside>
+        <div id="actions-bg"></div>
+
+        <div id="container-right" class="span9">
+            <h1 data-ng-show="create"><span class="gray">New Role</span></h1>
+
+            <h1 data-ng-hide="create">
+                <span class="gray">Role {{role.name}}</span>
+            </h1>
+
+            <div data-ng-show="roleForm.showErrors && roleForm.$error.required" class="alert alert-error">Please fill in
+                all required fields
+            </div>
+            <p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
+
+            <form class="form-horizontal" name="roleForm" novalidate>
+                <fieldset>
+                    <legend>Details</legend>
+                    <div class="control-group">
+                        <label class="control-label" for="name">Role name <span class="required">*</span></label>
+
+                        <div class="controls">
+                            <input type="text" class="input-xlarge" id="name" name="name" data-ng-model="role.name"
+                                   autofocus required data-ng-readonly="!create">
+                        </div>
+                    </div>
+
+                    <div class="control-group">
+                        <label class="control-label" for="description">Description </label>
+
+                        <div class="controls">
+                            <input type="text" class="input-xlarge" id="description" name="description" data-ng-model="role.description">
+                        </div>
+                    </div>
+                </fieldset>
+                <div class="form-actions" data-ng-show="create">
+                    <button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
+                    </button>
+                    <button type="submit" data-ng-click="cancel()" class="btn" data-ng-click="cancel()"
+                            data-ng-show="changed">Cancel
+                    </button>
+                </div>
+
+                <div class="form-actions" data-ng-show="!create">
+                    <button type="submit" data-ng-click="save()" class="btn btn-primary" data-ng-show="changed">Save
+                        changes
+                    </button>
+                    <button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
+                    </button>
+                    <a href="#/realms/{{realm.id}}/users" data-ng-hide="changed">View users &#187;</a>
+                    <button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
+                        Delete
+                    </button>
+                </div>
+
+            </form>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-list.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-list.html
new file mode 100755
index 0000000..1693cb1
--- /dev/null
+++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-list.html
@@ -0,0 +1,28 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <aside class="span3" data-ng-include data-src="'partials/realm-menu.html'"></aside>
+        <div id="actions-bg"></div>
+
+        <div id="container-right" class="span9">
+            <a class="btn btn-small pull-right" href="#/create/role/{{realm.id}}">Add Role</a>
+
+            <h1>
+                <span class="gray">{{realm.realm}}</span> roles
+            </h1>
+
+            <table class="table table-striped table-bordered">
+                <thead>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                </tr>
+                </thead>
+                <tr data-ng-repeat="role in roles">
+                    <td><a href="#/realms/{{realm.id}}/roles/{{role.id}}">{{role.name}}</a></td>
+                    <td>{{role.description}}</td>
+                </tr>
+            </table>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java b/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java
index 7bff8af..bb7c2b2 100755
--- a/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java
+++ b/services/src/main/java/org/keycloak/services/models/picketlink/RealmAdapter.java
@@ -26,6 +26,7 @@ import org.picketlink.idm.credential.TOTPCredential;
 import org.picketlink.idm.credential.TOTPCredentials;
 import org.picketlink.idm.credential.UsernamePasswordCredentials;
 import org.picketlink.idm.credential.X509CertificateCredentials;
+import org.picketlink.idm.model.IdentityType;
 import org.picketlink.idm.model.sample.Grant;
 import org.picketlink.idm.model.sample.Role;
 import org.picketlink.idm.model.sample.SampleModel;
@@ -339,6 +340,15 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public RoleModel getRoleById(String id) {
+        IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
+        query.setParameter(IdentityType.ID, id);
+        List<Role> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(roles.get(0), getIdm());
+    }
+
+    @Override
     public RoleAdapter addRole(String name) {
         Role role = new Role(name);
         getIdm().add(role);
diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/RoleAdapter.java b/services/src/main/java/org/keycloak/services/models/picketlink/RoleAdapter.java
index a17aaf1..2d715e2 100755
--- a/services/src/main/java/org/keycloak/services/models/picketlink/RoleAdapter.java
+++ b/services/src/main/java/org/keycloak/services/models/picketlink/RoleAdapter.java
@@ -25,11 +25,22 @@ public class RoleAdapter implements RoleModel {
     }
 
     @Override
+    public String getId() {
+        return role.getId();
+    }
+
+    @Override
     public String getName() {
         return role.getName();
     }
 
     @Override
+    public void setName(String name) {
+        role.setName(name);
+        idm.update(role);
+    }
+
+    @Override
     public String getDescription() {
         Attribute<Serializable> description = role.getAttribute("description");
         if (description == null) return null;
diff --git a/services/src/main/java/org/keycloak/services/models/RealmModel.java b/services/src/main/java/org/keycloak/services/models/RealmModel.java
index fa01607..abb7e1d 100755
--- a/services/src/main/java/org/keycloak/services/models/RealmModel.java
+++ b/services/src/main/java/org/keycloak/services/models/RealmModel.java
@@ -98,4 +98,6 @@ public interface RealmModel {
     boolean isRealmAdmin(UserModel agent);
 
     void addRealmAdmin(UserModel agent);
+
+    RoleModel getRoleById(String id);
 }
diff --git a/services/src/main/java/org/keycloak/services/models/RoleModel.java b/services/src/main/java/org/keycloak/services/models/RoleModel.java
index 674dc62..9ec6ab4 100755
--- a/services/src/main/java/org/keycloak/services/models/RoleModel.java
+++ b/services/src/main/java/org/keycloak/services/models/RoleModel.java
@@ -10,4 +10,8 @@ public interface RoleModel {
     String getDescription();
 
     void setDescription(String description);
+
+    String getId();
+
+    void setName(String name);
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index e30c052..255d59a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -2,8 +2,11 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.models.RoleModel;
 import org.keycloak.services.models.UserModel;
 import org.keycloak.services.resources.PublicRealmResource;
 import org.keycloak.services.resources.Transaction;
@@ -11,9 +14,11 @@ import org.keycloak.services.resources.Transaction;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.ForbiddenException;
 import javax.ws.rs.GET;
+import javax.ws.rs.InternalServerErrorException;
 import javax.ws.rs.NotAuthorizedException;
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -23,6 +28,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -44,19 +50,108 @@ public class RealmAdminResource {
     @GET
     @Produces("application/json")
     public RealmRepresentation getRealm() {
-        RealmRepresentation rep = new RealmRepresentation();
-        rep.setId(realm.getId());
-        rep.setRealm(realm.getName());
-        rep.setEnabled(realm.isEnabled());
-        rep.setSslNotRequired(realm.isSslNotRequired());
-        rep.setCookieLoginAllowed(realm.isCookieLoginAllowed());
-        rep.setPublicKey(realm.getPublicKeyPem());
-        rep.setTokenLifespan(realm.getTokenLifespan());
-        rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
-        return rep;
+        return new Transaction() {
+            @Override
+            protected RealmRepresentation callImpl() {
+                RealmRepresentation rep = new RealmRepresentation();
+                rep.setId(realm.getId());
+                rep.setRealm(realm.getName());
+                rep.setEnabled(realm.isEnabled());
+                rep.setSslNotRequired(realm.isSslNotRequired());
+                rep.setCookieLoginAllowed(realm.isCookieLoginAllowed());
+                rep.setPublicKey(realm.getPublicKeyPem());
+                rep.setTokenLifespan(realm.getTokenLifespan());
+                rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
+                return rep;
+            }
+        }.call();
 
     }
 
+    @Path("roles")
+    @GET
+    @Produces("application/json")
+    public List<RoleRepresentation> getRoles() {
+        return new Transaction() {
+            @Override
+            protected List<RoleRepresentation> callImpl() {
+                List<RoleModel> roleModels = realm.getRoles();
+                List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
+                for (RoleModel roleModel : roleModels) {
+                    RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
+                    roles.add(role);
+                }
+                return roles;
+            }
+        }.call();
+    }
+
+    @Path("roles/{id}")
+    @GET
+    @Produces("application/json")
+    public RoleRepresentation getRole(final @PathParam("id") String id) {
+        return new Transaction() {
+            @Override
+            protected RoleRepresentation callImpl() {
+                RoleModel roleModel = realm.getRoleById(id);
+                if (roleModel == null) {
+                    throw new NotFoundException();
+                }
+                RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
+                rep.setId(roleModel.getId());
+                return rep;
+            }
+        }.call();
+    }
+
+
+    @Path("roles/{id}")
+    @PUT
+    @Consumes("application/json")
+    public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
+        new Transaction() {
+            @Override
+            protected void runImpl() {
+                RoleModel role = realm.getRoleById(id);
+                if (role == null) {
+                   throw new NotFoundException();
+                }
+                role.setName(rep.getName());
+                role.setDescription(rep.getDescription());
+            }
+        }.run();
+
+    }
+
+    @Path("roles")
+    @POST
+    @Consumes("application/json")
+    public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
+        return new Transaction() {
+            @Override
+            protected Response callImpl() {
+                if (realm.getRole(rep.getName()) != null) {
+                   throw new InternalServerErrorException(); // todo appropriate status here.
+                }
+                RoleModel role = realm.addRole(rep.getName());
+                if (role == null) {
+                    throw new NotFoundException();
+                }
+                role.setDescription(rep.getDescription());
+                return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
+            }
+        }.call();
+
+    }
+
+
+    @Path("users")
+    @GET
+    @Produces("application/json")
+    public List<UserRepresentation> getUsers() {
+        return null;
+    }
+
 
 
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index fd6f1f5..7980877 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -18,7 +18,9 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -41,18 +43,25 @@ public class RealmsAdminResource {
         this.admin = admin;
     }
 
+    public static final CacheControl noCache = new CacheControl();
+    static {
+        noCache.setNoCache(true);
+    }
+
     @GET
     @Produces("application/json")
-    public Map<String, String> getRealms() {
+    public Response getRealms() {
         return new Transaction() {
             @Override
-            protected  Map<String, String> callImpl() {
+            protected  Response callImpl() {
+                logger.info(("getRealms()"));
                 List<RealmModel> realms = session.getRealms(admin);
                 Map<String, String> map = new HashMap<String, String>();
                 for (RealmModel realm : realms) {
                     map.put(realm.getId(), realm.getName());
                 }
-                return map;
+                return Response.ok(new GenericEntity<Map<String, String>>(map){})
+                               .cacheControl(noCache).build();
             }
         }.call();
     }
diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java
index 5d1be91..68c7be8 100755
--- a/services/src/test/java/org/keycloak/test/AdapterTest.java
+++ b/services/src/test/java/org/keycloak/test/AdapterTest.java
@@ -123,6 +123,10 @@ public class AdapterTest {
         RoleModel role = realmModel.getRole("user");
         realmModel.grantRole(user, role);
         Assert.assertTrue(realmModel.hasRole(user, role));
+        System.out.println("Role id: " + role.getId());
+        role = realmModel.getRoleById(role.getId());
+        Assert.assertNotNull(role);
+        Assert.assertEquals("user", role.getName());
     }