package middleware import ( "context" "net/http" "strings" "spend-sparrow/internal/service" "spend-sparrow/internal/types" ) type ContextKey string var SessionKey ContextKey = "session" var UserKey ContextKey = "user" func Authenticate(service service.Auth) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() if strings.Contains(r.URL.Path, "/static/") { next.ServeHTTP(w, r.WithContext(ctx)) return } sessionId := getSessionID(r) session, user, _ := service.SignInSession(r.Context(), sessionId) var err error // Always sign in anonymous // This way, we can always generate csrf tokens if session == nil { session, err = service.SignInAnonymous(r.Context()) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } cookie := CreateSessionCookie(session.Id) http.SetCookie(w, &cookie) } ctx = context.WithValue(ctx, UserKey, user) ctx = context.WithValue(ctx, SessionKey, session) next.ServeHTTP(w, r.WithContext(ctx)) }) } } func GetUser(r *http.Request) *types.User { obj := r.Context().Value(UserKey) if obj == nil { return nil } user, ok := obj.(*types.User) if !ok { return nil } return user } func GetSession(r *http.Request) *types.Session { obj := r.Context().Value(SessionKey) if obj == nil { return nil } session, ok := obj.(*types.Session) if !ok { return nil } return session } func getSessionID(r *http.Request) string { cookie, err := r.Cookie("id") if err != nil { return "" } return cookie.Value }