From 80cd6d3d72c5fd76d4842a8d5cf303b003878454 Mon Sep 17 00:00:00 2001 From: Nicolas Duhamel Date: Tue, 26 Apr 2016 07:43:29 +0200 Subject: [PATCH] Add post login redirect --- auth/middleware.go | 49 ++++++++++++++++++++++++++++++++++++++-------- main.go | 8 +++++++- users/handlers.go | 13 ++++++++++-- web/env.go | 37 +++++++++++++++++++++++++--------- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/auth/middleware.go b/auth/middleware.go index 237e682..a52a29a 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -1,6 +1,7 @@ package auth import ( + "fmt" "net/http" "github.com/gorilla/context" @@ -8,9 +9,9 @@ import ( type key int -const ukey key = 0 +const ukey key = 0 //user key -// AuthMiddleware get User from session and put it in context +// Middleware get User from session and put it in context type Middleware struct { authorizer *Authorizer } @@ -29,25 +30,57 @@ func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http } type MiddlewareRole struct { - authorizer *Authorizer - role string + authorizer *Authorizer + role string + loginPageGetter func() string } -func NewMiddlewareRole(authorizer *Authorizer, role string) *MiddlewareRole { - return &MiddlewareRole{authorizer, role} +func NewMiddlewareRole(authorizer *Authorizer, loginPageGetter func() string, role string) *MiddlewareRole { + return &MiddlewareRole{authorizer, role, loginPageGetter} } func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { user := GetCurrentUser(r) if user == nil || !user.HasRole(m.role) { - //TODO: redirect to login page and save wanted page + cookie, err := m.authorizer.cookiejar.Get(r, "rlogin") + if err != nil { + panic(err) + } + cookie.Values["redirect"] = r.URL.Path + err = cookie.Save(r, w) + if err != nil { + panic(err) + } + http.Redirect(w, r, m.loginPageGetter(), http.StatusTemporaryRedirect) return } next(w, r) } +func GetPostLoginRedirect(a *Authorizer, w http.ResponseWriter, r *http.Request) (string, error) { + cookie, err := a.cookiejar.Get(r, "rlogin") + if err != nil { + return "", err + } + val := cookie.Values["redirect"] + if val == nil { + return "", nil + } + path, ok := val.(string) + if !ok { + return "", fmt.Errorf("invalid redirect type") + } + cookie.Values["rlogin"] = "" + err = cookie.Save(r, w) + if err != nil { + return "", err + } + return path, nil + +} + func GetCurrentUser(r *http.Request) User { u := context.Get(r, ukey) if u == nil { @@ -55,7 +88,7 @@ func GetCurrentUser(r *http.Request) User { } user, ok := u.(User) if !ok { - panic("Invalid user type") + panic("invalid user type") } return user } diff --git a/main.go b/main.go index 6f02535..3fdbb88 100644 --- a/main.go +++ b/main.go @@ -38,11 +38,17 @@ func main() { authMiddleware := auth.NewMiddleware(env.Auth) env.Handle("users.login", "/users/login", users.LoginHandler) - env.Handle("users.logout", "users/logout", users.LogoutHandler) + env.Handle("users.logout", "/users/logout", users.LogoutHandler) env.HandleRole("users.details", "/users/details", users.DetailsHandler, users.UserRole) env.HandleRole("movies.polochon", "/", movies.PolochonMovies, users.UserRole) + err = env.SetLoginRoute("users.login") + if err != nil { + log.Error(err) + os.Exit(1) + } + n := negroni.Classic() n.Use(authMiddleware) n.UseHandler(env.Router) diff --git a/users/handlers.go b/users/handlers.go index 91dc4cf..bc677b1 100644 --- a/users/handlers.go +++ b/users/handlers.go @@ -41,13 +41,22 @@ func LoginHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { return err } - //TODO: redirect to user details or to previous location + path, err := auth.GetPostLoginRedirect(e.Auth, w, r) + if err != nil { + return err + } + if path != "" { + http.Redirect(w, r, path, http.StatusTemporaryRedirect) + return nil + } + http.Redirect(w, r, "/", http.StatusTemporaryRedirect) return nil } func LogoutHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { e.Auth.Logout(w, r) - //TODO: redirect to login page + route := e.GetLoginRouteGetter()() + http.Redirect(w, r, route, http.StatusTemporaryRedirect) return nil } diff --git a/web/env.go b/web/env.go index 37d5c9e..1871d97 100644 --- a/web/env.go +++ b/web/env.go @@ -23,12 +23,13 @@ const ( // Env describes an environement object passed to all handlers type Env struct { - Database *sqlx.DB - Log *logrus.Entry - Router *mux.Router - Render *render.Render - Auth *auth.Authorizer - Mode Mode + Database *sqlx.DB + Log *logrus.Entry + Router *mux.Router + Render *render.Render + Auth *auth.Authorizer + Mode Mode + loginRoute string } // NewEnv returns a new *Env @@ -49,6 +50,15 @@ func NewEnv(db *sqlx.DB, auth *auth.Authorizer, log *logrus.Entry, templatesDir } } +func (e *Env) SetLoginRoute(name string) error { + route, err := e.GetURL(name) + if err != nil { + return err + } + e.loginRoute = route + return nil +} + // GetURL returns URL string from URL name and params // Usefull for redirection and templates func (e *Env) GetURL(name string, pairs ...string) (string, error) { @@ -66,14 +76,14 @@ func (e *Env) GetURL(name string, pairs ...string) (string, error) { type HandlerFunc func(e *Env, w http.ResponseWriter, r *http.Request) error func (e *Env) Handle(name, route string, H HandlerFunc) { - e.Router.Handle(route, Handler{e, H}) + e.Router.Handle(route, Handler{e, H}).Name(name) } func (e *Env) HandleRole(name, route string, H HandlerFunc, role string) { e.Router.Handle(route, negroni.New( - auth.NewMiddlewareRole(e.Auth, role), + auth.NewMiddlewareRole(e.Auth, e.GetLoginRouteGetter(), role), negroni.Wrap(Handler{e, H}), - )) + )).Name(name) } // The Handler struct that takes a configured Env and a function matching our @@ -94,3 +104,12 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.StatusInternalServerError) } } + +func (e *Env) GetLoginRouteGetter() func() string { + return func() string { + if e.loginRoute == "" { + panic("Env: login route not set") + } + return e.loginRoute + } +}