group membership ui
This commit is contained in:
parent
0d20e3c7ff
commit
d7ea66ad44
5 changed files with 158 additions and 1 deletions
|
@ -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 : {
|
||||
|
|
|
@ -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();
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue