blob: 284134995a05e315f9a274e0029a441549c6417e [file] [log] [blame]
// Copyright (C) 2019 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.plugins.checks.api;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.plugins.checks.AdministrateCheckersPermission;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerJson;
import com.google.gerrit.plugins.checks.CheckerName;
import com.google.gerrit.plugins.checks.CheckerQuery;
import com.google.gerrit.plugins.checks.CheckerUpdate;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.CheckersUpdate;
import com.google.gerrit.plugins.checks.NoSuchCheckerException;
import com.google.gerrit.plugins.checks.UrlValidator;
import com.google.gerrit.server.UserInitiated;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import javax.inject.Singleton;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class UpdateChecker implements RestModifyView<CheckerResource, CheckerInput> {
private final CheckerJson checkerJson;
private final PermissionBackend permissionBackend;
private final ProjectCache projectCache;
private final Provider<CheckerQuery> checkerQueryProvider;
private final Provider<CheckersUpdate> checkersUpdate;
private final AdministrateCheckersPermission permission;
@Inject
public UpdateChecker(
CheckerJson checkerJson,
ProjectCache projectCache,
PermissionBackend permissionBackend,
Provider<CheckerQuery> checkerQueryProvider,
@UserInitiated Provider<CheckersUpdate> checkersUpdate,
AdministrateCheckersPermission permission) {
this.checkerJson = checkerJson;
this.projectCache = projectCache;
this.permissionBackend = permissionBackend;
this.checkerQueryProvider = checkerQueryProvider;
this.checkersUpdate = checkersUpdate;
this.permission = permission;
}
@Override
public Response<CheckerInfo> apply(CheckerResource resource, CheckerInput input)
throws RestApiException, PermissionBackendException, NoSuchCheckerException, IOException,
ConfigInvalidException, StorageException {
permissionBackend.currentUser().check(permission);
CheckerUuid checkerUuid = resource.getChecker().getUuid();
CheckerUpdate.Builder checkerUpdateBuilder = CheckerUpdate.builder();
// Callers shouldn't really be providing UUID. If they do, the only legal UUID is exactly the
// current UUID.
if (input.uuid != null && !input.uuid.equals(checkerUuid.get())) {
throw new BadRequestException("uuid cannot be updated");
}
if (input.name != null) {
String newName = CheckerName.clean(input.name);
if (newName.isEmpty()) {
throw new BadRequestException("name cannot be unset");
}
checkerUpdateBuilder.setName(newName);
}
if (input.description != null) {
checkerUpdateBuilder.setDescription(input.description.trim());
}
if (input.url != null) {
checkerUpdateBuilder.setUrl(UrlValidator.clean(input.url));
}
Project.NameKey repository;
if (input.repository != null) {
repository = resolveRepository(input.repository);
checkerUpdateBuilder.setRepository(repository);
} else {
repository = resource.getChecker().getRepository();
}
if (input.status != null) {
checkerUpdateBuilder.setStatus(input.status);
}
if (input.blocking != null) {
checkerUpdateBuilder.setBlockingConditions(ImmutableSortedSet.copyOf(input.blocking));
}
if (input.query != null) {
checkerUpdateBuilder.setQuery(validateQuery(checkerUuid, repository, input.query));
}
Checker updatedChecker =
checkersUpdate.get().updateChecker(checkerUuid, checkerUpdateBuilder.build());
return Response.ok(checkerJson.format(updatedChecker));
}
private Project.NameKey resolveRepository(String repository)
throws BadRequestException, UnprocessableEntityException {
if (repository == null || repository.trim().isEmpty()) {
throw new BadRequestException("repository cannot be unset");
}
ProjectState projectState =
projectCache
.get(Project.nameKey(repository.trim()))
.orElseThrow(
() ->
new UnprocessableEntityException(
String.format("repository %s not found", repository)));
return projectState.getNameKey();
}
private String validateQuery(CheckerUuid checkerUuid, Project.NameKey repository, String query)
throws BadRequestException, StorageException {
try {
return checkerQueryProvider.get().validate(checkerUuid, repository, query);
} catch (ConfigInvalidException e) {
throw new BadRequestException(e.getMessage(), e);
}
}
}