Disable capability endpoints when not using default backend

The capability names exposed by these endpoints are implementation
details of the DefaultPermissionBackend. A different implementation may
choose to hide the GlobalPermission enum names from the user entirely,
so it doesn't make sense to expose them.

Change-Id: I69ea38064ccbf1c04a976e7bcb4629ab5d66aeef
This commit is contained in:
Dave Borowitz
2018-04-11 10:27:36 +02:00
parent 0a5f646bd8
commit cc4d1ac051
6 changed files with 79 additions and 5 deletions

View File

@@ -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;

View File

@@ -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}.
*
* <p>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.
*

View File

@@ -60,6 +60,7 @@ class Capabilities implements ChildCollection<AccountResource, AccountResource.C
@Override
public Capability parse(AccountResource parent, IdString id)
throws ResourceNotFoundException, AuthException, PermissionBackendException {
permissionBackend.checkUsesDefaultCapabilities();
IdentifiedUser target = parent.getUser();
if (self.get() != target) {
permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);

View File

@@ -23,8 +23,9 @@ import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
import com.google.gerrit.extensions.api.access.PluginPermission;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.OptionUtil;
@@ -75,7 +76,8 @@ class GetCapabilities implements RestReadView<AccountResource> {
}
@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<AccountResource> {
@Singleton
static class CheckOne implements RestReadView<AccountResource.Capability> {
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");
}
}

View File

@@ -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<ConfigResource> {
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<CapabilityDefinition> pluginCapabilities;
@Inject
public ListCapabilities(DynamicMap<CapabilityDefinition> pluginCapabilities) {
public ListCapabilities(
PermissionBackend permissionBackend, DynamicMap<CapabilityDefinition> pluginCapabilities) {
this.permissionBackend = permissionBackend;
this.pluginCapabilities = pluginCapabilities;
}
@Override
public Map<String, CapabilityInfo> apply(ConfigResource resource)
throws IllegalAccessException, NoSuchFieldException {
throws ResourceNotFoundException, IllegalAccessException, NoSuchFieldException {
permissionBackend.checkUsesDefaultCapabilities();
return ImmutableMap.<String, CapabilityInfo>builder()
.putAll(collectCoreCapabilities())
.putAll(collectPluginCapabilities())

View File

@@ -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;
}
}
}