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:
@@ -84,6 +84,11 @@ public class DefaultPermissionBackend extends PermissionBackend {
|
|||||||
return new WithUserImpl(identifiedUser);
|
return new WithUserImpl(identifiedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean usesDefaultCapabilities() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class WithUserImpl extends WithUser {
|
class WithUserImpl extends WithUser {
|
||||||
private final CurrentUser user;
|
private final CurrentUser user;
|
||||||
private Boolean admin;
|
private Boolean admin;
|
||||||
|
@@ -23,6 +23,7 @@ import com.google.gerrit.common.data.LabelType;
|
|||||||
import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
|
import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
|
||||||
import com.google.gerrit.extensions.conditions.BooleanCondition;
|
import com.google.gerrit.extensions.conditions.BooleanCondition;
|
||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
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.Account;
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
import com.google.gerrit.reviewdb.client.Branch;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
@@ -112,6 +113,29 @@ public abstract class PermissionBackend {
|
|||||||
*/
|
*/
|
||||||
public abstract WithUser absentUser(Account.Id user);
|
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.
|
* Bulk evaluate a set of {@link PermissionBackendCondition} for view handling.
|
||||||
*
|
*
|
||||||
|
@@ -60,6 +60,7 @@ class Capabilities implements ChildCollection<AccountResource, AccountResource.C
|
|||||||
@Override
|
@Override
|
||||||
public Capability parse(AccountResource parent, IdString id)
|
public Capability parse(AccountResource parent, IdString id)
|
||||||
throws ResourceNotFoundException, AuthException, PermissionBackendException {
|
throws ResourceNotFoundException, AuthException, PermissionBackendException {
|
||||||
|
permissionBackend.checkUsesDefaultCapabilities();
|
||||||
IdentifiedUser target = parent.getUser();
|
IdentifiedUser target = parent.getUser();
|
||||||
if (self.get() != target) {
|
if (self.get() != target) {
|
||||||
permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
|
permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
|
||||||
|
@@ -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.api.access.PluginPermission;
|
||||||
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
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.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.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.OptionUtil;
|
import com.google.gerrit.server.OptionUtil;
|
||||||
@@ -75,7 +76,8 @@ class GetCapabilities implements RestReadView<AccountResource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(AccountResource rsrc) throws AuthException, PermissionBackendException {
|
public Object apply(AccountResource rsrc) throws RestApiException, PermissionBackendException {
|
||||||
|
permissionBackend.checkUsesDefaultCapabilities();
|
||||||
PermissionBackend.WithUser perm = permissionBackend.currentUser();
|
PermissionBackend.WithUser perm = permissionBackend.currentUser();
|
||||||
if (self.get() != rsrc.getUser()) {
|
if (self.get() != rsrc.getUser()) {
|
||||||
perm.check(GlobalPermission.ADMINISTRATE_SERVER);
|
perm.check(GlobalPermission.ADMINISTRATE_SERVER);
|
||||||
@@ -158,8 +160,16 @@ class GetCapabilities implements RestReadView<AccountResource> {
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
static class CheckOne implements RestReadView<AccountResource.Capability> {
|
static class CheckOne implements RestReadView<AccountResource.Capability> {
|
||||||
|
private final PermissionBackend permissionBackend;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CheckOne(PermissionBackend permissionBackend) {
|
||||||
|
this.permissionBackend = permissionBackend;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryResult apply(Capability resource) {
|
public BinaryResult apply(Capability resource) throws ResourceNotFoundException {
|
||||||
|
permissionBackend.checkUsesDefaultCapabilities();
|
||||||
return BinaryResult.create("ok\n");
|
return BinaryResult.create("ok\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,9 +18,11 @@ import com.google.common.collect.ImmutableMap;
|
|||||||
import com.google.gerrit.common.data.GlobalCapability;
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
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.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.server.config.CapabilityConstants;
|
import com.google.gerrit.server.config.CapabilityConstants;
|
||||||
import com.google.gerrit.server.config.ConfigResource;
|
import com.google.gerrit.server.config.ConfigResource;
|
||||||
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
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 Logger log = LoggerFactory.getLogger(ListCapabilities.class);
|
||||||
private static final Pattern PLUGIN_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9-]+$");
|
private static final Pattern PLUGIN_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9-]+$");
|
||||||
|
|
||||||
|
private final PermissionBackend permissionBackend;
|
||||||
private final DynamicMap<CapabilityDefinition> pluginCapabilities;
|
private final DynamicMap<CapabilityDefinition> pluginCapabilities;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ListCapabilities(DynamicMap<CapabilityDefinition> pluginCapabilities) {
|
public ListCapabilities(
|
||||||
|
PermissionBackend permissionBackend, DynamicMap<CapabilityDefinition> pluginCapabilities) {
|
||||||
|
this.permissionBackend = permissionBackend;
|
||||||
this.pluginCapabilities = pluginCapabilities;
|
this.pluginCapabilities = pluginCapabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, CapabilityInfo> apply(ConfigResource resource)
|
public Map<String, CapabilityInfo> apply(ConfigResource resource)
|
||||||
throws IllegalAccessException, NoSuchFieldException {
|
throws ResourceNotFoundException, IllegalAccessException, NoSuchFieldException {
|
||||||
|
permissionBackend.checkUsesDefaultCapabilities();
|
||||||
return ImmutableMap.<String, CapabilityInfo>builder()
|
return ImmutableMap.<String, CapabilityInfo>builder()
|
||||||
.putAll(collectCoreCapabilities())
|
.putAll(collectCoreCapabilities())
|
||||||
.putAll(collectPluginCapabilities())
|
.putAll(collectPluginCapabilities())
|
||||||
|
@@ -20,11 +20,15 @@ import com.google.gerrit.common.data.GlobalCapability;
|
|||||||
import com.google.gerrit.extensions.annotations.Exports;
|
import com.google.gerrit.extensions.annotations.Exports;
|
||||||
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
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;
|
||||||
import com.google.gerrit.server.restapi.config.ListCapabilities.CapabilityInfo;
|
import com.google.gerrit.server.restapi.config.ListCapabilities.CapabilityInfo;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -48,6 +52,7 @@ public class ListCapabilitiesTest {
|
|||||||
return "Print Hello";
|
return "Print Hello";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
bind(PermissionBackend.class).to(FakePermissionBackend.class);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
injector = Guice.createInjector(mod);
|
injector = Guice.createInjector(mod);
|
||||||
@@ -68,4 +73,27 @@ public class ListCapabilitiesTest {
|
|||||||
assertThat(m.get(pluginCapability).id).isEqualTo(pluginCapability);
|
assertThat(m.get(pluginCapability).id).isEqualTo(pluginCapability);
|
||||||
assertThat(m.get(pluginCapability).name).isEqualTo("Print Hello");
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user