All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.restapi.account.QueryAccounts Maven / Gradle / Ivy

There is a newer version: 3.10.0
Show newest version
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.restapi.account;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.client.ListAccountsOption;
import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.AccountVisibility;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
import com.google.gerrit.server.account.AccountInfoComparator;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.account.AccountPredicates;
import com.google.gerrit.server.query.account.AccountQueryBuilder;
import com.google.gerrit.server.query.account.AccountQueryProcessor;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;

/**
 * REST endpoint to query accounts.
 *
 * 

This REST endpoint handles {@code GET /accounts/} requests. * *

The account queries are parsed by {@link AccountQueryBuilder} and executed by {@link * AccountQueryProcessor}. */ public class QueryAccounts implements RestReadView { private static final int MAX_SUGGEST_RESULTS = 100; private final PermissionBackend permissionBackend; private final AccountLoader.Factory accountLoaderFactory; private final AccountQueryBuilder queryBuilder; private final Provider queryProcessorProvider; private final boolean suggestConfig; private final int suggestFrom; private AccountLoader accountLoader; private boolean suggest; private Integer limit; private int suggestLimit = 10; private String query; private Integer start; private EnumSet options; @Option(name = "--suggest", metaVar = "SUGGEST", usage = "suggest users") public void setSuggest(boolean suggest) { this.suggest = suggest; } @Option( name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "maximum number of users to return") public void setLimit(int n) { this.limit = n; if (n < 0) { suggestLimit = 10; } else if (n == 0) { suggestLimit = MAX_SUGGEST_RESULTS; } else { suggestLimit = Math.min(n, MAX_SUGGEST_RESULTS); } } @Option(name = "-o", usage = "Output options per account") public void addOption(ListAccountsOption o) { options.add(o); } @Option(name = "-O", usage = "Output option flags, in hex") void setOptionFlagsHex(String hex) { options.addAll(ListOption.fromBits(ListAccountsOption.class, Integer.parseInt(hex, 16))); } @Option( name = "--query", aliases = {"-q"}, metaVar = "QUERY", usage = "match users") public void setQuery(String query) { this.query = query; } @Option( name = "--start", aliases = {"-S"}, metaVar = "CNT", usage = "Number of accounts to skip") public void setStart(int start) { this.start = start; } @Inject QueryAccounts( PermissionBackend permissionBackend, AccountLoader.Factory accountLoaderFactory, AccountQueryBuilder queryBuilder, Provider queryProcessorProvider, @GerritServerConfig Config cfg) { this.permissionBackend = permissionBackend; this.accountLoaderFactory = accountLoaderFactory; this.queryBuilder = queryBuilder; this.queryProcessorProvider = queryProcessorProvider; this.suggestFrom = cfg.getInt("suggest", null, "from", 0); this.options = EnumSet.noneOf(ListAccountsOption.class); if ("off".equalsIgnoreCase(cfg.getString("suggest", null, "accounts"))) { suggestConfig = false; } else { boolean suggest; try { AccountVisibility av = cfg.getEnum("suggest", null, "accounts", AccountVisibility.ALL); suggest = (av != AccountVisibility.NONE); } catch (IllegalArgumentException err) { suggest = cfg.getBoolean("suggest", null, "accounts", true); } this.suggestConfig = suggest; } } @Override public Response> apply(TopLevelResource rsrc) throws RestApiException, PermissionBackendException { if (Strings.isNullOrEmpty(query)) { throw new BadRequestException("missing query field"); } if (suggest && (!suggestConfig || query.length() < suggestFrom)) { return Response.ok(Collections.emptyList()); } Set fillOptions = EnumSet.of(FillOptions.ID); if (options.contains(ListAccountsOption.DETAILS)) { fillOptions.addAll(AccountLoader.DETAILED_OPTIONS); } boolean modifyAccountCapabilityChecked = false; if (options.contains(ListAccountsOption.ALL_EMAILS)) { permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT); modifyAccountCapabilityChecked = true; fillOptions.add(FillOptions.EMAIL); fillOptions.add(FillOptions.SECONDARY_EMAILS); } if (suggest) { fillOptions.addAll(AccountLoader.DETAILED_OPTIONS); fillOptions.add(FillOptions.EMAIL); if (modifyAccountCapabilityChecked) { fillOptions.add(FillOptions.SECONDARY_EMAILS); } else { try { permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT); fillOptions.add(FillOptions.SECONDARY_EMAILS); } catch (AuthException e) { // Do nothing. } } } accountLoader = accountLoaderFactory.create(fillOptions); AccountQueryProcessor queryProcessor = queryProcessorProvider.get(); if (queryProcessor.isDisabled()) { throw new MethodNotAllowedException("query disabled"); } if (limit != null) { queryProcessor.setUserProvidedLimit(limit); } if (start != null) { queryProcessor.setStart(start); } Map matches = new LinkedHashMap<>(); try { Predicate queryPred; if (suggest) { queryPred = queryBuilder.defaultQuery(query); queryProcessor.setUserProvidedLimit(suggestLimit); } else { queryPred = queryBuilder.parse(query); } if (!AccountPredicates.hasActive(queryPred)) { // if neither 'is:active' nor 'is:inactive' appears in the query only // active accounts should be queried queryPred = AccountPredicates.andActive(queryPred); } QueryResult result = queryProcessor.query(queryPred); for (AccountState accountState : result.entities()) { Account.Id id = accountState.account().id(); matches.put(id, accountLoader.get(id)); } accountLoader.fill(); List sorted = AccountInfoComparator.ORDER_NULLS_LAST.sortedCopy(matches.values()); if (!sorted.isEmpty() && result.more()) { sorted.get(sorted.size() - 1)._moreAccounts = true; } return Response.ok(sorted); } catch (QueryParseException e) { if (suggest) { return Response.ok(ImmutableList.of()); } throw new BadRequestException(e.getMessage()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy