Index: appengine/logdog/coordinator/context.go |
diff --git a/appengine/logdog/coordinator/context.go b/appengine/logdog/coordinator/context.go |
index 38643ea7f20fa6dca86b6291a41dbece587105af..f8896477399f14a6bf52eb589c6960bd87363042 100644 |
--- a/appengine/logdog/coordinator/context.go |
+++ b/appengine/logdog/coordinator/context.go |
@@ -13,6 +13,25 @@ import ( |
"golang.org/x/net/context" |
) |
+// NamespaceAccessType specifies the type of namespace access that is being |
+// requested for WithProjectNamespace. |
+type NamespaceAccessType int |
+ |
+const ( |
+ // NamespaceAccessNoAuth grants unconditional access to a project's namespace. |
+ // This bypasses all ACL checks, and must only be used by service endpoints |
+ // that explicitly apply ACLs elsewhere. |
+ NamespaceAccessNoAuth NamespaceAccessType = iota |
+ |
+ // NamespaceAccessREAD enforces READ permission access to a project's |
+ // namespace. |
+ NamespaceAccessREAD |
+ |
+ // NamespaceAccessWRITE enforces WRITE permission access to a project's |
+ // namespace. |
+ NamespaceAccessWRITE |
+) |
+ |
type servicesKeyType int |
// WithServices installs the supplied Services instance into a Context. |
@@ -36,22 +55,9 @@ func GetServices(c context.Context) Services { |
// It will return an error if the project name or the project's namespace is |
// invalid. |
// |
-// If the current user does not have READ permission for the project, a |
+// If the current user does not have the requested permission for the project, a |
// MembershipError will be returned. |
-func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName) error { |
- return withProjectNamespaceImpl(c, project, true) |
-} |
- |
-// WithProjectNamespaceNoAuth sets the current namespace to the project name. It |
-// does NOT assert that the current user has project access. This should only be |
-// used for service functions that are not acting on behalf of a user. |
-// |
-// It will fail if the project name is invalid. |
-func WithProjectNamespaceNoAuth(c *context.Context, project luciConfig.ProjectName) error { |
- return withProjectNamespaceImpl(c, project, false) |
-} |
- |
-func withProjectNamespaceImpl(c *context.Context, project luciConfig.ProjectName, auth bool) error { |
+func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName, at NamespaceAccessType) error { |
ctx := *c |
// TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory. |
@@ -64,18 +70,37 @@ func withProjectNamespaceImpl(c *context.Context, project luciConfig.ProjectName |
return err |
} |
- // Validate the user's READ access to the named project, if authenticating. |
- if auth { |
+ // Validate the current user has the requested access. |
+ switch at { |
+ case NamespaceAccessNoAuth: |
+ break |
+ |
+ case NamespaceAccessREAD: |
+ pcfg, err := GetServices(ctx).ProjectConfig(ctx, project) |
+ if err != nil { |
+ log.WithError(err).Errorf(ctx, "Failed to load project config.") |
+ return err |
+ } |
+ |
+ if err := IsProjectReader(*c, pcfg); err != nil { |
+ log.WithError(err).Errorf(*c, "User denied READ access to requested project.") |
+ return err |
+ } |
+ |
+ case NamespaceAccessWRITE: |
pcfg, err := GetServices(ctx).ProjectConfig(ctx, project) |
if err != nil { |
log.WithError(err).Errorf(ctx, "Failed to load project config.") |
return err |
} |
- if err := IsProjectReader(ctx, pcfg); err != nil { |
- log.WithError(err).Errorf(ctx, "User cannot access requested project.") |
+ if err := IsProjectWriter(*c, pcfg); err != nil { |
+ log.WithError(err).Errorf(*c, "User denied WRITE access to requested project.") |
return err |
} |
+ |
+ default: |
+ return fmt.Errorf("unknown access type: %v", at) |
} |
pns := ProjectNamespace(project) |