package middleware import ( "context" "encoding/json" "net/http" "strings" "git.kirlllll.ru/volontery/backend/internal/pkg/jwt" ) type contextKey string const ( UserIDKey contextKey = "user_id" UserEmailKey contextKey = "user_email" ) // ErrorResponse represents a JSON error response type ErrorResponse struct { Error string `json:"error"` } // JSONError sends a JSON error response func JSONError(w http.ResponseWriter, message string, statusCode int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) json.NewEncoder(w).Encode(ErrorResponse{Error: message}) } // AuthMiddleware создает middleware для проверки JWT токена func AuthMiddleware(jwtManager *jwt.Manager) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Получение токена из заголовка Authorization authHeader := r.Header.Get("Authorization") if authHeader == "" { JSONError(w, "authorization header required", http.StatusUnauthorized) return } // Проверка формата "Bearer " parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { JSONError(w, "invalid authorization header format", http.StatusUnauthorized) return } tokenString := parts[1] // Валидация токена claims, err := jwtManager.ValidateToken(tokenString) if err != nil { JSONError(w, "invalid or expired token", http.StatusUnauthorized) return } // Добавление данных пользователя в контекст ctx := context.WithValue(r.Context(), UserIDKey, claims.UserID) ctx = context.WithValue(ctx, UserEmailKey, claims.Email) next.ServeHTTP(w, r.WithContext(ctx)) }) } } // GetUserIDFromContext извлекает ID пользователя из контекста func GetUserIDFromContext(ctx context.Context) (int64, bool) { userID, ok := ctx.Value(UserIDKey).(int64) return userID, ok } // GetUserEmailFromContext извлекает email пользователя из контекста func GetUserEmailFromContext(ctx context.Context) (string, bool) { email, ok := ctx.Value(UserEmailKey).(string) return email, ok } // OptionalAuthMiddleware делает аутентификацию опциональной (не возвращает ошибку если токена нет) func OptionalAuthMiddleware(jwtManager *jwt.Manager) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authHeader := r.Header.Get("Authorization") if authHeader == "" { next.ServeHTTP(w, r) return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { next.ServeHTTP(w, r) return } claims, err := jwtManager.ValidateToken(parts[1]) if err != nil { next.ServeHTTP(w, r) return } ctx := context.WithValue(r.Context(), UserIDKey, claims.UserID) ctx = context.WithValue(ctx, UserEmailKey, claims.Email) next.ServeHTTP(w, r.WithContext(ctx)) }) } }