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 »</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());
}