go-full-stack/lib/middleware/middleware.go
2024-12-09 18:04:39 -05:00

179 lines
3.9 KiB
Go

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)
}
}