package middleware import ( "fmt" "net/http" "os" "git.markbailey.dev/cerbervs/ptpp/app/session" "git.markbailey.dev/cerbervs/ptpp/util" "git.markbailey.dev/cerbervs/ptpp/lib/logger" ) type IRouterCtx interface { GetRouteByName(string) (string, error) } type IMiddlewareCtx interface { GetRouteByName(string) string } type MiddlewareCtx struct { RouterCtx IRouterCtx } func (m MiddlewareCtx) GetRouteByName(name string) string { path, err := m.RouterCtx.GetRouteByName(name) if err != nil { panic(err) } return path } type Func func(http.Handler, IMiddlewareCtx) http.Handler var sess session.IManager func Compose(xs []Func) Func { return func(next http.Handler, m IMiddlewareCtx) http.Handler { for i := len(xs) - 1; i >= 0; i-- { x := xs[i] next = x(next, m) } return next } } func DontPanic(next http.Handler, m IMiddlewareCtx) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r != nil { http.Error(w, fmt.Sprintf("%v", r), http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } func WithLogger(next http.Handler, m IMiddlewareCtx) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handlerSess := sess.SessionStart(w, r) username, ok := handlerSess.Get("username").(string) if !ok { username = "" } username = "(username " + username + ")" ipAddr := r.Header.Get("X-Real-IP") if ipAddr == "" { ipAddr = r.Header.Get("X-Forwarded-For") } if ipAddr == "" { ipAddr = r.RemoteAddr } handlerLogger := logger.NewCompositeLogger() output := fmt.Sprintf( "%s Request sent from %s to %s %s", r.Method, ipAddr, r.URL.Path, username, ) handlerLogger.Info(output) next.ServeHTTP(w, r) }) } func WithAuth(next http.Handler, m IMiddlewareCtx) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ( claims *util.CustomClaims cookie *http.Cookie err error token string handlerSess = sess.SessionStart(w, r) ) if handlerSess.Get("username") != nil { req := util.AddValuesToRequestContext(r, map[any]any{ "username": handlerSess.Get("username"), }) next.ServeHTTP(w, req) return } if cookie, err = r.Cookie("token"); err != nil { _ = util.Redirect(w, r, m.GetRouteByName("app.user.sign_in"), http.StatusPermanentRedirect, true) return } if token = cookie.Value; token == "" { _ = util.Redirect(w, r, m.GetRouteByName("app.user.sign_in"), http.StatusPermanentRedirect, true) return } if claims, err = util.ParseToken(token, os.Getenv("TOKEN_SECRET")); err != nil { _ = util.Redirect(w, r, m.GetRouteByName("app.user.sign_in"), http.StatusPermanentRedirect, true) return } req := util.AddValuesToRequestContext(r, map[any]any{ "username": claims.Username, }) next.ServeHTTP(w, req) }) } func WithUsername(next http.Handler, m IMiddlewareCtx) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ( claims *util.CustomClaims cookie *http.Cookie err error token string handlerSess = sess.SessionStart(w, r) ) if handlerSess.Get("username") != nil { req := util.AddValuesToRequestContext(r, map[any]any{ "username": handlerSess.Get("username"), }) next.ServeHTTP(w, req) return } var uname *string if cookie, err = r.Cookie("token"); err == nil { if token = cookie.Value; token == "" { uname = nil } if claims, err = util.ParseToken(token, os.Getenv("TOKEN_SECRET")); err != nil { uname = nil } uname = &claims.Username } if uname != nil { req := util.AddValuesToRequestContext(r, map[any]any{ "username": uname, }) next.ServeHTTP(w, req) return } next.ServeHTTP(w, r) }) } func init() { var err error sess, err = session.NewManager("memory", "ptpp", 3600) if err != nil { panic(err) } }