Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: appengine/logdog/coordinator/context.go

Issue 1971493003: LogDog: Project READ access for user endpoints. (Closed) Base URL: https://github.com/luci/luci-go@logdog-project-service-config
Patch Set: Updated patchset dependency Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.
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 {
55 ctx := *c
56
54 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory . 57 // TODO(dnj): REQUIRE this to be non-empty once namespacing is mandatory .
55 if project == "" { 58 if project == "" {
56 log.Debugf(*c, "Using default namespace.")
57 return nil 59 return nil
58 } 60 }
59 61
60 if err := project.Validate(); err != nil { 62 if err := project.Validate(); err != nil {
61 » » log.Fields{ 63 » » log.WithError(err).Errorf(ctx, "Project name is invalid.")
62 » » » log.ErrorKey: err,
63 » » » "project": project,
64 » » }.Errorf(*c, "Project name is invalid.")
65 return err 64 return err
66 } 65 }
67 66
68 » // Validate the user's access to the named project, if authenticating. 67 » // Validate the user's READ access to the named project, if authenticati ng.
69 if auth { 68 if auth {
70 » » if err := config.AssertProjectAccess(*c, project); err != nil { 69 » » pcfg, err := GetServices(ctx).ProjectConfig(ctx, project)
71 » » » log.Fields{ 70 » » if err != nil {
72 » » » » log.ErrorKey: err, 71 » » » log.WithError(err).Errorf(ctx, "Failed to load project c onfig.")
73 » » » » "project": project, 72 » » » return err
74 » » » }.Errorf(*c, "User cannot access requested project.") 73 » » }
74
75 » » if err := IsProjectReader(ctx, pcfg); err != nil {
76 » » » log.WithError(err).Errorf(ctx, "User cannot access reque sted project.")
75 return err 77 return err
76 } 78 }
77 } 79 }
78 80
79 pns := ProjectNamespace(project) 81 pns := ProjectNamespace(project)
80 » nc, err := info.Get(*c).Namespace(pns) 82 » nc, err := info.Get(ctx).Namespace(pns)
81 if err != nil { 83 if err != nil {
82 log.Fields{ 84 log.Fields{
83 log.ErrorKey: err, 85 log.ErrorKey: err,
84 "project": project, 86 "project": project,
85 "namespace": pns, 87 "namespace": pns,
86 » » }.Errorf(*c, "Failed to set namespace.") 88 » » }.Errorf(ctx, "Failed to set namespace.")
87 return err 89 return err
88 } 90 }
89 91
90 log.Fields{
91 "project": project,
92 }.Debugf(*c, "Using project namespace.")
93 *c = nc 92 *c = nc
94 return nil 93 return nil
95 } 94 }
96 95
97 // Project returns the current project installed in the supplied Context's 96 // Project returns the current project installed in the supplied Context's
98 // namespace. 97 // namespace.
99 // 98 //
100 // This function is called with the expectation that the Context is in a 99 // 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 100 // namespace conforming to ProjectNamespace. If this is not the case, this
102 // method will panic. 101 // method will panic.
103 func Project(c context.Context) luciConfig.ProjectName { 102 func Project(c context.Context) luciConfig.ProjectName {
104 ns, _ := info.Get(c).GetNamespace() 103 ns, _ := info.Get(c).GetNamespace()
105 104
106 // TODO(dnj): Remove the empty namespace/project exception once we no lo nger 105 // TODO(dnj): Remove the empty namespace/project exception once we no lo nger
107 // support that. 106 // support that.
108 if ns == "" { 107 if ns == "" {
109 return "" 108 return ""
110 } 109 }
111 110
112 project := ProjectFromNamespace(ns) 111 project := ProjectFromNamespace(ns)
113 if project != "" { 112 if project != "" {
114 return project 113 return project
115 } 114 }
116 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix)) 115 panic(fmt.Errorf("current namespace %q does not begin with project names pace prefix (%q)", ns, projectNamespacePrefix))
117 } 116 }
OLDNEW
« no previous file with comments | « appengine/logdog/coordinator/config/projects.go ('k') | appengine/logdog/coordinator/coordinatorTest/context.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698