package middleware import ( "context" "fmt" "net/http" "strings" "gitea.local/admin/hspguard/internal/config" "gitea.local/admin/hspguard/internal/types" "gitea.local/admin/hspguard/internal/util" "gitea.local/admin/hspguard/internal/web" ) type AuthMiddleware struct { cfg *config.AppConfig } func NewAuthMiddleware(cfg *config.AppConfig) *AuthMiddleware { return &AuthMiddleware{ cfg, } } func (m *AuthMiddleware) Runner(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authHeader := r.Header.Get("Authorization") if authHeader == "" { web.Error(w, "unauthorized", http.StatusUnauthorized) return } parts := strings.Split(authHeader, "Bearer ") if len(parts) != 2 { web.Error(w, "invalid auth header format", http.StatusUnauthorized) return } tokenStr := parts[1] var userClaims types.UserClaims token, err := util.VerifyToken(tokenStr, m.cfg.Jwt.PublicKey, &userClaims) if err != nil || !token.Valid { web.Error(w, fmt.Sprintf("invalid token: %v", err), http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), types.UserIdKey, userClaims.Subject) next.ServeHTTP(w, r.WithContext(ctx)) }) } func WithSkipper(mw func(http.Handler) http.Handler, excludedPaths ...string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { for _, path := range excludedPaths { if strings.HasPrefix(r.URL.Path, path) { next.ServeHTTP(w, r) return } } mw(next).ServeHTTP(w, r) }) } }