diff --git a/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java b/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
index 2c8c951339..17ea107e4b 100644
--- a/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
+++ b/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
@@ -84,6 +84,11 @@ public class DefaultPermissionBackend extends PermissionBackend {
return new WithUserImpl(identifiedUser);
}
+ @Override
+ public boolean usesDefaultCapabilities() {
+ return true;
+ }
+
class WithUserImpl extends WithUser {
private final CurrentUser user;
private Boolean admin;
diff --git a/java/com/google/gerrit/server/permissions/PermissionBackend.java b/java/com/google/gerrit/server/permissions/PermissionBackend.java
index ed10184a8c..491769ccac 100644
--- a/java/com/google/gerrit/server/permissions/PermissionBackend.java
+++ b/java/com/google/gerrit/server/permissions/PermissionBackend.java
@@ -23,6 +23,7 @@ import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
@@ -112,6 +113,29 @@ public abstract class PermissionBackend {
*/
public abstract WithUser absentUser(Account.Id user);
+ /**
+ * Check whether this {@code PermissionBackend} respects the same global capabilities as the
+ * {@link DefaultPermissionBackend}.
+ *
+ *
If true, then it makes sense for downstream callers to refer to built-in Gerrit capability
+ * names in user-facing error messages, for example.
+ *
+ * @return whether this is the default permission backend.
+ */
+ public boolean usesDefaultCapabilities() {
+ return false;
+ }
+
+ /**
+ * Throw {@link ResourceNotFoundException} if this backend does not use the default global
+ * capabilities.
+ */
+ public void checkUsesDefaultCapabilities() throws ResourceNotFoundException {
+ if (!usesDefaultCapabilities()) {
+ throw new ResourceNotFoundException("Gerrit capabilities not used on this server");
+ }
+ }
+
/**
* Bulk evaluate a set of {@link PermissionBackendCondition} for view handling.
*
diff --git a/java/com/google/gerrit/server/restapi/account/Capabilities.java b/java/com/google/gerrit/server/restapi/account/Capabilities.java
index 2dd54a505e..d18f1b25ad 100644
--- a/java/com/google/gerrit/server/restapi/account/Capabilities.java
+++ b/java/com/google/gerrit/server/restapi/account/Capabilities.java
@@ -60,6 +60,7 @@ class Capabilities implements ChildCollection {
}
@Override
- public Object apply(AccountResource rsrc) throws AuthException, PermissionBackendException {
+ public Object apply(AccountResource rsrc) throws RestApiException, PermissionBackendException {
+ permissionBackend.checkUsesDefaultCapabilities();
PermissionBackend.WithUser perm = permissionBackend.currentUser();
if (self.get() != rsrc.getUser()) {
perm.check(GlobalPermission.ADMINISTRATE_SERVER);
@@ -158,8 +160,16 @@ class GetCapabilities implements RestReadView {
@Singleton
static class CheckOne implements RestReadView {
+ private final PermissionBackend permissionBackend;
+
+ @Inject
+ CheckOne(PermissionBackend permissionBackend) {
+ this.permissionBackend = permissionBackend;
+ }
+
@Override
- public BinaryResult apply(Capability resource) {
+ public BinaryResult apply(Capability resource) throws ResourceNotFoundException {
+ permissionBackend.checkUsesDefaultCapabilities();
return BinaryResult.create("ok\n");
}
}
diff --git a/java/com/google/gerrit/server/restapi/config/ListCapabilities.java b/java/com/google/gerrit/server/restapi/config/ListCapabilities.java
index 853e156972..412b88dc6f 100644
--- a/java/com/google/gerrit/server/restapi/config/ListCapabilities.java
+++ b/java/com/google/gerrit/server/restapi/config/ListCapabilities.java
@@ -18,9 +18,11 @@ import com.google.common.collect.ImmutableMap;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.config.CapabilityConstants;
import com.google.gerrit.server.config.ConfigResource;
+import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -36,16 +38,20 @@ public class ListCapabilities implements RestReadView {
private static final Logger log = LoggerFactory.getLogger(ListCapabilities.class);
private static final Pattern PLUGIN_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9-]+$");
+ private final PermissionBackend permissionBackend;
private final DynamicMap pluginCapabilities;
@Inject
- public ListCapabilities(DynamicMap pluginCapabilities) {
+ public ListCapabilities(
+ PermissionBackend permissionBackend, DynamicMap pluginCapabilities) {
+ this.permissionBackend = permissionBackend;
this.pluginCapabilities = pluginCapabilities;
}
@Override
public Map apply(ConfigResource resource)
- throws IllegalAccessException, NoSuchFieldException {
+ throws ResourceNotFoundException, IllegalAccessException, NoSuchFieldException {
+ permissionBackend.checkUsesDefaultCapabilities();
return ImmutableMap.builder()
.putAll(collectCoreCapabilities())
.putAll(collectPluginCapabilities())
diff --git a/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java b/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
index 577d931dc2..935dfc69af 100644
--- a/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
+++ b/javatests/com/google/gerrit/server/config/ListCapabilitiesTest.java
@@ -20,11 +20,15 @@ import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.Exports;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.restapi.config.ListCapabilities;
import com.google.gerrit.server.restapi.config.ListCapabilities.CapabilityInfo;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.Singleton;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +52,7 @@ public class ListCapabilitiesTest {
return "Print Hello";
}
});
+ bind(PermissionBackend.class).to(FakePermissionBackend.class);
}
};
injector = Guice.createInjector(mod);
@@ -68,4 +73,27 @@ public class ListCapabilitiesTest {
assertThat(m.get(pluginCapability).id).isEqualTo(pluginCapability);
assertThat(m.get(pluginCapability).name).isEqualTo("Print Hello");
}
+
+ @Singleton
+ private static class FakePermissionBackend extends PermissionBackend {
+ @Override
+ public WithUser currentUser() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WithUser user(CurrentUser user) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public WithUser absentUser(Id user) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean usesDefaultCapabilities() {
+ return true;
+ }
+ }
}