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

Side by Side Diff: server/settings/admin/handlers.go

Issue 2043423004: Make HTTP middleware easier to use (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Rebase origin/master Created 4 years, 6 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 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 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 admin implements HTTP routes for settings UI. 5 // Package admin implements HTTP routes for settings UI.
6 package admin 6 package admin
7 7
8 import ( 8 import (
9 "html/template" 9 "html/template"
10 "net" 10 "net"
11 "net/http" 11 "net/http"
12 12
13 "github.com/julienschmidt/httprouter"
14 "golang.org/x/net/context" 13 "golang.org/x/net/context"
15 14
16 "github.com/luci/luci-go/common/errors" 15 "github.com/luci/luci-go/common/errors"
17 16
18 "github.com/luci/luci-go/server/auth" 17 "github.com/luci/luci-go/server/auth"
19 "github.com/luci/luci-go/server/auth/identity" 18 "github.com/luci/luci-go/server/auth/identity"
20 "github.com/luci/luci-go/server/auth/xsrf" 19 "github.com/luci/luci-go/server/auth/xsrf"
21 » "github.com/luci/luci-go/server/middleware" 20 » "github.com/luci/luci-go/server/router"
22 "github.com/luci/luci-go/server/templates" 21 "github.com/luci/luci-go/server/templates"
23 22
24 "github.com/luci/luci-go/server/settings/admin/internal/assets" 23 "github.com/luci/luci-go/server/settings/admin/internal/assets"
25 ) 24 )
26 25
27 // InstallHandlers installs HTTP handlers that implement admin UI. 26 // InstallHandlers installs HTTP handlers that implement admin UI.
28 // 27 //
29 // `adminAuth` is the method that will be used to authenticate the access 28 // `adminAuth` is the method that will be used to authenticate the access
30 // (regardless of what's installed in the base context). It must be able to 29 // (regardless of what's installed in the base context). It must be able to
31 // distinguish admins (aka superusers) from non-admins. It is needed because 30 // distinguish admins (aka superusers) from non-admins. It is needed because
32 // settings UI must be usable even before auth system is configured. 31 // settings UI must be usable even before auth system is configured.
33 func InstallHandlers(r *httprouter.Router, base middleware.Base, adminAuth auth. Method) { 32 func InstallHandlers(r *router.Router, base router.MiddlewareChain, adminAuth au th.Method) {
34 tmpl := &templates.Bundle{ 33 tmpl := &templates.Bundle{
35 Loader: templates.AssetsLoader(assets.Assets()), 34 Loader: templates.AssetsLoader(assets.Assets()),
36 DefaultTemplate: "base", 35 DefaultTemplate: "base",
37 FuncMap: template.FuncMap{ 36 FuncMap: template.FuncMap{
38 "includeCSS": func(name string) template.CSS { 37 "includeCSS": func(name string) template.CSS {
39 return template.CSS(assets.GetAsset(name)) 38 return template.CSS(assets.GetAsset(name))
40 }, 39 },
41 }, 40 },
42 DefaultArgs: func(c context.Context) (templates.Args, error) { 41 DefaultArgs: func(c context.Context) (templates.Args, error) {
43 logoutURL, err := auth.LogoutURL(c, "/") 42 logoutURL, err := auth.LogoutURL(c, "/")
44 if err != nil { 43 if err != nil {
45 return nil, err 44 return nil, err
46 } 45 }
47 return templates.Args{ 46 return templates.Args{
48 "Email": auth.CurrentUser(c).Email, 47 "Email": auth.CurrentUser(c).Email,
49 "LogoutURL": logoutURL, 48 "LogoutURL": logoutURL,
50 }, nil 49 }, nil
51 }, 50 },
52 } 51 }
53 52
54 adminDB := adminBypassDB{ 53 adminDB := adminBypassDB{
55 auth.ErroringDB{ 54 auth.ErroringDB{
56 Error: errors.New("admin: unexpected call to auth.DB on admin page"), 55 Error: errors.New("admin: unexpected call to auth.DB on admin page"),
57 }, 56 },
58 } 57 }
59 58
60 » wrap := func(h middleware.Handler) httprouter.Handle { 59 » rr := r.Subrouter("/admin/settings")
61 » » h = adminOnly(h) 60 » rr.Use(append(
Vadim Sh. 2016/06/18 16:57:20 I think it should be in reverse now? base, // bas
nishanths 2016/06/19 02:47:02 You're right. Done.
62 » » h = auth.WithDB(h, func(c context.Context) (auth.DB, error) { 61 » » base,
62 » » auth.Autologin,
63 » » adminOnly,
64 » » auth.WithDB(func(c context.Context) (auth.DB, error) {
63 return adminDB, nil 65 return adminDB, nil
64 » » }) 66 » » }),
65 » » h = auth.Use(h, auth.Authenticator{adminAuth}) 67 » » auth.Use(auth.Authenticator{adminAuth}),
66 » » h = templates.WithTemplates(h, tmpl) 68 » » templates.WithTemplates(tmpl),
67 » » return base(h) 69 » ))
68 » }
69 70
70 » r.GET("/admin/settings", wrap(indexPage)) 71 » rr.GET("/", nil, indexPage)
nishanths 2016/06/19 02:47:02 This change expects that clients follow redirects.
nishanths 2016/06/20 15:14:29 Changed in Patch Set 33.
71 » r.GET("/admin/settings/:SettingsKey", wrap(settingsPageGET)) 72 » rr.GET("/:SettingsKey", nil, settingsPageGET)
72 » r.POST("/admin/settings/:SettingsKey", wrap(xsrf.WithTokenCheck(settings PagePOST))) 73 » rr.POST("/:SettingsKey", router.MiddlewareChain{xsrf.WithTokenCheck}, se ttingsPagePOST)
73 } 74 }
74 75
75 // replyError sends HTML error page with status 500 on transient errors or 400 76 // replyError sends HTML error page with status 500 on transient errors or 400
76 // on fatal ones. 77 // on fatal ones.
77 func replyError(c context.Context, rw http.ResponseWriter, err error) { 78 func replyError(c context.Context, rw http.ResponseWriter, err error) {
78 if errors.IsTransient(err) { 79 if errors.IsTransient(err) {
79 rw.WriteHeader(http.StatusInternalServerError) 80 rw.WriteHeader(http.StatusInternalServerError)
80 } else { 81 } else {
81 rw.WriteHeader(http.StatusBadRequest) 82 rw.WriteHeader(http.StatusBadRequest)
82 } 83 }
(...skipping 18 matching lines...) Expand all
101 return "", nil 102 return "", nil
102 } 103 }
103 104
104 func (adminBypassDB) IsInWhitelist(c context.Context, ip net.IP, whitelist strin g) (bool, error) { 105 func (adminBypassDB) IsInWhitelist(c context.Context, ip net.IP, whitelist strin g) (bool, error) {
105 return false, nil 106 return false, nil
106 } 107 }
107 108
108 // adminOnly is middleware that ensures authenticated user is local site admin 109 // adminOnly is middleware that ensures authenticated user is local site admin
109 // aka superuser. On GAE it grants access only to users that have Editor or 110 // aka superuser. On GAE it grants access only to users that have Editor or
110 // Owner roles in the Cloud Project. 111 // Owner roles in the Cloud Project.
111 func adminOnly(h middleware.Handler) middleware.Handler { 112 func adminOnly(c *router.Context, next router.Handler) {
112 » return auth.Autologin(func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) { 113 » if !auth.CurrentUser(c.Context).Superuser {
nishanths 2016/06/19 02:47:02 Note: auth.Autologin is not coupled with adminOnly
113 » » if !auth.CurrentUser(c).Superuser { 114 » » c.Writer.WriteHeader(http.StatusForbidden)
114 » » » rw.WriteHeader(http.StatusForbidden) 115 » » templates.MustRender(c.Context, c.Writer, "pages/access_denied.h tml", nil)
115 » » » templates.MustRender(c, rw, "pages/access_denied.html", nil) 116 » » return
116 » » » return 117 » }
117 » » } 118 » next(c)
118 » » h(c, rw, r, p)
119 » })
120 } 119 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698