Details
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index b270045..b930d43 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -24,7 +24,7 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
}
$scope.access = {
- admin: data.admin,
+ createRealm: data.createRealm,
get viewRealm() {
return getAccess('view-realm') || this.manageRealm;
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
index f42f25f..c7c1dfd 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
@@ -33,7 +33,7 @@
</li>
</ul>
</li>
- <li class="active pull-right" data-ng-show="auth.loggedIn && access.admin">
+ <li class="active pull-right" data-ng-show="auth.loggedIn && access.createRealm">
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
data-ng-show="auth.loggedIn">Add Realm</a>
</li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-list.html
index 9690462..2777613 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-list.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-list.html
@@ -1,34 +1,25 @@
-<div id="wrapper" class="container">
- <div class="row">
- <div class="bs-sidebar col-md-3 clearfix">
- <ul data-ng-hide="createRealm">
- <li class="active"><a href="#/realms">Realms</a></li>
- </ul>
- </div>
- <div id="content-area" class="col-md-9" role="main">
- <div class="top-nav" data-ng-hide="createRealm">
- <ul class="rcue-tabs">
-
- </ul>
- </div>
- <div id="content">
-
- <h1>
- <span class="gray">Realms</span>
- </h1>
-
- <table class="table table-striped table-bordered">
- <thead>
- <tr>
- <th>Realm</th>
- </tr>
- </thead>
- <tr data-ng-repeat="r in realms">
- <td><a href="#/realms/{{r.realm}}">{{r.realm}}</a></td>
- </tr>
- </table>
- </div>
- </div>
- <div id="container-right-bg"></div>
+<div class="bs-sidebar col-sm-3 ">
+ <ul data-ng-hide="createRealm">
+ <li class="active"><a href="#/realms">Realms</a></li>
+ </ul>
+</div>
+<div id="content-area" class="col-md-9" role="main">
+ <ul class="nav nav-tabs nav-tabs-pf">
+ <li class="active"><a href="">Realm List</a></li>
+ </ul>
+ <div id="content">
+ <h2><span>Realms</span></h2>
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Realm</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr data-ng-repeat="r in realms">
+ <td><a href="#/realms/{{r.realm}}">{{r.realm}}</a></td>
+ </tr>
+ </tbody>
+ </table>
</div>
</div>
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
index a156be7..e1216cf 100644
--- a/model/api/src/main/java/org/keycloak/models/AdminRoles.java
+++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
@@ -9,6 +9,8 @@ public class AdminRoles {
public static String ADMIN = "admin";
+ public static String CREATE_REALM = "create-realm";
+
public static String VIEW_REALM = "view-realm";
public static String VIEW_USERS = "view-users";
public static String VIEW_APPLICATIONS = "view-applications";
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 1fa6e10..18f2901 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -162,6 +162,9 @@ public class RealmManager {
adminRealm = realm;
adminRole = realm.addRole(AdminRoles.ADMIN);
+
+ RoleModel createRealmRole = realm.addRole(AdminRoles.CREATE_REALM);
+ adminRole.addCompositeRole(createRealmRole);
} else {
adminRealm = identitySession.getRealmByName(Constants.ADMIN_REALM);
adminRole = adminRealm.getRole(AdminRoles.ADMIN);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 7c1e3f5..233c5ab 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -79,18 +79,18 @@ public class AdminService {
protected String userId;
protected String displayName;
- @JsonProperty("admin")
- protected boolean admin;
+ @JsonProperty("createRealm")
+ protected boolean createRealm;
@JsonProperty("realm_access")
protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
public WhoAmI() {
}
- public WhoAmI(String userId, String displayName, boolean admin, Map<String, Set<String>> realmAccess) {
+ public WhoAmI(String userId, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
this.userId = userId;
this.displayName = displayName;
- this.admin = admin;
+ this.createRealm = createRealm;
this.realmAccess = realmAccess;
}
@@ -110,12 +110,12 @@ public class AdminService {
this.displayName = displayName;
}
- public boolean isAdmin() {
- return admin;
+ public boolean isCreateRealm() {
+ return createRealm;
}
- public void setAdmin(boolean admin) {
- this.admin = admin;
+ public void setCreateRealm(boolean createRealm) {
+ this.createRealm = createRealm;
}
public Map<String, Set<String>> getRealmAccess() {
@@ -169,12 +169,12 @@ public class AdminService {
displayName = user.getLoginName();
}
- boolean admin = realm.hasRole(user, realm.getRole("admin"));
+ boolean createRealm = realm.hasRole(user, realm.getRole(AdminRoles.CREATE_REALM));
Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
addRealmAdminAccess(realmAccess, auth.getRealm().getRoleMappings(auth.getUser()));
- return Response.ok(new WhoAmI(user.getId(), displayName, admin, realmAccess)).build();
+ return Response.ok(new WhoAmI(user.getId(), displayName, createRealm, realmAccess)).build();
}
private void addRealmAdminAccess(Map<String, Set<String>> realmAdminAccess, Set<RoleModel> roles) {
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 b21cbb4..49d5198 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
@@ -6,8 +6,10 @@ import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.jboss.resteasy.util.GenericType;
import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.ModelToRepresentation;
@@ -87,7 +89,7 @@ public class RealmsAdminResource {
@POST
@Consumes("application/json")
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
- if (!auth.hasRealmRole(AdminRoles.ADMIN)) {
+ if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
throw new ForbiddenException();
}
@@ -98,6 +100,8 @@ public class RealmsAdminResource {
}
RealmModel realm = realmManager.importRealm(rep);
+ grantPermissionsToRealmCreator(realm);
+
URI location = realmUrl(uriInfo).build(realm.getName());
logger.debug("imported realm success, sending back: {0}", location.toString());
return Response.created(location).build();
@@ -106,7 +110,7 @@ public class RealmsAdminResource {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadRealm(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
- if (!auth.hasRealmRole(AdminRoles.ADMIN)) {
+ if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
throw new ForbiddenException();
}
@@ -117,7 +121,9 @@ public class RealmsAdminResource {
for (InputPart inputPart : inputParts) {
inputPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
RealmRepresentation rep = inputPart.getBody(new GenericType<RealmRepresentation>(){});
+
RealmModel realm = realmManager.importRealm(rep);
+ grantPermissionsToRealmCreator(realm);
if (inputParts.size() == 1) {
URI location = realmUrl(uriInfo).build(realm.getName());
@@ -128,6 +134,20 @@ public class RealmsAdminResource {
return Response.noContent().build();
}
+ private void grantPermissionsToRealmCreator(RealmModel realm) {
+ if (auth.hasRealmRole(AdminRoles.ADMIN)) {
+ return;
+ }
+
+ RealmModel adminRealm = new RealmManager(session).getKeycloakAdminstrationRealm();
+ ApplicationModel realmAdminApp = adminRealm.getApplicationByName(AdminRoles.getAdminApp(realm));
+ for (String r : AdminRoles.ALL_REALM_ROLES) {
+ RoleModel role = realmAdminApp.getRole(r);
+ adminRealm.grantRole(auth.getUser(), role);
+ }
+ }
+
+
@Path("{realm}")
public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
@PathParam("realm") final String name) {