shelves/internal/httpx/middleware.go
2024-11-16 14:31:32 -05:00

91 lines
1.9 KiB
Go

package httpx
import (
"context"
"database/sql"
"git.soup.land/soup/shelves/internal/auth"
"log"
"net/http"
"time"
)
type LogWrapper struct {
statusCode *int
http.ResponseWriter
}
func (w LogWrapper) WriteHeader(statusCode int) {
*w.statusCode = statusCode
w.ResponseWriter.WriteHeader(statusCode)
}
func Log(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
statusCode := 200
wrapper := LogWrapper{statusCode: &statusCode, ResponseWriter: w}
start := time.Now()
next.ServeHTTP(wrapper, r)
log.Println(r.Method, r.URL.Path, statusCode, time.Since(start))
})
}
func queryNeedsOwnerSetup(db *sql.DB) (bool, error) {
count := 0
err := db.QueryRow("select count(*) from owner_settings").Scan(&count)
if err != nil {
return false, err
}
return count != 1, nil
}
func sessionInfo(db *sql.DB, r *http.Request) (auth.SessionInfo, error) {
cookie, err := r.Cookie("SHELVES_OWNER_SESSION_ID")
if err == http.ErrNoCookie {
return auth.SessionInfo{}, nil
}
if err != nil {
return auth.SessionInfo{}, err
}
return auth.SessionCheck(db, cookie.Value)
}
type Ctx struct {
DB *sql.DB
SessionInfo auth.SessionInfo
NeedsOwnerSetup bool
}
func GetCtx(r *http.Request) Ctx {
ctx := r.Context()
return ctx.Value("__ctx").(Ctx)
}
func WithCtx(db *sql.DB, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
needsOwnerSetup, err := queryNeedsOwnerSetup(db)
if err != nil {
log.Printf("Error while querying owner_settings: %v\n", err)
}
ctx := r.Context()
session, err := sessionInfo(db, r)
if err != nil {
log.Printf("Error while querying session info: %v\n", err)
}
ctx = context.WithValue(ctx, "__ctx", Ctx{
DB: db,
SessionInfo: session,
NeedsOwnerSetup: needsOwnerSetup,
})
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}