package middleware import ( "context" "encoding/json" "net/http" "strings" "5803025015/w04/internal/models" ) type contextKey string const UserIDKey contextKey = "user_id" func GetUserID(ctx context.Context) string { if val, ok := ctx.Value(UserIDKey).(string); ok { return val } return "" } type SessionStore interface { Get(ctx context.Context, token string) (*models.Session, error) } type AuthMiddleware struct { sessionStore SessionStore } func NewAuthMiddleware(sessionStore SessionStore) *AuthMiddleware { return &AuthMiddleware{sessionStore: sessionStore} } func writeJSONError(w http.ResponseWriter, status int, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) _ = json.NewEncoder(w).Encode(map[string]string{"error": msg}) } func (m *AuthMiddleware) RequireAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authHeader := r.Header.Get("Authorization") if authHeader == "" { writeJSONError(w, http.StatusUnauthorized, "unauthorized") return } const bearerPrefix = "bearer " if !strings.HasPrefix(strings.ToLower(authHeader), bearerPrefix) { writeJSONError(w, http.StatusUnauthorized, "unauthorized") return } token := strings.TrimSpace(authHeader[len(bearerPrefix):]) if token == "" { writeJSONError(w, http.StatusUnauthorized, "unauthorized") return } session, err := m.sessionStore.Get(r.Context(), token) if err != nil || session == nil { writeJSONError(w, http.StatusUnauthorized, "unauthorized") return } ctx := context.WithValue(r.Context(), UserIDKey, session.UserID) next.ServeHTTP(w, r.WithContext(ctx)) }) } func (m *AuthMiddleware) RequireAuthFunc(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { m.RequireAuth(next).ServeHTTP(w, r) } } func RequireAuth(sessionStore SessionStore) func(http.Handler) http.Handler { return NewAuthMiddleware(sessionStore).RequireAuth }