Skip to content

Commit

Permalink
Refactor PaginatedUserService to use new MongoDB API (#21009)
Browse files Browse the repository at this point in the history
  • Loading branch information
thll authored Nov 21, 2024
1 parent 74e0fe9 commit 0af1c03
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.graylog2.plugin.rest.ValidationResult;
import org.graylog2.rest.PaginationParameters;
import org.graylog2.rest.models.PaginatedResponse;
import org.graylog2.rest.models.SortOrder;
import org.graylog2.search.SearchQuery;
import org.graylog2.search.SearchQueryField;
import org.graylog2.search.SearchQueryParser;
Expand Down Expand Up @@ -195,7 +196,7 @@ public PaginatedResponse<UserOverviewDTO> getUsers(
@ApiParam(name = "sort", value = "The field to sort the result on", required = true, allowableValues = "username,full_name,email")
@DefaultValue(UserOverviewDTO.FIELD_FULL_NAME) @QueryParam("sort") String sort,
@ApiParam(name = "order", value = "The sort direction", allowableValues = "asc, desc")
@DefaultValue("asc") @QueryParam("order") String order,
@DefaultValue("asc") @QueryParam("order") SortOrder order,
@ApiParam(name = "backendId", required = true) @PathParam("backendId") @NotBlank String backendId
) {
final AuthServiceBackendDTO activeConfig = loadConfig(backendId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.graylog2.plugin.database.ValidationException;
import org.graylog2.plugin.database.users.User;
import org.graylog2.rest.models.PaginatedResponse;
import org.graylog2.rest.models.SortOrder;
import org.graylog2.search.SearchQuery;
import org.graylog2.search.SearchQueryField;
import org.graylog2.search.SearchQueryParser;
Expand Down Expand Up @@ -151,7 +152,7 @@ public PaginatedResponse<UserOverviewDTO> getUsersForRole(
allowableValues = "username,full_name,email")
@DefaultValue(AuthzRoleDTO.FIELD_NAME) @QueryParam("sort") String sort,
@ApiParam(name = "order", value = "The sort direction", allowableValues = "asc, desc")
@DefaultValue("asc") @QueryParam("order") String order) {
@DefaultValue("asc") @QueryParam("order") SortOrder order) {

SearchQuery searchQuery;
try {
Expand Down Expand Up @@ -283,7 +284,7 @@ public void delete(@ApiParam(name = "roleId") @PathParam("roleId") @NotBlank Str

private Map<String, Set<Map<String, String>>> userRoleContext(PaginatedList<AuthzRoleDTO> roles) {
final PaginatedList<UserOverviewDTO> users = paginatedUserService.findPaginatedByRole(new SearchQuery(""),
1, 0, UserOverviewDTO.FIELD_USERNAME, "asc",
1, 0, UserOverviewDTO.FIELD_USERNAME, SortOrder.ASCENDING,
roles.stream().map(AuthzRoleDTO::id).collect(Collectors.toSet()));
final Map<String, Set<Map<String, String>>> userRoleMap = new HashMap<>(roles.size());
roles.forEach(authzRoleDTO -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.graylog2.plugin.database.ValidationException;
import org.graylog2.plugin.database.users.User;
import org.graylog2.rest.models.PaginatedResponse;
import org.graylog2.rest.models.SortOrder;
import org.graylog2.rest.models.users.requests.ChangePasswordRequest;
import org.graylog2.rest.models.users.requests.CreateUserRequest;
import org.graylog2.rest.models.users.requests.PermissionEditRequest;
Expand Down Expand Up @@ -279,7 +280,7 @@ public PaginatedResponse<UserOverviewDTO> getPage(@ApiParam(name = "page") @Quer
allowableValues = "title,description")
@DefaultValue(UserOverviewDTO.FIELD_FULL_NAME) @QueryParam("sort") String sort,
@ApiParam(name = "order", value = "The sort direction", allowableValues = "asc, desc")
@DefaultValue("asc") @QueryParam("order") String order) {
@DefaultValue("asc") @QueryParam("order") SortOrder order) {

SearchQuery searchQuery;
final AllUserSessions sessions = AllUserSessions.create(sessionService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,72 +16,92 @@
*/
package org.graylog2.users;

import com.mongodb.client.MongoCollection;
import jakarta.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.graylog2.bindings.providers.MongoJackObjectMapperProvider;
import org.graylog2.database.MongoConnection;
import org.graylog2.database.PaginatedDbService;
import org.bson.types.ObjectId;
import org.graylog2.database.MongoCollections;
import org.graylog2.database.PaginatedList;
import org.graylog2.database.pagination.MongoPaginationHelper;
import org.graylog2.database.utils.MongoUtils;
import org.graylog2.rest.models.SortOrder;
import org.graylog2.search.SearchQuery;
import org.mongojack.DBQuery;
import org.mongojack.DBSort;

import jakarta.inject.Inject;

import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkArgument;
import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Filters.in;
import static org.graylog2.database.utils.MongoUtils.stringIdsIn;

public class PaginatedUserService extends PaginatedDbService<UserOverviewDTO> {
public class PaginatedUserService {
private static final String COLLECTION_NAME = "users";
private final MongoCollection<UserOverviewDTO> collection;
private final MongoPaginationHelper<UserOverviewDTO> paginationHelper;

@Inject
public PaginatedUserService(MongoConnection mongoConnection,
MongoJackObjectMapperProvider mapper) {
super(mongoConnection, mapper, UserOverviewDTO.class, COLLECTION_NAME);
public PaginatedUserService(MongoCollections mongoCollections) {
collection = mongoCollections.collection(COLLECTION_NAME, UserOverviewDTO.class);
paginationHelper = mongoCollections.paginationHelper(collection);
}

public long count() {
return db.count();
return collection.countDocuments();
}

public PaginatedList<UserOverviewDTO> findPaginated(SearchQuery searchQuery, int page,
int perPage, String sortField, String order) {
final DBQuery.Query dbQuery = searchQuery.toDBQuery();
final DBSort.SortBuilder sortBuilder = getSortBuilder(order, sortField);
return findPaginatedWithQueryAndSort(dbQuery, sortBuilder, page, perPage);
int perPage, String sortField, SortOrder order) {

return paginationHelper
.filter(searchQuery.toBson())
.sort(order.toBsonSort(sortField))
.perPage(perPage)
.page(page);
}

public PaginatedList<UserOverviewDTO> findPaginatedByUserId(SearchQuery searchQuery, int page,
int perPage, String sortField, String order,
int perPage, String sortField, SortOrder order,
Set<String> userIds) {
final DBQuery.Query dbQuery = searchQuery.toDBQuery()
.in("_id", userIds);
final DBSort.SortBuilder sortBuilder = getSortBuilder(order, sortField);
return findPaginatedWithQueryAndSort(dbQuery, sortBuilder, page, perPage);

return paginationHelper
.filter(and(searchQuery.toBson(), stringIdsIn(userIds)))
.sort(order.toBsonSort(sortField))
.perPage(perPage)
.page(page);
}

public PaginatedList<UserOverviewDTO> findPaginatedByRole(SearchQuery searchQuery, int page,
int perPage, String sortField, String order,
int perPage, String sortField, SortOrder order,
Set<String> roleIds) {
final DBQuery.Query dbQuery = searchQuery.toDBQuery()
.in(UserImpl.ROLES, roleIds);
final DBSort.SortBuilder sortBuilder = getSortBuilder(order, sortField);
return findPaginatedWithQueryAndSort(dbQuery, sortBuilder, page, perPage);

final var roleObjectIds = roleIds.stream().map(ObjectId::new).collect(Collectors.toSet());

return paginationHelper
.filter(and(searchQuery.toBson(), in(UserImpl.ROLES, roleObjectIds)))
.sort(order.toBsonSort(sortField))
.perPage(perPage)
.page(page);
}

public PaginatedList<UserOverviewDTO> findPaginatedByAuthServiceBackend(SearchQuery searchQuery,
int page,
int perPage,
String sortField,
String order,
SortOrder order,
String authServiceBackendId) {
checkArgument(!StringUtils.isBlank(authServiceBackendId), "authServiceBackendId cannot be blank");

final DBQuery.Query query = DBQuery.and(
DBQuery.is(UserImpl.AUTH_SERVICE_ID, Optional.of(authServiceBackendId)),
searchQuery.toDBQuery()
);
return findPaginatedWithQueryAndSort(query, getSortBuilder(order, sortField), page, perPage);
return paginationHelper
.filter(and(eq(UserImpl.AUTH_SERVICE_ID, authServiceBackendId), searchQuery.toBson()))
.sort(order.toBsonSort(sortField))
.perPage(perPage)
.page(page);
}

public Stream<UserOverviewDTO> streamAll() {
return MongoUtils.stream(collection.find());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.auto.value.AutoValue;
import org.graylog2.database.MongoEntity;
import org.graylog2.plugin.database.users.User;
import org.graylog2.security.MongoDbSession;
import org.mongojack.Id;
Expand All @@ -35,7 +36,7 @@

@AutoValue
@JsonDeserialize(builder = UserOverviewDTO.Builder.class)
public abstract class UserOverviewDTO {
public abstract class UserOverviewDTO implements MongoEntity {

public static final String FIELD_ID = "id";
private static final String FIELD_AUTH_SERVICE_ID = "auth_service_id";
Expand Down

0 comments on commit 0af1c03

Please sign in to comment.