| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- // Package middleware предоставляет middleware для HTTP-роутера.
- // Включает аутентификацию через JWT (AuthMiddleware), проверку ролей
- // (RoleMiddleware), in-memory rate limiter и Redis-based rate limiter
- // с настройками для auth, read, write и admin эндпоинтов.
- package middleware
- import (
- "context"
- "encoding/json"
- "net/http"
- "strings"
- "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/services"
- )
- type contextKey string
- const (
- UserIDKey contextKey = "user_id"
- UserRoleKey contextKey = "user_role"
- )
- func AuthMiddleware(authSvc *services.AuthService) 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 == "" {
- writeAuthError(w, "missing authorization header")
- return
- }
- parts := strings.SplitN(authHeader, " ", 2)
- if len(parts) != 2 || parts[0] != "Bearer" {
- writeAuthError(w, "invalid authorization format")
- return
- }
- claims, err := authSvc.ValidateAccessToken(parts[1])
- if err != nil {
- writeAuthError(w, "invalid or expired token")
- return
- }
- ctx := context.WithValue(r.Context(), UserIDKey, claims.UserID)
- ctx = context.WithValue(ctx, UserRoleKey, claims.Role)
- next.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- }
- func RoleMiddleware(roles ...string) func(http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- role, _ := r.Context().Value(UserRoleKey).(string)
- for _, allowed := range roles {
- if role == allowed {
- next.ServeHTTP(w, r)
- return
- }
- }
- writeAuthError(w, "insufficient permissions")
- })
- }
- }
- func GetUserID(ctx context.Context) string {
- v, _ := ctx.Value(UserIDKey).(string)
- return v
- }
- func GetUserRole(ctx context.Context) string {
- v, _ := ctx.Value(UserRoleKey).(string)
- return v
- }
- func writeAuthError(w http.ResponseWriter, msg string) {
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusUnauthorized)
- json.NewEncoder(w).Encode(map[string]string{"error": msg})
- }
|