package ext import ( "encoding/base64" "time" "git.sr.ht/~gabrielgio/img/pkg/components/user" "github.com/sirupsen/logrus" "github.com/valyala/fasthttp" ) func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { ctx.Response.Header.SetContentType("text/html") next(ctx) } } type LogMiddleware struct { entry *logrus.Entry } func NewLogMiddleare(log *logrus.Entry) *LogMiddleware { return &LogMiddleware{ entry: log, } } func (l *LogMiddleware) HTTP(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { start := time.Now() next(ctx) elapsed := time.Since(start) l.entry. WithField("time", elapsed). WithField("code", ctx.Response.StatusCode()). WithField("path", string(ctx.Path())). WithField("bytes", len(ctx.Response.Body())). Info(string(ctx.Request.Header.Method())) } } type AuthMiddleware struct { key []byte entry *logrus.Entry } func NewAuthMiddleware(key []byte, log *logrus.Entry) *AuthMiddleware { return &AuthMiddleware{ key: key, entry: log.WithField("context", "auth"), } } func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { path := string(ctx.Path()) if path == "/login" || path == "/initial" { next(ctx) return } redirectLogin := "/login?redirect=" + path authBase64 := ctx.Request.Header.Cookie("auth") if authBase64 == nil { a.entry.Info("No auth provided") ctx.Redirect(redirectLogin, 307) return } auth, err := base64.StdEncoding.DecodeString(string(authBase64)) if err != nil { a.entry.Error(err) return } token, err := ReadToken(auth, a.key) if err != nil { a.entry.Error(err) ctx.Redirect(redirectLogin, 307) return } ctx.SetUserValue("token", token) a.entry. WithField("userID", token.UserID). WithField("username", token.Username). Info("user recognized") next(ctx) } } type InitialSetupMiddleware struct { userRepository user.Repository } func NewInitialSetupMiddleware(userRepository user.Repository) *InitialSetupMiddleware { return &InitialSetupMiddleware{ userRepository: userRepository, } } func (i *InitialSetupMiddleware) Check(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { // if user has been set to context it is logged in already _, ok := ctx.UserValue("token").(*Token) if ok { next(ctx) return } path := string(ctx.Path()) if path == "/initial" { next(ctx) return } exists, err := i.userRepository.Any(ctx) if err != nil { InternalServerError(ctx, err) return } if exists { next(ctx) return } ctx.Redirect("/initial", 307) } }