linstrom/server/middlewares.go
mstar b9eb4234f4 Fix passkey authentication
Also prep for better router layout
2024-10-15 16:16:18 +02:00

87 lines
2.1 KiB
Go

package server
import (
"context"
"net/http"
"slices"
"time"
"github.com/rs/zerolog/hlog"
"github.com/rs/zerolog/log"
"gitlab.com/mstarongitlab/goutils/other"
)
type HandlerBuilder func(http.Handler) http.Handler
func ChainMiddlewares(base http.Handler, links ...HandlerBuilder) http.Handler {
slices.Reverse(links)
for _, f := range links {
base = f(base)
}
return base
}
func ContextValsMiddleware(pairs map[any]any) HandlerBuilder {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
for key, val := range pairs {
ctx = context.WithValue(ctx, key, val)
}
newRequest := r.WithContext(ctx)
h.ServeHTTP(w, newRequest)
})
}
}
func LoggingMiddleware(handler http.Handler) http.Handler {
return ChainMiddlewares(handler,
hlog.NewHandler(log.Logger),
hlog.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
hlog.FromRequest(r).Info().
Str("method", r.Method).
Stringer("url", r.URL).
Int("status", status).
Int("size", size).
Dur("duration", duration).
Send()
}),
hlog.RemoteAddrHandler("ip"),
hlog.UserAgentHandler("user_agent"),
hlog.RefererHandler("referer"),
hlog.RequestIDHandler("req_id", "Request-Id"),
)
}
func passkeyIdToAccountIdTransformerMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s := StorageFromRequest(w, r)
if s == nil {
return
}
log := hlog.FromRequest(r)
passkeyId, ok := r.Context().Value(ContextKeyPasskeyUsername).(string)
if !ok {
other.HttpErr(
w,
HttpErrIdMissingContextValue,
"Actor name missing",
http.StatusInternalServerError,
)
return
}
log.Debug().Bytes("passkey-bytes", []byte(passkeyId)).Msg("Id from passkey auth")
acc, err := s.FindAccountByPasskeyId([]byte(passkeyId))
if err != nil {
other.HttpErr(
w,
HttpErrIdDbFailure,
"Failed to get account from storage",
http.StatusInternalServerError,
)
return
}
r = r.WithContext(context.WithValue(r.Context(), ContextKeyActorId, acc.ID))
handler.ServeHTTP(w, r)
})
}