Add modify reviewers config plugin capability
Allow to use plugin own capability in addition to project owners ACL.
Feature: Issue 9224
Change-Id: I2e214cb39b08788f4f2fff03d82ab8811960d3ca
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/ModifyReviewersConfigCapability.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/ModifyReviewersConfigCapability.java
new file mode 100644
index 0000000..4c6cb9a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/ModifyReviewersConfigCapability.java
@@ -0,0 +1,26 @@
+// 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 com.google.gerrit.extensions.config.CapabilityDefinition;
+
+public class ModifyReviewersConfigCapability extends CapabilityDefinition {
+ static final String MODIFY_REVIEWERS_CONFIG = "modifyReviewersConfig";
+
+ @Override
+ public String getDescription() {
+ return "Modify Reviewers Config";
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
index 3e949d6..9951538 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
@@ -15,8 +15,10 @@
package com.googlesource.gerrit.plugins.reviewers;
import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
+import static com.googlesource.gerrit.plugins.reviewers.ModifyReviewersConfigCapability.MODIFY_REVIEWERS_CONFIG;
import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.extensions.events.RevisionCreatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
@@ -48,6 +50,10 @@
@Override
protected void configure() {
+ bind(CapabilityDefinition.class)
+ .annotatedWith(Exports.named(MODIFY_REVIEWERS_CONFIG))
+ .to(ModifyReviewersConfigCapability.class);
+
if (enableUI) {
DynamicSet.bind(binder(), TopMenu.class).to(ReviewersTopMenu.class);
DynamicSet.bind(binder(), WebUiPlugin.class).toInstance(new GwtPlugin("reviewers"));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
index f23e275..b3de693 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/PutReviewers.java
@@ -14,7 +14,11 @@
package com.googlesource.gerrit.plugins.reviewers;
+import static com.googlesource.gerrit.plugins.reviewers.ModifyReviewersConfigCapability.MODIFY_REVIEWERS_CONFIG;
+
import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.api.access.PluginPermission;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -25,6 +29,7 @@
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.group.GroupsCollection;
+import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gwtorm.server.OrmException;
@@ -55,6 +60,7 @@
private final ProjectCache projectCache;
private final AccountResolver accountResolver;
private final Provider<GroupsCollection> groupsCollection;
+ private final PermissionBackend permissionBackend;
@Inject
PutReviewers(
@@ -63,13 +69,15 @@
Provider<MetaDataUpdate.User> metaDataUpdateFactory,
ProjectCache projectCache,
AccountResolver accountResolver,
- Provider<GroupsCollection> groupsCollection) {
+ Provider<GroupsCollection> groupsCollection,
+ PermissionBackend permissionBackend) {
this.pluginName = pluginName;
this.config = config;
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.projectCache = projectCache;
this.accountResolver = accountResolver;
this.groupsCollection = groupsCollection;
+ this.permissionBackend = permissionBackend;
}
@Override
@@ -77,10 +85,16 @@
throws RestApiException {
Project.NameKey projectName = rsrc.getNameKey();
ReviewersConfig.ForProject cfg = config.forProject(projectName);
- if (!rsrc.getControl().isOwner() || cfg == null) {
+ if (cfg == null) {
throw new ResourceNotFoundException("Project" + projectName.get() + " not found");
}
+ PermissionBackend.WithUser userPermission = permissionBackend.user(rsrc.getUser());
+ if (!rsrc.getControl().isOwner()
+ && !userPermission.testOrFalse(new PluginPermission(pluginName, MODIFY_REVIEWERS_CONFIG))) {
+ throw new AuthException("not allowed to modify reviewers config");
+ }
+
try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
if (input.action == Action.ADD) {
validateReviewer(input.reviewer);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/AccountCapabilities.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/AccountCapabilities.java
new file mode 100644
index 0000000..397ffcb
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/AccountCapabilities.java
@@ -0,0 +1,31 @@
+// 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.client;
+
+import com.google.gerrit.plugin.client.rpc.RestApi;
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+public class AccountCapabilities extends JavaScriptObject {
+ static String MODIFY_REVIEWERS_CONFIG = "reviewers-modifyReviewersConfig";
+
+ public static void queryPluginCapability(AsyncCallback<AccountCapabilities> cb) {
+ new RestApi("/accounts/self/capabilities").addParameter("q", MODIFY_REVIEWERS_CONFIG).get(cb);
+ }
+
+ protected AccountCapabilities() {}
+
+ public final native boolean canPerform(String name) /*-{ return this[name] ? true : false; }-*/;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/ReviewersScreen.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/ReviewersScreen.java
index ba601ae..47bedd7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/ReviewersScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/client/ReviewersScreen.java
@@ -14,6 +14,8 @@
package com.googlesource.gerrit.plugins.reviewers.client;
+import static com.googlesource.gerrit.plugins.reviewers.client.AccountCapabilities.MODIFY_REVIEWERS_CONFIG;
+
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.plugin.client.rpc.RestApi;
@@ -48,10 +50,11 @@
}
private boolean isOwner;
+ private boolean hasModifyReviewersConfigCapability;
private String projectName;
private Set<ReviewerEntry> rEntries;
- ReviewersScreen(final String projectName) {
+ ReviewersScreen(String projectName) {
setStyleName("reviewers-panel");
this.projectName = projectName;
this.rEntries = new HashSet<>();
@@ -64,7 +67,24 @@
@Override
public void onSuccess(NativeMap<ProjectAccessInfo> result) {
isOwner = result.get(projectName).isOwner();
- display();
+ if (isOwner) {
+ display();
+ } else {
+ // TODO(davido): Find a way to run above and below requests in parallel
+ AccountCapabilities.queryPluginCapability(
+ new AsyncCallback<AccountCapabilities>() {
+
+ @Override
+ public void onSuccess(AccountCapabilities result) {
+ hasModifyReviewersConfigCapability =
+ result.canPerform(MODIFY_REVIEWERS_CONFIG);
+ display();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {}
+ });
+ }
}
@Override
@@ -124,7 +144,7 @@
doSave(Action.REMOVE, e);
}
});
- removeButton.setVisible(isOwner);
+ removeButton.setVisible(isModifiable());
HorizontalPanel p = new HorizontalPanel();
p.add(l);
@@ -161,9 +181,9 @@
reviewerBox.setText("");
}
});
- filterBox.setEnabled(isOwner);
- reviewerBox.setEnabled(isOwner);
- addButton.setEnabled(isOwner);
+ filterBox.setEnabled(isModifiable());
+ reviewerBox.setEnabled(isModifiable());
+ addButton.setEnabled(isModifiable());
Panel p = new VerticalPanel();
p.setStyleName("reviewers-inputPanel");
@@ -172,6 +192,10 @@
return p;
}
+ boolean isModifiable() {
+ return isOwner || hasModifyReviewersConfigCapability;
+ }
+
void doSave(Action action, ReviewerEntry entry) {
ChangeReviewersInput in = ChangeReviewersInput.create();
in.setAction(action);
diff --git a/src/main/resources/Documentation/rest-api.md b/src/main/resources/Documentation/rest-api.md
index 6fe3733..ebd04d4 100644
--- a/src/main/resources/Documentation/rest-api.md
+++ b/src/main/resources/Documentation/rest-api.md
@@ -56,6 +56,9 @@
The change to reviewers must be provided in the request body inside
a [ConfigReviewersInput](#config-reviewers-input) entity.
+Caller must be a member of a group that is granted the 'Modify Reviewers Config'
+capability (provided by this plugin) or be a Project Owner for the project.
+
#### Request
```