diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js index c148a02cdf..fe74ff27a0 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js @@ -643,9 +643,21 @@ module.config([ '$routeProvider', function($routeProvider) { group : function(GroupLoader) { return GroupLoader(); } - }, + }, controller : 'GroupDetailCtrl' }) + .when('/realms/:realm/groups/:group/members', { + templateUrl : resourceUrl + '/partials/group-members.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + }, + group : function(GroupLoader) { + return GroupLoader(); + } + }, + controller : 'GroupMembersCtrl' + }) .when('/realms/:realm/groups/:group/role-mappings', { templateUrl : resourceUrl + '/partials/group-role-mappings.html', resolve : { diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js index 7e82f32b36..4e3b98634c 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js @@ -319,3 +319,50 @@ module.controller('GroupRoleMappingCtrl', function($scope, $http, realm, group, }); + +module.controller('GroupMembersCtrl', function($scope, realm, group, GroupMembership) { + $scope.realm = realm; + $scope.page = 0; + + + $scope.query = { + realm: realm.realm, + groupId: group.id, + max : 5, + first : 0 + } + + + $scope.firstPage = function() { + $scope.query.first = 0; + $scope.searchQuery(); + } + + $scope.previousPage = function() { + $scope.query.first -= parseInt($scope.query.max); + if ($scope.query.first < 0) { + $scope.query.first = 0; + } + $scope.searchQuery(); + } + + $scope.nextPage = function() { + $scope.query.first += parseInt($scope.query.max); + $scope.searchQuery(); + } + + $scope.searchQuery = function() { + console.log("query.search: " + $scope.query.search); + $scope.searchLoaded = false; + + $scope.users = GroupMembership.query($scope.query, function() { + console.log('search loaded'); + $scope.searchLoaded = true; + $scope.lastSearch = $scope.query.search; + }); + }; + + $scope.searchQuery(); + +}); + diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js index c2d8c32b0b..065f831877 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js @@ -1512,6 +1512,14 @@ module.factory('GroupCompositeClientRoleMapping', function($resource) { }); }); +module.factory('GroupMembership', function($resource) { + return $resource(authUrl + '/admin/realms/:realm/groups/:groupId/members', { + realm : '@realm', + groupId : '@groupId' + }); +}); + + module.factory('UserGroupMembership', function($resource) { return $resource(authUrl + '/admin/realms/:realm/users/:userId/groups', { realm : '@realm', diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/group-members.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/group-members.html new file mode 100755 index 0000000000..6c20930275 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/group-members.html @@ -0,0 +1,50 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UsernameLast NameFirst NameEmailActions
+
+ + + +
+
{{user.username}}{{user.lastName}}{{user.firstName}}{{user.email}} + +
No group membersNo group members
+
+ + \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java index 6c973e10c7..87253c103f 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java @@ -10,6 +10,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.representations.idm.GroupRepresentation; +import org.keycloak.representations.idm.UserRepresentation; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -19,12 +20,15 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; 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.net.URI; +import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -256,6 +260,42 @@ public class GroupResource { } + /** + * Get users + * + * Returns a list of users, filtered according to query parameters + * + * @param firstResult Pagination offset + * @param maxResults Pagination size + * @return + */ + @GET + @NoCache + @Path("{id}/members") + @Produces(MediaType.APPLICATION_JSON) + public List getMembers(@PathParam("id") String id, + @QueryParam("first") Integer firstResult, + @QueryParam("max") Integer maxResults) { + auth.requireView(); + + GroupModel group = session.realms().getGroupById(id, realm); + if (group == null) { + throw new NotFoundException("Group not found"); + } + + firstResult = firstResult != null ? firstResult : -1; + maxResults = maxResults != null ? maxResults : -1; + + List results = new ArrayList(); + List userModels = session.users().getGroupMembers(realm, group, firstResult, maxResults); + + for (UserModel user : userModels) { + results.add(ModelToRepresentation.toRepresentation(user)); + } + return results; + } + + }