Apply @RequiresCapability to REST API
Move the @RequiresCapability from SSHD to gerrit-extension-api. Modify the RestApiServlet to check the current user has the required capabilities. All RestApiServlets must now inject the currentUser provider in their constructor and pass it to the super class. Signed-off-by: Brad Larson <bklarson@gmail.com> Change-Id: Iffc9bc99b8d2fafd07bf624008719b0ec647ce7d
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.sshd;
|
||||
package com.google.gerrit.extensions.annotations;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@@ -21,7 +21,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation on {@link SshCommand} declaring a capability must be granted.
|
||||
* Annotation on {@link SshCommand} or {@link RestApiServlet} declaring a
|
||||
* capability must be granted.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RUNTIME)
|
@@ -15,10 +15,14 @@
|
||||
package com.google.gerrit.httpd;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.account.CapabilityControl;
|
||||
import com.google.gerrit.util.cli.CmdLineParser;
|
||||
import com.google.gwtjsonrpc.server.RPCServletUtils;
|
||||
import com.google.gwtjsonrpc.common.JsonConstants;
|
||||
import com.google.gwtjsonrpc.server.RPCServletUtils;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.kohsuke.args4j.CmdLineException;
|
||||
import org.slf4j.Logger;
|
||||
@@ -62,12 +66,24 @@ public abstract class RestApiServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
private final Provider<CurrentUser> currentUser;
|
||||
|
||||
@Inject
|
||||
protected RestApiServlet(final Provider<CurrentUser> currentUser) {
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse res)
|
||||
throws ServletException, IOException {
|
||||
noCache(res);
|
||||
try {
|
||||
checkRequiresCapability();
|
||||
super.service(req, res);
|
||||
} catch (RequireCapabilityException err) {
|
||||
res.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
noCache(res);
|
||||
sendText(req, res, err.getMessage());
|
||||
} catch (Error err) {
|
||||
handleError(err, req, res);
|
||||
} catch (RuntimeException err) {
|
||||
@@ -75,6 +91,20 @@ public abstract class RestApiServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRequiresCapability() throws RequireCapabilityException {
|
||||
RequiresCapability rc = getClass().getAnnotation(RequiresCapability.class);
|
||||
if (rc != null) {
|
||||
CurrentUser user = currentUser.get();
|
||||
CapabilityControl ctl = user.getCapabilities();
|
||||
if (!ctl.canPerform(rc.value()) && !ctl.canAdministrateServer()) {
|
||||
String msg = String.format(
|
||||
"fatal: %s does not have \"%s\" capability.",
|
||||
user.getUserName(), rc.value());
|
||||
throw new RequireCapabilityException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void noCache(HttpServletResponse res) {
|
||||
res.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
@@ -175,4 +205,11 @@ public abstract class RestApiServlet extends HttpServlet {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial") // Never serialized or thrown out of this class.
|
||||
private static class RequireCapabilityException extends Exception {
|
||||
public RequireCapabilityException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -58,8 +58,9 @@ public class AccountCapabilitiesServlet extends RestApiServlet {
|
||||
private final Provider<Impl> factory;
|
||||
|
||||
@Inject
|
||||
AccountCapabilitiesServlet(
|
||||
AccountCapabilitiesServlet(final Provider<CurrentUser> currentUser,
|
||||
ParameterParser paramParser, Provider<Impl> factory) {
|
||||
super(currentUser);
|
||||
this.paramParser = paramParser;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.httpd.rpc.change;
|
||||
|
||||
import com.google.gerrit.httpd.RestApiServlet;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.OutputFormat;
|
||||
import com.google.gerrit.server.query.QueryParseException;
|
||||
import com.google.gerrit.server.query.change.ListChanges;
|
||||
@@ -43,7 +44,9 @@ public class ListChangesServlet extends RestApiServlet {
|
||||
private final Provider<ListChanges> factory;
|
||||
|
||||
@Inject
|
||||
ListChangesServlet(ParameterParser paramParser, Provider<ListChanges> ls) {
|
||||
ListChangesServlet(final Provider<CurrentUser> currentUser,
|
||||
ParameterParser paramParser, Provider<ListChanges> ls) {
|
||||
super(currentUser);
|
||||
this.paramParser = paramParser;
|
||||
this.factory = ls;
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.httpd.rpc.project;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.httpd.RestApiServlet;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.OutputFormat;
|
||||
import com.google.gerrit.server.project.ListProjects;
|
||||
import com.google.inject.Inject;
|
||||
@@ -36,7 +37,9 @@ public class ListProjectsServlet extends RestApiServlet {
|
||||
private final Provider<ListProjects> factory;
|
||||
|
||||
@Inject
|
||||
ListProjectsServlet(ParameterParser paramParser, Provider<ListProjects> ls) {
|
||||
ListProjectsServlet(final Provider<CurrentUser> currentUser,
|
||||
ParameterParser paramParser, Provider<ListProjects> ls) {
|
||||
super(currentUser);
|
||||
this.paramParser = paramParser;
|
||||
this.factory = ls;
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.sshd;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.Atomics;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.account.CapabilityControl;
|
||||
import com.google.inject.Provider;
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.sshd;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.Atomics;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.account.CapabilityControl;
|
||||
import com.google.gerrit.sshd.args4j.SubcommandHandler;
|
||||
|
@@ -15,8 +15,8 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.git.MetaDataUpdate;
|
||||
@@ -22,7 +23,6 @@ import com.google.gerrit.server.git.ProjectConfig;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.gerrit.server.project.ProjectControl;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.common.errors.InvalidSshKeyException;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
@@ -27,7 +28,6 @@ import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.AccountByEmailCache;
|
||||
import com.google.gerrit.server.account.AccountCache;
|
||||
import com.google.gerrit.server.ssh.SshKeyCache;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.gwtorm.server.OrmDuplicateKeyException;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
|
@@ -17,10 +17,10 @@ package com.google.gerrit.sshd.commands;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||
import com.google.gerrit.common.errors.PermissionDeniedException;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.server.account.PerformCreateGroup;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.sshd.commands;
|
||||
|
||||
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.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
@@ -23,7 +24,6 @@ import com.google.gerrit.server.project.CreateProject;
|
||||
import com.google.gerrit.server.project.CreateProjectArgs;
|
||||
import com.google.gerrit.server.project.ProjectControl;
|
||||
import com.google.gerrit.server.project.SuggestParentCandidates;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -15,9 +15,9 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.sshd.BaseCommand;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
@@ -15,11 +15,11 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.git.WorkQueue;
|
||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||
import com.google.gerrit.server.util.IdGenerator;
|
||||
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -16,9 +16,9 @@ package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.plugins.PluginInstallException;
|
||||
import com.google.gerrit.server.plugins.PluginLoader;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -15,9 +15,9 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.plugins.ListPlugins;
|
||||
import com.google.gerrit.sshd.BaseCommand;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.apache.sshd.server.Environment;
|
||||
|
@@ -17,8 +17,8 @@ package com.google.gerrit.sshd.commands;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.server.plugins.InvalidPluginException;
|
||||
import com.google.gerrit.server.plugins.PluginInstallException;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.plugins.PluginLoader;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -16,8 +16,8 @@ package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.plugins.PluginLoader;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -16,11 +16,11 @@ package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.Version;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||
import com.google.gerrit.server.config.SitePath;
|
||||
import com.google.gerrit.server.git.WorkQueue;
|
||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshDaemon;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@@ -15,10 +15,10 @@
|
||||
package com.google.gerrit.sshd.commands;
|
||||
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.util.IdGenerator;
|
||||
import com.google.gerrit.sshd.RequiresCapability;
|
||||
import com.google.gerrit.sshd.SshCommand;
|
||||
import com.google.gerrit.sshd.SshDaemon;
|
||||
import com.google.gerrit.sshd.SshSession;
|
||||
|
Reference in New Issue
Block a user