Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit ff7eef03990faa02d7ad1ff845f6e9525275fd95 1 parent 2d872eb
Brad Larson authored May 15, 2012

Showing 20 changed files with 66 additions and 19 deletions. Show diff stats Hide diff stats

  1. 5  ...→ gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations}/RequiresCapability.java
  2. 39  gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java
  3. 3  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java
  4. 5  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java
  5. 5  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java
  6. 1  gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java
  7. 1  gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java
  8. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java
  9. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
  10. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
  11. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
  12. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
  13. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java
  14. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java
  15. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java
  16. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java
  17. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java
  18. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java
  19. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java
  20. 2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java
5  ...va/com/google/gerrit/sshd/RequiresCapability.java → ...it/extensions/annotations/RequiresCapability.java
@@ -12,7 +12,7 @@
12 12
 // See the License for the specific language governing permissions and
13 13
 // limitations under the License.
14 14
 
15  
-package com.google.gerrit.sshd;
  15
+package com.google.gerrit.extensions.annotations;
16 16
 
17 17
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
18 18
 
@@ -21,7 +21,8 @@
21 21
 import java.lang.annotation.Target;
22 22
 
23 23
 /**
24  
- * Annotation on {@link SshCommand} declaring a capability must be granted.
  24
+ * Annotation on {@link SshCommand} or {@link RestApiServlet} declaring a
  25
+ * capability must be granted.
25 26
  */
26 27
 @Target({ElementType.TYPE})
27 28
 @Retention(RUNTIME)
39  gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java
@@ -15,10 +15,14 @@
15 15
 package com.google.gerrit.httpd;
16 16
 
17 17
 import com.google.common.base.Strings;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
  19
+import com.google.gerrit.server.CurrentUser;
  20
+import com.google.gerrit.server.account.CapabilityControl;
18 21
 import com.google.gerrit.util.cli.CmdLineParser;
19  
-import com.google.gwtjsonrpc.server.RPCServletUtils;
20 22
 import com.google.gwtjsonrpc.common.JsonConstants;
  23
+import com.google.gwtjsonrpc.server.RPCServletUtils;
21 24
 import com.google.inject.Inject;
  25
+import com.google.inject.Provider;
22 26
 
23 27
 import org.kohsuke.args4j.CmdLineException;
24 28
 import org.slf4j.Logger;
@@ -62,12 +66,24 @@
62 66
     }
63 67
   }
64 68
 
  69
+  private final Provider<CurrentUser> currentUser;
  70
+
  71
+  @Inject
  72
+  protected RestApiServlet(final Provider<CurrentUser> currentUser) {
  73
+    this.currentUser = currentUser;
  74
+  }
  75
+
65 76
   @Override
66 77
   protected void service(HttpServletRequest req, HttpServletResponse res)
67 78
       throws ServletException, IOException {
68 79
     noCache(res);
69 80
     try {
  81
+      checkRequiresCapability();
70 82
       super.service(req, res);
  83
+    } catch (RequireCapabilityException err) {
  84
+      res.setStatus(HttpServletResponse.SC_FORBIDDEN);
  85
+      noCache(res);
  86
+      sendText(req, res, err.getMessage());
71 87
     } catch (Error err) {
72 88
       handleError(err, req, res);
73 89
     } catch (RuntimeException err) {
@@ -75,6 +91,20 @@ protected void service(HttpServletRequest req, HttpServletResponse res)
75 91
     }
76 92
   }
77 93
 
  94
+  private void checkRequiresCapability() throws RequireCapabilityException {
  95
+    RequiresCapability rc = getClass().getAnnotation(RequiresCapability.class);
  96
+    if (rc != null) {
  97
+      CurrentUser user = currentUser.get();
  98
+      CapabilityControl ctl = user.getCapabilities();
  99
+      if (!ctl.canPerform(rc.value()) && !ctl.canAdministrateServer()) {
  100
+        String msg = String.format(
  101
+            "fatal: %s does not have \"%s\" capability.",
  102
+            user.getUserName(), rc.value());
  103
+        throw new RequireCapabilityException(msg);
  104
+      }
  105
+    }
  106
+  }
  107
+
78 108
   private static void noCache(HttpServletResponse res) {
79 109
     res.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
80 110
     res.setHeader("Pragma", "no-cache");
@@ -175,4 +205,11 @@ protected static void send(HttpServletRequest req, HttpServletResponse res,
175 205
       return true;
176 206
     }
177 207
   }
  208
+
  209
+  @SuppressWarnings("serial") // Never serialized or thrown out of this class.
  210
+  private static class RequireCapabilityException extends Exception {
  211
+    public RequireCapabilityException(String msg) {
  212
+      super(msg);
  213
+    }
  214
+  }
178 215
 }
3  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java
@@ -58,8 +58,9 @@
58 58
   private final Provider<Impl> factory;
59 59
 
60 60
   @Inject
61  
-  AccountCapabilitiesServlet(
  61
+  AccountCapabilitiesServlet(final Provider<CurrentUser> currentUser,
62 62
       ParameterParser paramParser, Provider<Impl> factory) {
  63
+    super(currentUser);
63 64
     this.paramParser = paramParser;
64 65
     this.factory = factory;
65 66
   }
5  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java
@@ -15,6 +15,7 @@
15 15
 package com.google.gerrit.httpd.rpc.change;
16 16
 
17 17
 import com.google.gerrit.httpd.RestApiServlet;
  18
+import com.google.gerrit.server.CurrentUser;
18 19
 import com.google.gerrit.server.OutputFormat;
19 20
 import com.google.gerrit.server.query.QueryParseException;
20 21
 import com.google.gerrit.server.query.change.ListChanges;
@@ -43,7 +44,9 @@
43 44
   private final Provider<ListChanges> factory;
44 45
 
45 46
   @Inject
46  
-  ListChangesServlet(ParameterParser paramParser, Provider<ListChanges> ls) {
  47
+  ListChangesServlet(final Provider<CurrentUser> currentUser,
  48
+      ParameterParser paramParser, Provider<ListChanges> ls) {
  49
+    super(currentUser);
47 50
     this.paramParser = paramParser;
48 51
     this.factory = ls;
49 52
   }
5  gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java
@@ -16,6 +16,7 @@
16 16
 
17 17
 import com.google.common.base.Strings;
18 18
 import com.google.gerrit.httpd.RestApiServlet;
  19
+import com.google.gerrit.server.CurrentUser;
19 20
 import com.google.gerrit.server.OutputFormat;
20 21
 import com.google.gerrit.server.project.ListProjects;
21 22
 import com.google.inject.Inject;
@@ -36,7 +37,9 @@
36 37
   private final Provider<ListProjects> factory;
37 38
 
38 39
   @Inject
39  
-  ListProjectsServlet(ParameterParser paramParser, Provider<ListProjects> ls) {
  40
+  ListProjectsServlet(final Provider<CurrentUser> currentUser,
  41
+      ParameterParser paramParser, Provider<ListProjects> ls) {
  42
+    super(currentUser);
40 43
     this.paramParser = paramParser;
41 44
     this.factory = ls;
42 45
   }
1  gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java
@@ -16,6 +16,7 @@
16 16
 
17 17
 import com.google.common.collect.Lists;
18 18
 import com.google.common.util.concurrent.Atomics;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.server.CurrentUser;
20 21
 import com.google.gerrit.server.account.CapabilityControl;
21 22
 import com.google.inject.Provider;
1  gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java
@@ -16,6 +16,7 @@
16 16
 
17 17
 import com.google.common.collect.Sets;
18 18
 import com.google.common.util.concurrent.Atomics;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.server.CurrentUser;
20 21
 import com.google.gerrit.server.account.CapabilityControl;
21 22
 import com.google.gerrit.sshd.args4j.SubcommandHandler;
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java
@@ -15,8 +15,8 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.sshd.AdminHighPriorityCommand;
19  
-import com.google.gerrit.sshd.RequiresCapability;
20 20
 import com.google.gerrit.sshd.SshCommand;
21 21
 import com.google.inject.Inject;
22 22
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
@@ -15,6 +15,7 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.reviewdb.client.Project;
19 20
 import com.google.gerrit.server.config.AllProjectsName;
20 21
 import com.google.gerrit.server.git.MetaDataUpdate;
@@ -22,7 +23,6 @@
22 23
 import com.google.gerrit.server.project.ProjectCache;
23 24
 import com.google.gerrit.server.project.ProjectControl;
24 25
 import com.google.gerrit.server.project.ProjectState;
25  
-import com.google.gerrit.sshd.RequiresCapability;
26 26
 import com.google.gerrit.sshd.SshCommand;
27 27
 import com.google.inject.Inject;
28 28
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
@@ -16,6 +16,7 @@
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
18 18
 import com.google.gerrit.common.errors.InvalidSshKeyException;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.reviewdb.client.Account;
20 21
 import com.google.gerrit.reviewdb.client.AccountExternalId;
21 22
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -27,7 +28,6 @@
27 28
 import com.google.gerrit.server.account.AccountByEmailCache;
28 29
 import com.google.gerrit.server.account.AccountCache;
29 30
 import com.google.gerrit.server.ssh.SshKeyCache;
30  
-import com.google.gerrit.sshd.RequiresCapability;
31 31
 import com.google.gerrit.sshd.SshCommand;
32 32
 import com.google.gwtorm.server.OrmDuplicateKeyException;
33 33
 import com.google.gwtorm.server.OrmException;
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
@@ -17,10 +17,10 @@
17 17
 import com.google.gerrit.common.data.GlobalCapability;
18 18
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
19 19
 import com.google.gerrit.common.errors.PermissionDeniedException;
  20
+import com.google.gerrit.extensions.annotations.RequiresCapability;
20 21
 import com.google.gerrit.reviewdb.client.Account;
21 22
 import com.google.gerrit.reviewdb.client.AccountGroup;
22 23
 import com.google.gerrit.server.account.PerformCreateGroup;
23  
-import com.google.gerrit.sshd.RequiresCapability;
24 24
 import com.google.gerrit.sshd.SshCommand;
25 25
 import com.google.gwtorm.server.OrmException;
26 26
 import com.google.inject.Inject;
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
@@ -16,6 +16,7 @@
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
18 18
 import com.google.gerrit.common.errors.ProjectCreationFailedException;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.reviewdb.client.AccountGroup;
20 21
 import com.google.gerrit.reviewdb.client.Project;
21 22
 import com.google.gerrit.reviewdb.client.Project.SubmitType;
@@ -23,7 +24,6 @@
23 24
 import com.google.gerrit.server.project.CreateProjectArgs;
24 25
 import com.google.gerrit.server.project.ProjectControl;
25 26
 import com.google.gerrit.server.project.SuggestParentCandidates;
26  
-import com.google.gerrit.sshd.RequiresCapability;
27 27
 import com.google.gerrit.sshd.SshCommand;
28 28
 import com.google.inject.Inject;
29 29
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java
@@ -15,9 +15,9 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.server.IdentifiedUser;
19 20
 import com.google.gerrit.sshd.BaseCommand;
20  
-import com.google.gerrit.sshd.RequiresCapability;
21 21
 import com.google.inject.Inject;
22 22
 
23 23
 import net.sf.ehcache.Ehcache;
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java
@@ -15,11 +15,11 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.server.git.WorkQueue;
19 20
 import com.google.gerrit.server.git.WorkQueue.Task;
20 21
 import com.google.gerrit.server.util.IdGenerator;
21 22
 import com.google.gerrit.sshd.AdminHighPriorityCommand;
22  
-import com.google.gerrit.sshd.RequiresCapability;
23 23
 import com.google.gerrit.sshd.SshCommand;
24 24
 import com.google.inject.Inject;
25 25
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java
@@ -16,9 +16,9 @@
16 16
 
17 17
 import com.google.common.base.Strings;
18 18
 import com.google.gerrit.common.data.GlobalCapability;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.server.plugins.PluginInstallException;
20 21
 import com.google.gerrit.server.plugins.PluginLoader;
21  
-import com.google.gerrit.sshd.RequiresCapability;
22 22
 import com.google.gerrit.sshd.SshCommand;
23 23
 import com.google.inject.Inject;
24 24
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java
@@ -15,9 +15,9 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.server.plugins.ListPlugins;
19 20
 import com.google.gerrit.sshd.BaseCommand;
20  
-import com.google.gerrit.sshd.RequiresCapability;
21 21
 import com.google.inject.Inject;
22 22
 
23 23
 import org.apache.sshd.server.Environment;
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java
@@ -17,8 +17,8 @@
17 17
 import com.google.gerrit.common.data.GlobalCapability;
18 18
 import com.google.gerrit.server.plugins.InvalidPluginException;
19 19
 import com.google.gerrit.server.plugins.PluginInstallException;
  20
+import com.google.gerrit.extensions.annotations.RequiresCapability;
20 21
 import com.google.gerrit.server.plugins.PluginLoader;
21  
-import com.google.gerrit.sshd.RequiresCapability;
22 22
 import com.google.gerrit.sshd.SshCommand;
23 23
 import com.google.inject.Inject;
24 24
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java
@@ -16,8 +16,8 @@
16 16
 
17 17
 import com.google.common.collect.Sets;
18 18
 import com.google.gerrit.common.data.GlobalCapability;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.server.plugins.PluginLoader;
20  
-import com.google.gerrit.sshd.RequiresCapability;
21 21
 import com.google.gerrit.sshd.SshCommand;
22 22
 import com.google.inject.Inject;
23 23
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java
@@ -16,11 +16,11 @@
16 16
 
17 17
 import com.google.gerrit.common.Version;
18 18
 import com.google.gerrit.common.data.GlobalCapability;
  19
+import com.google.gerrit.extensions.annotations.RequiresCapability;
19 20
 import com.google.gerrit.extensions.events.LifecycleListener;
20 21
 import com.google.gerrit.server.config.SitePath;
21 22
 import com.google.gerrit.server.git.WorkQueue;
22 23
 import com.google.gerrit.server.git.WorkQueue.Task;
23  
-import com.google.gerrit.sshd.RequiresCapability;
24 24
 import com.google.gerrit.sshd.SshDaemon;
25 25
 import com.google.inject.Inject;
26 26
 
2  gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java
@@ -15,10 +15,10 @@
15 15
 package com.google.gerrit.sshd.commands;
16 16
 
17 17
 import com.google.gerrit.common.data.GlobalCapability;
  18
+import com.google.gerrit.extensions.annotations.RequiresCapability;
18 19
 import com.google.gerrit.server.CurrentUser;
19 20
 import com.google.gerrit.server.IdentifiedUser;
20 21
 import com.google.gerrit.server.util.IdGenerator;
21  
-import com.google.gerrit.sshd.RequiresCapability;
22 22
 import com.google.gerrit.sshd.SshCommand;
23 23
 import com.google.gerrit.sshd.SshDaemon;
24 24
 import com.google.gerrit.sshd.SshSession;

0 notes on commit ff7eef0

Please sign in to comment.
Something went wrong with that request. Please try again.