From 53c26a3b31d230a0deb1bdcce137ef9467b06de1 Mon Sep 17 00:00:00 2001 From: Gustaf Lundh Date: Tue, 20 Sep 2016 22:06:47 +0200 Subject: [PATCH] AssigneeValidationListener extension point Listener to provide extensions with validation of assignees. Change-Id: I61f6558d79b8e4c0d322c293dacdf4f33d882b26 * submodules: * Update plugins/cookbook-plugin from branch 'master' - AssigneeValidator example Will not allow a user to be assigned to more than 5 changes. Change-Id: I1887f7007e66bd5ccac207c7789be2712ffbd00a --- Documentation/config-validation.txt | 7 ++++ .../gerrit/server/change/SetAssigneeOp.java | 18 +++++++++- .../server/config/GerritGlobalModule.java | 2 ++ .../AssigneeValidationListener.java | 34 +++++++++++++++++++ plugins/cookbook-plugin | 2 +- 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/validators/AssigneeValidationListener.java diff --git a/Documentation/config-validation.txt b/Documentation/config-validation.txt index 2707e5c898..cccfe5c1c1 100644 --- a/Documentation/config-validation.txt +++ b/Documentation/config-validation.txt @@ -80,6 +80,13 @@ input arguments. E.g. a plugin could use this to enforce a certain name scheme for group names. +[[assignee-validation]] +== Assignee validation + + +Plugins implementing the `AssigneeValidationListener` interface can perform +validation of assignees before they are assigned to a change. + [[hashtag-validation]] == Hashtag validation diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetAssigneeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetAssigneeOp.java index b75463da82..df43169bfa 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetAssigneeOp.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetAssigneeOp.java @@ -16,11 +16,13 @@ package com.google.gerrit.server.change; import com.google.common.base.Optional; import com.google.gerrit.extensions.api.changes.AssigneeInput; +import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.UnprocessableEntityException; import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.ChangeMessage; import com.google.gerrit.server.ChangeMessagesUtil; import com.google.gerrit.server.ChangeUtil; @@ -31,6 +33,8 @@ import com.google.gerrit.server.config.AnonymousCowardName; import com.google.gerrit.server.git.BatchUpdate; import com.google.gerrit.server.notedb.ChangeUpdate; import com.google.gerrit.server.notedb.NotesMigration; +import com.google.gerrit.server.validators.AssigneeValidationListener; +import com.google.gerrit.server.validators.ValidationException; import com.google.gwtorm.server.OrmException; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; @@ -46,6 +50,9 @@ public class SetAssigneeOp extends BatchUpdate.Op { private final AccountInfoCacheFactory.Factory accountInfosFactory; private final NotesMigration notesMigration; private final String anonymousCowardName; + private final DynamicSet validationListeners; + + private Change change; private Account newAssignee; @AssistedInject @@ -54,13 +61,15 @@ public class SetAssigneeOp extends BatchUpdate.Op { ChangeMessagesUtil cmUtil, AccountInfoCacheFactory.Factory accountInfosFactory, @AnonymousCowardName String anonymousCowardName, - @Assisted AssigneeInput input) { + @Assisted AssigneeInput input, + DynamicSet validationListeners) { this.accounts = accounts; this.notesMigration = notesMigration; this.cmUtil = cmUtil; this.accountInfosFactory = accountInfosFactory; this.anonymousCowardName = anonymousCowardName; this.input = input; + this.validationListeners = validationListeners; } @Override @@ -101,6 +110,13 @@ public class SetAssigneeOp extends BatchUpdate.Op { ctx.getChange().getChangeId(), newAssigneeUser.getUserName())); } + try { + for (AssigneeValidationListener validator : validationListeners) { + validator.validateAssignee(change, newAssigneeUser.getAccount()); + } + } catch (ValidationException e) { + throw new BadRequestException(e.getMessage()); + } update.setAssignee(newAssigneeUser.getAccountId()); this.newAssignee = newAssigneeUser.getAccount(); addMessage(ctx, update, oldAssignee); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index c91ca3bd81..8a13eca845 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java @@ -162,6 +162,7 @@ import com.google.gerrit.server.ssh.SshAddressesModule; import com.google.gerrit.server.tools.ToolsCatalog; import com.google.gerrit.server.util.IdGenerator; import com.google.gerrit.server.util.ThreadLocalRequestContext; +import com.google.gerrit.server.validators.AssigneeValidationListener; import com.google.gerrit.server.validators.GroupCreationValidationListener; import com.google.gerrit.server.validators.HashtagValidationListener; import com.google.gerrit.server.validators.OutgoingEmailValidationListener; @@ -362,6 +363,7 @@ public class GerritGlobalModule extends FactoryModule { DynamicSet.setOf(binder(), AccountExternalIdCreator.class); DynamicSet.setOf(binder(), WebUiPlugin.class); DynamicItem.itemOf(binder(), AccountPatchReviewStore.class); + DynamicSet.setOf(binder(), AssigneeValidationListener.class); factory(UploadValidators.Factory.class); DynamicSet.setOf(binder(), UploadValidationListener.class); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/validators/AssigneeValidationListener.java b/gerrit-server/src/main/java/com/google/gerrit/server/validators/AssigneeValidationListener.java new file mode 100644 index 0000000000..5d1191cecb --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/validators/AssigneeValidationListener.java @@ -0,0 +1,34 @@ +// Copyright (C) 2016 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.validators; + +import com.google.gerrit.extensions.annotations.ExtensionPoint; +import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.Change; + +/** + * Listener to provide validation of assignees. + */ +@ExtensionPoint +public interface AssigneeValidationListener { + /** + * Invoked by Gerrit before the assignee of a change is modified. + * + * @param change the change on which the assignee is changed + * @param assignee the new assignee. Null if removed + * @throws ValidationException if validation fails + */ + void validateAssignee(Change change, Account assignee) throws ValidationException; +} diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin index 288f50d28a..2dd17f3599 160000 --- a/plugins/cookbook-plugin +++ b/plugins/cookbook-plugin @@ -1 +1 @@ -Subproject commit 288f50d28ab8b141efad4297125dcc145d62f0ec +Subproject commit 2dd17f35997e5c9bdea4d64acef6db0e42a26242