keycloak-aplcache

Merge pull request #1818 from patriot1burke/master group

11/13/2015 11:49:23 AM

Details

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 c148a02..fe74ff2 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 7e82f32..4e3b986 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 c2d8c32..065f831 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 0000000..6c20930
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/group-members.html
@@ -0,0 +1,50 @@
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/groups">Groups</a></li>
+        <li>{{group.name}}</li>
+    </ol>
+    <kc-tabs-group></kc-tabs-group>
+
+    <table class="table table-striped table-bordered">
+        <caption data-ng-show="users" class="hidden">Table of group members</caption>
+        <thead>
+         <tr>
+        <tr data-ng-show="searchLoaded && users.length > 0">
+            <th>Username</th>
+            <th>Last Name</th>
+            <th>First Name</th>
+            <th>Email</th>
+            <th>Actions</th>
+        </tr>
+        </tr>
+        </thead>
+        <tfoot data-ng-show="users && (users.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="users.length < query.max">Next page</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
+        <tbody>
+        <tr ng-repeat="user in users">
+            <td><a href="#/realms/{{realm.realm}}/users/{{user.id}}">{{user.username}}</a></td>
+            <td>{{user.lastName}}</td>
+            <td>{{user.firstName}}</td>
+            <td>{{user.email}}</td>
+            <td class="kc-action-cell">
+                <button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/users/{{user.id}}">Edit</button>
+            </td>
+        </tr>
+        <tr data-ng-show="!users || users.length == 0">
+            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch != null">No group members</td>
+            <td class="text-muted" data-ng-show="searchLoaded && users.length == 0 && lastSearch == null">No group members</td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+<kc-menu></kc-menu>
\ 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 6c973e1..87253c1 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<UserRepresentation> 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<UserRepresentation> results = new ArrayList<UserRepresentation>();
+        List<UserModel> userModels = session.users().getGroupMembers(realm, group, firstResult, maxResults);
+
+        for (UserModel user : userModels) {
+            results.add(ModelToRepresentation.toRepresentation(user));
+        }
+        return results;
+    }
+
+
 
 
 }