From 1e45ae2ea3497958b2ea6a20137955cfc3bbc964 Mon Sep 17 00:00:00 2001 From: "Gabriel A. Giovanini" Date: Wed, 11 Dec 2024 17:05:12 +0100 Subject: feat: Add UI/Handler login process It adds the whole workflow to store and handle login on both UI and handler level. With that the login information should be available at any point given the context. --- pkg/ext/auth.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ pkg/ext/router.go | 18 ++++++++++++------ 2 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 pkg/ext/auth.go (limited to 'pkg/ext') diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go new file mode 100644 index 0000000..bb6c0a2 --- /dev/null +++ b/pkg/ext/auth.go @@ -0,0 +1,45 @@ +package ext + +import ( + "context" + "encoding/base64" + "log/slog" + "net/http" +) + +type authService interface { + ValidateToken(token []byte) (bool, error) +} + +func Authenticate(auth authService) func(next http.HandlerFunc) http.HandlerFunc { + return func(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("auth") + if err != nil { + slog.Error("Error loading cookie", "error", err) + next(w, r) + return + } + + value, err := base64.StdEncoding.DecodeString(cookie.Value) + if err != nil { + slog.Error("Error decoding", "error", err) + next(w, r) + return + } + + valid, err := auth.ValidateToken(value) + if err != nil { + slog.Error("Error validating token", "error", err, "cookie", cookie.Value) + next(w, r) + return + } + + ctx := r.Context() + ctx = context.WithValue(ctx, "logged", true) + + slog.Info("Validated token", "valid?", valid) + next(w, r.WithContext(ctx)) + } + } +} diff --git a/pkg/ext/router.go b/pkg/ext/router.go index 96da1c9..956254d 100644 --- a/pkg/ext/router.go +++ b/pkg/ext/router.go @@ -23,6 +23,7 @@ func NewRouter() *Router { router: http.NewServeMux(), } } + func (r *Router) Handler() http.Handler { return r.router } @@ -35,9 +36,9 @@ func wrapError(next ErrorRequestHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := next(w, r); err != nil { if errors.Is(err, service.ErrRepositoryNotFound) { - NotFound(w) + NotFound(w, r) } else { - InternalServerError(w, err) + InternalServerError(r, w, err) } } } @@ -57,16 +58,21 @@ func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) { r.router.HandleFunc(path, r.run(handler)) } -func NotFound(w http.ResponseWriter) { +func NotFound(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) templates.WritePageTemplate(w, &templates.ErrorPage{ Message: "Not Found", - }) + }, r.Context()) +} + +func Redirect(w http.ResponseWriter, location string) { + w.Header().Add("location", location) + w.WriteHeader(http.StatusTemporaryRedirect) } -func InternalServerError(w http.ResponseWriter, err error) { +func InternalServerError(r *http.Request, w http.ResponseWriter, err error) { w.WriteHeader(http.StatusInternalServerError) templates.WritePageTemplate(w, &templates.ErrorPage{ Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()), - }) + }, r.Context()) } -- cgit v1.2.3