OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package coordinator | 5 package coordinator |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 | 9 |
10 "github.com/luci/gae/service/info" | 10 "github.com/luci/gae/service/info" |
11 luciConfig "github.com/luci/luci-go/common/config" | 11 luciConfig "github.com/luci/luci-go/common/config" |
12 log "github.com/luci/luci-go/common/logging" | 12 log "github.com/luci/luci-go/common/logging" |
13 "golang.org/x/net/context" | 13 "golang.org/x/net/context" |
14 ) | 14 ) |
15 | 15 |
16 // NamespaceAccessType specifies the type of namespace access that is being | |
17 // requested for WithProjectNamespace. | |
18 type NamespaceAccessType int | |
19 | |
20 const ( | |
21 // NamespaceAccessNoAuth grants unconditional access to a project's name space. | |
nodir
2016/05/19 16:43:17
please clarify that this simply skips the check
dnj (Google)
2016/05/19 22:52:04
Done.
| |
22 // | |
23 // This must only be used by endpoints that enforce admin- or service-on ly | |
24 // access. | |
25 NamespaceAccessNoAuth NamespaceAccessType = iota | |
26 | |
27 // NamespaceAccessREAD enforces READ permission access to a project's | |
28 // namespace. | |
29 NamespaceAccessREAD | |
30 | |
31 // NamespaceAccessWRITE enforces WRITE permission access to a project's | |
32 // namespace. | |
33 NamespaceAccessWRITE | |
34 ) | |
35 | |
16 type servicesKeyType int | 36 type servicesKeyType int |
17 | 37 |
18 // WithServices installs the supplied Services instance into a Context. | 38 // WithServices installs the supplied Services instance into a Context. |
19 func WithServices(c context.Context, s Services) context.Context { | 39 func WithServices(c context.Context, s Services) context.Context { |
20 return context.WithValue(c, servicesKeyType(0), s) | 40 return context.WithValue(c, servicesKeyType(0), s) |
21 } | 41 } |
22 | 42 |
23 // GetServices gets the Services instance installed in the supplied Context. | 43 // GetServices gets the Services instance installed in the supplied Context. |
24 // | 44 // |
25 // If no Services has been installed, it will panic. | 45 // If no Services has been installed, it will panic. |
26 func GetServices(c context.Context) Services { | 46 func GetServices(c context.Context) Services { |
27 s, ok := c.Value(servicesKeyType(0)).(Services) | 47 s, ok := c.Value(servicesKeyType(0)).(Services) |
28 if !ok { | 48 if !ok { |
29 panic("no Services instance is installed") | 49 panic("no Services instance is installed") |
30 } | 50 } |
31 return s | 51 return s |
32 } | 52 } |
33 | 53 |
34 // WithProjectNamespace sets the current namespace to the project name. | 54 // WithProjectNamespace sets the current namespace to the project name. |
35 // | 55 // |
36 // It will return an error if the project name or the project's namespace is | 56 // It will return an error if the project name or the project's namespace is |
37 // invalid | 57 // invalid |
38 // | 58 // |
39 // If the current user does not have READ permission for the project, a | 59 // If the current user does not have READ permission for the project, a |
40 // MembershipError will be returned. | 60 // MembershipError will be returned. |
nodir
2016/05/19 16:43:17
this comment needs an update
dnj (Google)
2016/05/19 22:52:04
Done.
| |
41 func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName) er ror { | 61 func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName, at NamespaceAccessType) error { |
42 » return withProjectNamespaceImpl(c, project, true) | |
43 } | |
44 | |
45 // WithProjectNamespaceNoAuth sets the current namespace to the project name. It | |
46 // does NOT assert that the current user has project access. This should only be | |
47 // used for service functions that are not acting on behalf of a user. | |
48 // | |
49 // It will fail if the project name is invalid. | |
50 func WithProjectNamespaceNoAuth(c *context.Context, project luciConfig.ProjectNa me) error { | |
51 » return withProjectNamespaceImpl(c, project, false) | |
52 } | |
53 | |
54 func withProjectNamespaceImpl(c *context.Context, project luciConfig.ProjectName , auth bool) error { | |
55 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory . | 62 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory . |
56 if project == "" { | 63 if project == "" { |
57 return nil | 64 return nil |
58 } | 65 } |
59 | 66 |
60 if err := project.Validate(); err != nil { | 67 if err := project.Validate(); err != nil { |
61 log.WithError(err).Errorf(*c, "Project name is invalid.") | 68 log.WithError(err).Errorf(*c, "Project name is invalid.") |
62 return err | 69 return err |
63 } | 70 } |
64 | 71 |
65 » // Validate the user's READ access to the named project, if authenticati ng. | 72 » // Validate the current user has the requested access. |
66 » if auth { | 73 » switch at { |
74 » case NamespaceAccessNoAuth: | |
75 » » break | |
76 | |
77 » case NamespaceAccessREAD: | |
67 if err := IsProjectReader(*c, project); err != nil { | 78 if err := IsProjectReader(*c, project); err != nil { |
68 » » » log.WithError(err).Errorf(*c, "User cannot access reques ted project.") | 79 » » » log.WithError(err).Errorf(*c, "User denied READ access t o requested project.") |
69 return err | 80 return err |
70 } | 81 } |
82 | |
83 case NamespaceAccessWRITE: | |
84 if err := IsProjectWriter(*c, project); err != nil { | |
85 log.WithError(err).Errorf(*c, "User denied WRITE access to requested project.") | |
86 return err | |
87 } | |
88 | |
89 default: | |
90 return fmt.Errorf("unknown access type: %v", at) | |
71 } | 91 } |
72 | 92 |
73 pns := ProjectNamespace(project) | 93 pns := ProjectNamespace(project) |
74 nc, err := info.Get(*c).Namespace(pns) | 94 nc, err := info.Get(*c).Namespace(pns) |
nodir
2016/05/19 16:43:17
please add a check that namespace is not set alrea
dnj (Google)
2016/05/19 22:52:04
That's allowed. This function only enters namespac
nodir
2016/05/25 17:34:05
Acknowledged.
| |
75 if err != nil { | 95 if err != nil { |
76 log.Fields{ | 96 log.Fields{ |
77 log.ErrorKey: err, | 97 log.ErrorKey: err, |
78 "project": project, | 98 "project": project, |
79 "namespace": pns, | 99 "namespace": pns, |
80 }.Errorf(*c, "Failed to set namespace.") | 100 }.Errorf(*c, "Failed to set namespace.") |
81 return err | 101 return err |
82 } | 102 } |
83 | 103 |
84 *c = nc | 104 *c = nc |
(...skipping 14 matching lines...) Expand all Loading... | |
99 if ns == "" { | 119 if ns == "" { |
100 return "" | 120 return "" |
101 } | 121 } |
102 | 122 |
103 project := ProjectFromNamespace(ns) | 123 project := ProjectFromNamespace(ns) |
104 if project != "" { | 124 if project != "" { |
105 return project | 125 return project |
106 } | 126 } |
107 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix)) | 127 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix)) |
108 } | 128 } |
OLD | NEW |