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 "github.com/luci/luci-go/appengine/logdog/coordinator/config" | |
12 luciConfig "github.com/luci/luci-go/common/config" | 11 luciConfig "github.com/luci/luci-go/common/config" |
13 log "github.com/luci/luci-go/common/logging" | 12 log "github.com/luci/luci-go/common/logging" |
14 "golang.org/x/net/context" | 13 "golang.org/x/net/context" |
15 ) | 14 ) |
16 | 15 |
17 type servicesKeyType int | 16 type servicesKeyType int |
18 | 17 |
19 // WithServices installs the supplied Services instance into a Context. | 18 // WithServices installs the supplied Services instance into a Context. |
20 func WithServices(c context.Context, s Services) context.Context { | 19 func WithServices(c context.Context, s Services) context.Context { |
21 return context.WithValue(c, servicesKeyType(0), s) | 20 return context.WithValue(c, servicesKeyType(0), s) |
22 } | 21 } |
23 | 22 |
24 // GetServices gets the Services instance installed in the supplied Context. | 23 // GetServices gets the Services instance installed in the supplied Context. |
25 // | 24 // |
26 // If no Services has been installed, it will panic. | 25 // If no Services has been installed, it will panic. |
27 func GetServices(c context.Context) Services { | 26 func GetServices(c context.Context) Services { |
28 s, ok := c.Value(servicesKeyType(0)).(Services) | 27 s, ok := c.Value(servicesKeyType(0)).(Services) |
29 if !ok { | 28 if !ok { |
30 panic("no Services instance is installed") | 29 panic("no Services instance is installed") |
31 } | 30 } |
32 return s | 31 return s |
33 } | 32 } |
34 | 33 |
35 // WithProjectNamespace sets the current namespace to the project name. | 34 // WithProjectNamespace sets the current namespace to the project name. |
36 // | 35 // |
37 // It will fail if either the project name or the project's namespace is | 36 // It will return an error if the project name or the project's namespace is |
38 // invalid. In the event of an error, the supplied Context will be not be | 37 // invalid |
nodir
2016/05/19 00:38:58
period missing
dnj (Google)
2016/05/19 16:12:34
Done.
| |
39 // modified or invalidated. | 38 // |
39 // If the current user does not have READ permission for the project, a | |
40 // MembershipError will be returned. | |
40 func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName) er ror { | 41 func WithProjectNamespace(c *context.Context, project luciConfig.ProjectName) er ror { |
41 return withProjectNamespaceImpl(c, project, true) | 42 return withProjectNamespaceImpl(c, project, true) |
42 } | 43 } |
43 | 44 |
44 // WithProjectNamespaceNoAuth sets the current namespace to the project name. It | 45 // WithProjectNamespaceNoAuth sets the current namespace to the project name. It |
45 // does NOT assert that the current user has project access. This should only be | 46 // does NOT assert that the current user has project access. This should only be |
46 // used for service functions that are not acting on behalf of a user. | 47 // used for service functions that are not acting on behalf of a user. |
47 // | 48 // |
48 // It will fail if the project name is invalid. | 49 // It will fail if the project name is invalid. |
49 func WithProjectNamespaceNoAuth(c *context.Context, project luciConfig.ProjectNa me) error { | 50 func WithProjectNamespaceNoAuth(c *context.Context, project luciConfig.ProjectNa me) error { |
50 return withProjectNamespaceImpl(c, project, false) | 51 return withProjectNamespaceImpl(c, project, false) |
51 } | 52 } |
52 | 53 |
53 func withProjectNamespaceImpl(c *context.Context, project luciConfig.ProjectName , auth bool) error { | 54 func withProjectNamespaceImpl(c *context.Context, project luciConfig.ProjectName , auth bool) error { |
54 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory . | 55 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory . |
55 if project == "" { | 56 if project == "" { |
56 log.Debugf(*c, "Using default namespace.") | |
57 return nil | 57 return nil |
58 } | 58 } |
59 | 59 |
60 if err := project.Validate(); err != nil { | 60 if err := project.Validate(); err != nil { |
61 » » log.Fields{ | 61 » » log.WithError(err).Errorf(*c, "Project name is invalid.") |
62 » » » log.ErrorKey: err, | |
63 » » » "project": project, | |
64 » » }.Errorf(*c, "Project name is invalid.") | |
65 return err | 62 return err |
66 } | 63 } |
67 | 64 |
68 » // Validate the user's access to the named project, if authenticating. | 65 » // Validate the user's READ access to the named project, if authenticati ng. |
69 if auth { | 66 if auth { |
70 » » if err := config.AssertProjectAccess(*c, project); err != nil { | 67 » » if err := IsProjectReader(*c, project); err != nil { |
71 » » » log.Fields{ | 68 » » » log.WithError(err).Errorf(*c, "User cannot access reques ted project.") |
72 » » » » log.ErrorKey: err, | |
73 » » » » "project": project, | |
74 » » » }.Errorf(*c, "User cannot access requested project.") | |
75 return err | 69 return err |
76 } | 70 } |
77 } | 71 } |
78 | 72 |
79 pns := ProjectNamespace(project) | 73 pns := ProjectNamespace(project) |
80 nc, err := info.Get(*c).Namespace(pns) | 74 nc, err := info.Get(*c).Namespace(pns) |
81 if err != nil { | 75 if err != nil { |
82 log.Fields{ | 76 log.Fields{ |
83 log.ErrorKey: err, | 77 log.ErrorKey: err, |
84 "project": project, | 78 "project": project, |
85 "namespace": pns, | 79 "namespace": pns, |
86 }.Errorf(*c, "Failed to set namespace.") | 80 }.Errorf(*c, "Failed to set namespace.") |
87 return err | 81 return err |
88 } | 82 } |
89 | 83 |
90 log.Fields{ | |
91 "project": project, | |
92 }.Debugf(*c, "Using project namespace.") | |
93 *c = nc | 84 *c = nc |
94 return nil | 85 return nil |
95 } | 86 } |
96 | 87 |
97 // Project returns the current project installed in the supplied Context's | 88 // Project returns the current project installed in the supplied Context's |
98 // namespace. | 89 // namespace. |
99 // | 90 // |
100 // This function is called with the expectation that the Context is in a | 91 // This function is called with the expectation that the Context is in a |
101 // namespace conforming to ProjectNamespace. If this is not the case, this | 92 // namespace conforming to ProjectNamespace. If this is not the case, this |
102 // method will panic. | 93 // method will panic. |
103 func Project(c context.Context) luciConfig.ProjectName { | 94 func Project(c context.Context) luciConfig.ProjectName { |
104 ns, _ := info.Get(c).GetNamespace() | 95 ns, _ := info.Get(c).GetNamespace() |
105 | 96 |
106 // TODO(dnj): Remove the empty namespace/project exception once we no lo nger | 97 // TODO(dnj): Remove the empty namespace/project exception once we no lo nger |
107 // support that. | 98 // support that. |
108 if ns == "" { | 99 if ns == "" { |
109 return "" | 100 return "" |
110 } | 101 } |
111 | 102 |
112 project := ProjectFromNamespace(ns) | 103 project := ProjectFromNamespace(ns) |
113 if project != "" { | 104 if project != "" { |
114 return project | 105 return project |
115 } | 106 } |
116 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix)) | 107 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix)) |
117 } | 108 } |
OLD | NEW |