From dab68faac6937a908b58cc452ec12e12b105d1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Delattre?= Date: Sat, 5 Nov 2016 14:10:02 +0100 Subject: [PATCH] Fix the user context Let's use the context in go 1.7 instead of the gorilla package. While we're here, let's add some logs too. --- src/internal/auth/middleware.go | 53 +++++++++++++++++++++++++-------- src/internal/movies/handlers.go | 2 +- src/internal/users/handlers.go | 4 +-- src/internal/web/env.go | 4 +-- src/main.go | 11 +++++-- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/internal/auth/middleware.go b/src/internal/auth/middleware.go index 71af311..268ad45 100644 --- a/src/internal/auth/middleware.go +++ b/src/internal/auth/middleware.go @@ -1,23 +1,25 @@ package auth import ( + "context" "fmt" "net/http" - "github.com/gorilla/context" + "github.com/Sirupsen/logrus" ) -type key int - -const ukey key = 0 //user key - // Middleware get User from session and put it in context type Middleware struct { authorizer *Authorizer + log *logrus.Entry } -func NewMiddleware(authorizer *Authorizer) *Middleware { - return &Middleware{authorizer} +// NewMiddleware returns a new authentication middleware +func NewMiddleware(authorizer *Authorizer, log *logrus.Entry) *Middleware { + return &Middleware{ + authorizer: authorizer, + log: log.WithField("middleware", "auth"), + } } func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { @@ -25,24 +27,42 @@ func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http if err != nil { panic(err) } - context.Set(r, ukey, user) + + m.log.Debug("setting user in the context") + ctx := context.WithValue(r.Context(), "auth.user", user) + r = r.WithContext(ctx) + next(w, r) } +// MiddlewareRole handles the role checking for the current user type MiddlewareRole struct { authorizer *Authorizer + log *logrus.Entry role string loginPageGetter func() string } -func NewMiddlewareRole(authorizer *Authorizer, loginPageGetter func() string, role string) *MiddlewareRole { - return &MiddlewareRole{authorizer, role, loginPageGetter} +// NewMiddlewareRole returns a new MiddlewareRole +func NewMiddlewareRole(authorizer *Authorizer, log *logrus.Entry, loginPageGetter func() string, role string) *MiddlewareRole { + return &MiddlewareRole{ + authorizer: authorizer, + log: log.WithField("middleware", "role"), + role: role, + loginPageGetter: loginPageGetter, + } } func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - user := GetCurrentUser(r) + user := GetCurrentUser(r, m.log) if user == nil || !user.HasRole(m.role) { + if user == nil { + m.log.Debug("user is nil in the context") + } else { + m.log.Debug("user doesn't have the role") + } + cookie, err := m.authorizer.Cookiejar.Get(r, "rlogin") if err != nil { panic(err) @@ -56,9 +76,13 @@ func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next return } + m.log.Debug("user has the role, continuing") + next(w, r) } +// GetPostLoginRedirect returns the location of the page requested before the +// users was redirected to the login page func GetPostLoginRedirect(a *Authorizer, w http.ResponseWriter, r *http.Request) (string, error) { cookie, err := a.Cookiejar.Get(r, "rlogin") if err != nil { @@ -81,8 +105,11 @@ func GetPostLoginRedirect(a *Authorizer, w http.ResponseWriter, r *http.Request) } -func GetCurrentUser(r *http.Request) User { - u := context.Get(r, ukey) +// GetCurrentUser gets the current user from the request context +func GetCurrentUser(r *http.Request, log *logrus.Entry) User { + log.Debug("getting user from context") + + u := r.Context().Value("auth.user") if u == nil { return nil } diff --git a/src/internal/movies/handlers.go b/src/internal/movies/handlers.go index 238ff8a..0e66697 100644 --- a/src/internal/movies/handlers.go +++ b/src/internal/movies/handlers.go @@ -59,8 +59,8 @@ func getPolochonMovies(user *users.User) ([]*Movie, error) { } func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error { + v := auth.GetCurrentUser(r, env.Log) - v := auth.GetCurrentUser(r) user, ok := v.(*users.User) if !ok { return fmt.Errorf("invalid user type") diff --git a/src/internal/users/handlers.go b/src/internal/users/handlers.go index 598b748..a8fcf03 100644 --- a/src/internal/users/handlers.go +++ b/src/internal/users/handlers.go @@ -65,7 +65,7 @@ func LogoutHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { // DetailsHandler show user details func DetailsHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { - v := auth.GetCurrentUser(r) + v := auth.GetCurrentUser(r, e.Log) user, ok := v.(*User) if !ok { return fmt.Errorf("invalid user type") @@ -84,7 +84,7 @@ func DetailsHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { // EditHandler allow editing user info and configuration func EditHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { - v := auth.GetCurrentUser(r) + v := auth.GetCurrentUser(r, e.Log) user, ok := v.(*User) if !ok { return fmt.Errorf("invalid user type") diff --git a/src/internal/web/env.go b/src/internal/web/env.go index b235168..cabc99c 100644 --- a/src/internal/web/env.go +++ b/src/internal/web/env.go @@ -7,10 +7,10 @@ import ( "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/config" "github.com/Sirupsen/logrus" - "github.com/codegangsta/negroni" "github.com/gorilla/mux" "github.com/jmoiron/sqlx" "github.com/unrolled/render" + "github.com/urfave/negroni" ) // Env describes an environement object passed to all handlers @@ -76,7 +76,7 @@ func (r *Route) Methods(methods ...string) *Route { func (r *Route) WithRole(role string) *Route { handler := r.mRoute.GetHandler() newHandler := negroni.New( - auth.NewMiddlewareRole(r.env.Auth, r.env.GetLoginRouteGetter(), role), + auth.NewMiddlewareRole(r.env.Auth, r.env.Log, r.env.GetLoginRouteGetter(), role), negroni.Wrap(handler)) r.mRoute.Handler(newHandler) return r diff --git a/src/main.go b/src/main.go index 8dfd555..3da4738 100644 --- a/src/main.go +++ b/src/main.go @@ -17,10 +17,12 @@ import ( _ "github.com/lib/pq" ) +// UserBackend represents the data backend to get the user type UserBackend struct { Database *sqlx.DB } +// Get gets the username from the UserBackend func (b *UserBackend) Get(username string) (auth.User, error) { return users.Get(b.Database, username) } @@ -32,7 +34,12 @@ func main() { cfgPath = "./config.yml" } - log := logrus.NewEntry(logrus.New()) + // Setup the logger + logger := logrus.New() + logger.Formatter = &logrus.TextFormatter{FullTimestamp: true} + logger.Level = logrus.DebugLevel + + log := logrus.NewEntry(logger) cf, err := config.Load(cfgPath) if err != nil { log.Panic(err) @@ -60,7 +67,7 @@ func main() { Config: cf, }) - authMiddleware := auth.NewMiddleware(env.Auth) + authMiddleware := auth.NewMiddleware(env.Auth, log) env.Handle("/users/login", users.LoginGETHandler).Name("users.login").Methods("GET") env.Handle("/users/login", users.LoginPOSTHandler).Name("users.login").Methods("POST")