From de3bfb2fb5c2bbfae416f291a44eb5ad4c7d687c Mon Sep 17 00:00:00 2001 From: Edwin Kempin Date: Wed, 22 Jan 2014 16:13:03 +0100 Subject: [PATCH] Add extension point to allow plugins to validate project creation By implementing this extension point plugins can validate the creation of new projects based on input arguments. E.g. a plugin could enforce a certain name scheme for the project names. A more sophisticated plugin could use this extension point to restrict the project creation for certain groups to certain folders. Change-Id: I6b5c69cd435acf9789111d13f31049ef38699215 Signed-off-by: Edwin Kempin --- Documentation/config-validation.txt | 11 ++++++ .../server/config/GerritGlobalModule.java | 2 ++ .../validators/CommitValidationException.java | 4 ++- .../validators/MergeValidationException.java | 3 +- .../gerrit/server/project/CreateProject.java | 17 ++++++++- .../ProjectCreationValidationListener.java | 35 +++++++++++++++++++ .../validators/ValidationException.java | 27 ++++++++++++++ 7 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/validators/ProjectCreationValidationListener.java create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/validators/ValidationException.java diff --git a/Documentation/config-validation.txt b/Documentation/config-validation.txt index 9f5cded5c3..b3ca5870f2 100644 --- a/Documentation/config-validation.txt +++ b/Documentation/config-validation.txt @@ -32,6 +32,17 @@ are merged to the git repository. If the commit fails the validation, the plugin can throw an exception which will cause the merge to fail. +[[new-project-validation]] +== New project validation + + +Plugins implementing the `ProjectCreationValidationListener` interface +can perform additional validation on project creation based on the +input arguments. + +E.g. a plugin could use this to enforce a certain name scheme for +project names. + GERRIT ------ 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 d7f413e016..f9e2de45b8 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 @@ -118,6 +118,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.ProjectCreationValidationListener; import com.google.inject.Inject; import com.google.inject.TypeLiteral; import com.google.inject.internal.UniqueAnnotations; @@ -249,6 +250,7 @@ public class GerritGlobalModule extends FactoryModule { DynamicSet.setOf(binder(), ChangeListener.class); DynamicSet.setOf(binder(), CommitValidationListener.class); DynamicSet.setOf(binder(), MergeValidationListener.class); + DynamicSet.setOf(binder(), ProjectCreationValidationListener.class); DynamicItem.itemOf(binder(), AvatarProvider.class); DynamicSet.setOf(binder(), LifecycleListener.class); DynamicSet.setOf(binder(), TopMenu.class); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidationException.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidationException.java index 45278f9af0..029096e8f9 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidationException.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidationException.java @@ -14,10 +14,12 @@ package com.google.gerrit.server.git.validators; +import com.google.gerrit.server.validators.ValidationException; + import java.util.Collections; import java.util.List; -public class CommitValidationException extends Exception { +public class CommitValidationException extends ValidationException { private static final long serialVersionUID = 1L; private final List messages; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/MergeValidationException.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/MergeValidationException.java index 78819a80d8..bfad0e3932 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/MergeValidationException.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/MergeValidationException.java @@ -15,8 +15,9 @@ package com.google.gerrit.server.git.validators; import com.google.gerrit.server.git.CommitMergeStatus; +import com.google.gerrit.server.validators.ValidationException; -public class MergeValidationException extends Exception { +public class MergeValidationException extends ValidationException { private static final long serialVersionUID = 1L; private final CommitMergeStatus status; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java index 32c4ef850e..32956e5ece 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java @@ -20,7 +20,9 @@ import com.google.common.collect.Lists; import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.errors.ProjectCreationFailedException; import com.google.gerrit.extensions.annotations.RequiresCapability; +import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.TopLevelResource; @@ -33,6 +35,8 @@ import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.group.GroupsCollection; import com.google.gerrit.server.project.CreateProject.Input; import com.google.gerrit.server.project.ProjectJson.ProjectInfo; +import com.google.gerrit.server.validators.ProjectCreationValidationListener; +import com.google.gerrit.server.validators.ValidationException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; @@ -67,6 +71,7 @@ public class CreateProject implements RestModifyView { private final PerformCreateProject.Factory createProjectFactory; private final Provider projectsCollection; private final Provider groupsCollection; + private final DynamicSet projectCreationValidationListeners; private final ProjectJson json; private final String name; @@ -74,10 +79,12 @@ public class CreateProject implements RestModifyView { CreateProject(PerformCreateProject.Factory performCreateProjectFactory, Provider projectsCollection, Provider groupsCollection, ProjectJson json, + DynamicSet projectCreationValidationListeners, @Assisted String name) { this.createProjectFactory = performCreateProjectFactory; this.projectsCollection = projectsCollection; this.groupsCollection = groupsCollection; + this.projectCreationValidationListeners = projectCreationValidationListeners; this.json = json; this.name = name; } @@ -85,7 +92,7 @@ public class CreateProject implements RestModifyView { @Override public Response apply(TopLevelResource resource, Input input) throws BadRequestException, UnprocessableEntityException, - ProjectCreationFailedException, IOException { + ResourceConflictException, ProjectCreationFailedException, IOException { if (input == null) { input = new Input(); } @@ -129,6 +136,14 @@ public class CreateProject implements RestModifyView { throw new BadRequestException(e.getMessage()); } + for (ProjectCreationValidationListener l : projectCreationValidationListeners) { + try { + l.validateNewProject(args); + } catch (ValidationException e) { + throw new ResourceConflictException(e.getMessage(), e); + } + } + Project p = createProjectFactory.create(args).createProject(); return Response.created(json.format(p)); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/validators/ProjectCreationValidationListener.java b/gerrit-server/src/main/java/com/google/gerrit/server/validators/ProjectCreationValidationListener.java new file mode 100644 index 0000000000..d3c69c13f7 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/validators/ProjectCreationValidationListener.java @@ -0,0 +1,35 @@ +// 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.validators; + +import com.google.gerrit.extensions.annotations.ExtensionPoint; +import com.google.gerrit.server.project.CreateProjectArgs; + +/** + * Listener to provide validation on project creation. + */ +@ExtensionPoint +public interface ProjectCreationValidationListener { + /** + * Project creation validation. + * + * Invoked by Gerrit just before a new project is going to be created. + * + * @param args arguments for the project creation + * @throws ValidationException if validation fails + */ + public void validateNewProject(CreateProjectArgs args) + throws ValidationException; +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/validators/ValidationException.java b/gerrit-server/src/main/java/com/google/gerrit/server/validators/ValidationException.java new file mode 100644 index 0000000000..53ded1fd53 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/validators/ValidationException.java @@ -0,0 +1,27 @@ +// 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.validators; + +public class ValidationException extends Exception { + private static final long serialVersionUID = 1L; + + public ValidationException(String reason) { + super(reason); + } + + public ValidationException(String reason, Throwable why) { + super(reason, why); + } +}