blob: 0d00272bd2d3a6ce7d9e3b7173e340a7784e5eb3 [file] [log] [blame]
// Copyright (C) 2018 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.googlesource.gerrit.plugins.reviewers;
import static java.util.stream.Collectors.toSet;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.GroupMembers;
import com.google.gerrit.server.group.GroupResolver;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
/* Resolve account and group names to account ids */
@Singleton
class ReviewersResolver {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final AccountResolver accountResolver;
private final Provider<GroupResolver> groupResolver;
private final GroupMembers groupMembers;
@Inject
ReviewersResolver(
AccountResolver accountResolver,
Provider<GroupResolver> groupResolver,
GroupMembers groupMembers) {
this.accountResolver = accountResolver;
this.groupResolver = groupResolver;
this.groupMembers = groupMembers;
}
/**
* Resolve a set of account names to {@link com.google.gerrit.entities.Account.Id}s. Group names
* are resolved to their account members.
*
* @param names the set of account names to convert
* @param project the project name
* @param changeNumber the change Id
* @param uploader account to use to look up groups, or null if groups are not needed
* @return set of {@link com.google.gerrit.entities.Account.Id}s.
*/
@VisibleForTesting
Set<Account.Id> resolve(
Set<String> names,
Project.NameKey project,
int changeNumber,
@Nullable AccountInfo uploader) {
Set<Account.Id> reviewers = Sets.newHashSetWithExpectedSize(names.size());
for (String name : names) {
if (resolveAccount(project, changeNumber, uploader, reviewers, name)) {
continue;
}
resolveGroup(project, changeNumber, reviewers, groupMembers, name);
}
return reviewers;
}
private boolean resolveAccount(
Project.NameKey project,
int changeNumber,
@Nullable AccountInfo uploader,
Set<Account.Id> reviewers,
String accountName) {
try {
AccountResolver.Result result = accountResolver.resolve(accountName);
if (result.asList().size() == 1) {
Account.Id id = result.asList().get(0).account().id();
if (uploader == null || id.get() != uploader._accountId) {
reviewers.add(id);
return true;
}
}
return false;
} catch (StorageException | IOException | ConfigInvalidException e) {
logger.atSevere().withCause(e).log(
"For the change %d of project %s: failed to resolve account %s.",
changeNumber, project, accountName);
return true;
}
}
private void resolveGroup(
Project.NameKey project,
int changeNumber,
Set<Account.Id> reviewers,
GroupMembers groupMembers,
String group) {
try {
Set<Account.Id> accounts =
groupMembers.listAccounts(groupResolver.get().parse(group).getGroupUUID(), project)
.stream()
.filter(Account::isActive)
.map(Account::id)
.collect(toSet());
reviewers.addAll(accounts);
} catch (UnprocessableEntityException e) {
logger.atWarning().log(
"For the change %d of project %s: reviewer %s is neither an account nor a group.",
changeNumber, project, group);
} catch (NoSuchProjectException | IOException e) {
logger.atSevere().withCause(e).log(
"For the change %d of project %s: failed to list accounts for group %s.",
changeNumber, project, group);
}
}
}