Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package common | 5 package common |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "net/http" | 8 "net/http" |
| 9 "strings" | 9 "strings" |
| 10 | 10 |
| 11 "cloud.google.com/go/compute/metadata" | |
| 12 "cloud.google.com/go/datastore" | |
| 13 | |
| 11 "golang.org/x/net/context" | 14 "golang.org/x/net/context" |
| 15 "golang.org/x/oauth2" | |
| 16 "golang.org/x/oauth2/google" | |
| 12 | 17 |
| 18 "github.com/luci/gae/impl/cloud" | |
| 19 "github.com/luci/gae/impl/memory" | |
| 13 "github.com/luci/gae/service/info" | 20 "github.com/luci/gae/service/info" |
| 14 "github.com/luci/luci-go/appengine/gaeauth/server" | 21 "github.com/luci/luci-go/appengine/gaeauth/server" |
| 22 "github.com/luci/luci-go/appengine/gaeauth/server/gaesigner" | |
| 15 "github.com/luci/luci-go/appengine/gaemiddleware" | 23 "github.com/luci/luci-go/appengine/gaemiddleware" |
| 24 "github.com/luci/luci-go/appengine/gaesecrets" | |
| 16 "github.com/luci/luci-go/common/clock" | 25 "github.com/luci/luci-go/common/clock" |
| 26 "github.com/luci/luci-go/common/logging/gologger" | |
| 17 "github.com/luci/luci-go/server/analytics" | 27 "github.com/luci/luci-go/server/analytics" |
| 18 "github.com/luci/luci-go/server/auth" | 28 "github.com/luci/luci-go/server/auth" |
| 29 "github.com/luci/luci-go/server/auth/authdb" | |
| 19 "github.com/luci/luci-go/server/auth/identity" | 30 "github.com/luci/luci-go/server/auth/identity" |
| 20 "github.com/luci/luci-go/server/router" | 31 "github.com/luci/luci-go/server/router" |
| 21 "github.com/luci/luci-go/server/templates" | 32 "github.com/luci/luci-go/server/templates" |
| 22 ) | 33 ) |
| 23 | 34 |
| 24 // GetTemplateBundles is used to render HTML templates. It provides base args | 35 // GetTemplateBundles is used to render HTML templates. It provides base args |
| 25 // passed to all templates. | 36 // passed to all templates. |
| 26 func GetTemplateBundle() *templates.Bundle { | 37 func GetTemplateBundle() *templates.Bundle { |
| 27 return &templates.Bundle{ | 38 return &templates.Bundle{ |
| 28 Loader: templates.FileSystemLoader("templates"), | 39 Loader: templates.FileSystemLoader("templates"), |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 47 "LogoutURL": logoutURL, | 58 "LogoutURL": logoutURL, |
| 48 "CurrentTime": clock.Now(c), | 59 "CurrentTime": clock.Now(c), |
| 49 "Analytics": analytics.Snippet(c), | 60 "Analytics": analytics.Snippet(c), |
| 50 "RequestID": info.RequestID(c), | 61 "RequestID": info.RequestID(c), |
| 51 }, nil | 62 }, nil |
| 52 }, | 63 }, |
| 53 FuncMap: funcMap, | 64 FuncMap: funcMap, |
| 54 } | 65 } |
| 55 } | 66 } |
| 56 | 67 |
| 68 // authMethods returns the set of authentication methods used for Milo. | |
| 69 func authMethods() auth.Authenticator { | |
| 70 return auth.Authenticator{ | |
| 71 &server.OAuth2Method{Scopes: []string{server.EmailScope}}, | |
|
Vadim Sh.
2017/04/18 00:33:24
fyi: this doesn't work on Flex currently
hinoka
2017/04/21 22:12:41
I'll wait to rebase https://codereview.chromium.or
| |
| 72 server.CookieAuth, | |
| 73 &server.InboundAppIDAuthMethod{}, | |
|
Vadim Sh.
2017/04/18 00:33:24
nit: drop this, we don't actually use it, and it w
hinoka
2017/04/21 22:12:41
Same as above
| |
| 74 } | |
| 75 } | |
| 76 | |
| 77 // Flex returns the basic middleware for use on appengine flex. Flex does not | |
| 78 // allow the use of appengine APIs. | |
| 79 func FlexBase() router.MiddlewareChain { | |
| 80 // Get the name of this project from the metadata server, since we're on GCE. | |
| 81 project, err := metadata.Get("project/project-id") | |
| 82 if err != nil { | |
| 83 panic(err) | |
| 84 } | |
| 85 // Use the standard Go logger. | |
| 86 // TODO(hinoka): Use the cloud logger, somehow. | |
|
Vadim Sh.
2017/04/18 00:33:24
There's this: https://github.com/luci/luci-go/blob
hinoka
2017/04/21 22:12:41
Done.
| |
| 87 logger := func(c *router.Context, next router.Handler) { | |
| 88 c.Context = gologger.StdConfig.Use(c.Context) | |
| 89 next(c) | |
| 90 } | |
| 91 // The base set of services uses memory implementations. | |
| 92 memory := func(c *router.Context, next router.Handler) { | |
| 93 c.Context = memory.UseWithAppID(c.Context, project) | |
|
Vadim Sh.
2017/04/18 00:33:24
hm... This looks dangerous. Most services there ar
hinoka
2017/04/21 22:12:41
Addressing in https://codereview.chromium.org/2829
| |
| 94 next(c) | |
| 95 } | |
| 96 // Use the cloud datastore client. | |
| 97 ds := func(c *router.Context, next router.Handler) { | |
| 98 client, err := datastore.NewClient(c.Context, project) | |
| 99 if err != nil { | |
| 100 panic(err) | |
| 101 } | |
| 102 c.Context = cloud.UseDatastore(c.Context, client) | |
| 103 next(c) | |
| 104 } | |
| 105 // Secret store, used for decryping OID tokens, which is needed for cook ieauth. | |
| 106 secrets := func(c *router.Context, next router.Handler) { | |
| 107 c.Context = gaesecrets.Use(c.Context, nil) | |
| 108 next(c) | |
| 109 } | |
| 110 // Swap out the default auth configs with one that uses a in-memory cach e, since | |
| 111 // we can't use memcache. | |
| 112 authConfig := func(c *router.Context, next router.Handler) { | |
| 113 mustToken := func(c context.Context, scopes []string) (*oauth2.T oken, error) { | |
| 114 // Ignore context and scope since its not needed. | |
| 115 return google.ComputeTokenSource("").Token() | |
| 116 } | |
| 117 config := auth.Config{ | |
| 118 DBProvider: authdb.NewDBCache(server.GetAuthDB) , | |
|
Vadim Sh.
2017/04/18 00:33:24
'config' variable should be global. It is stateful
hinoka
2017/04/21 22:12:41
Moved to init()
| |
| 119 Signer: gaesigner.Signer{}, | |
|
Vadim Sh.
2017/04/18 00:33:24
fyi: this will not work, but milo isn't signing an
hinoka
2017/04/21 22:12:41
Acknowledged.
| |
| 120 AccessTokenProvider: mustToken, | |
| 121 AnonymousTransport: func(c context.Context) http.RoundTr ipper { | |
| 122 return http.DefaultTransport | |
| 123 }, | |
| 124 Cache: auth.MemoryCache(10), | |
|
Vadim Sh.
2017/04/18 00:33:24
nit: 1000 or something
we have gigs of ram on Flex
hinoka
2017/04/21 22:12:41
Done.
| |
| 125 IsDevMode: false, | |
| 126 } | |
| 127 c.Context = auth.SetConfig(c.Context, config) | |
| 128 next(c) | |
| 129 } | |
| 130 // Now chain it all together! | |
| 131 return router.NewMiddlewareChain( | |
| 132 logger, memory, ds, secrets, auth.Use(authMethods()), authConfig , auth.Authenticate) | |
|
Vadim Sh.
2017/04/18 00:33:24
I think authConfig should be before auth.Use(...)
hinoka
2017/04/21 22:12:41
Done.
| |
| 133 } | |
| 134 | |
| 57 // Base returns the basic LUCI appengine middlewares. | 135 // Base returns the basic LUCI appengine middlewares. |
| 58 func Base() router.MiddlewareChain { | 136 func Base() router.MiddlewareChain { |
| 59 » methods := auth.Authenticator{ | 137 » m := gaemiddleware.BaseProd().Extend(auth.Use(authMethods()), auth.Authe nticate) |
| 60 » » &server.OAuth2Method{Scopes: []string{server.EmailScope}}, | |
| 61 » » server.CookieAuth, | |
| 62 » » &server.InboundAppIDAuthMethod{}, | |
| 63 » } | |
| 64 » m := gaemiddleware.BaseProd().Extend(auth.Use(methods), auth.Authenticat e) | |
| 65 m = m.Extend(withRequestMiddleware) | 138 m = m.Extend(withRequestMiddleware) |
| 66 m = m.Extend(templates.WithTemplates(GetTemplateBundle())) | 139 m = m.Extend(templates.WithTemplates(GetTemplateBundle())) |
| 67 return m | 140 return m |
| 68 } | 141 } |
| 69 | 142 |
| 70 // The context key, so that we can embed the http.Request object into | 143 // The context key, so that we can embed the http.Request object into |
| 71 // the context. | 144 // the context. |
| 72 var requestKey = "http.request" | 145 var requestKey = "http.request" |
| 73 | 146 |
| 74 // WithRequest returns a context with the http.Request object | 147 // WithRequest returns a context with the http.Request object |
| 75 // in it. | 148 // in it. |
| 76 func WithRequest(c context.Context, r *http.Request) context.Context { | 149 func WithRequest(c context.Context, r *http.Request) context.Context { |
| 77 return context.WithValue(c, &requestKey, r) | 150 return context.WithValue(c, &requestKey, r) |
| 78 } | 151 } |
| 79 | 152 |
| 80 // withRequestMiddleware is a middleware that installs a request into the contex t. | 153 // withRequestMiddleware is a middleware that installs a request into the contex t. |
| 81 // This is used for various things in the default template. | 154 // This is used for various things in the default template. |
| 82 func withRequestMiddleware(c *router.Context, next router.Handler) { | 155 func withRequestMiddleware(c *router.Context, next router.Handler) { |
| 83 c.Context = WithRequest(c.Context, c.Request) | 156 c.Context = WithRequest(c.Context, c.Request) |
| 84 next(c) | 157 next(c) |
| 85 } | 158 } |
| 86 | 159 |
| 87 func getRequest(c context.Context) *http.Request { | 160 func getRequest(c context.Context) *http.Request { |
| 88 if req, ok := c.Value(&requestKey).(*http.Request); ok { | 161 if req, ok := c.Value(&requestKey).(*http.Request); ok { |
| 89 return req | 162 return req |
| 90 } | 163 } |
| 91 panic("No http.request found in context") | 164 panic("No http.request found in context") |
| 92 } | 165 } |
| OLD | NEW |