package app import ( "context" "errors" "net/http" "git.farahty.com/nimer/go-mongo/models" "git.farahty.com/nimer/go-mongo/utils" "github.com/99designs/gqlgen/graphql" "github.com/golang-jwt/jwt/v4" ) // Middleware injects dataloaders into context for each HTTP request func LoaderMiddleware(loaders *Loaders, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctxWithLoaders := context.WithValue(r.Context(), LoadersKey, loaders) next.ServeHTTP(w, r.WithContext(ctxWithLoaders)) }) } // ExpiryMiddleware checks for expired tokens in GraphQL resolvers func ExpiryMiddleware(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { if IsTokenExpired(ctx) { return graphql.ErrorResponse(ctx, "token expired") } return next(ctx) } // add response writer to context for GraphQL resolvers func WriterMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), WriterKye, &rw) next.ServeHTTP(rw, r.WithContext(ctx)) }) } // add request to context for GraphQL resolvers func RequestMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), RequestKey, r) next.ServeHTTP(rw, r.WithContext(ctx)) }) } // AuthMiddleware parses JWT token and injects user context for HTTP requests func AuthMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { headerToken, headerErr := utils.GetTokenFromHeader(r) cookieToken, cookieErr := utils.GetTokenFromCookie(r) if headerErr != nil && cookieErr != nil { ctx := SetStatus(r.Context(), headerErr.Error()) next.ServeHTTP(rw, r.WithContext(ctx)) return } token := headerToken if token == "" { token = cookieToken } user, err := utils.GetUserFromToken[models.UserJWT](token, Config.AccessSecret) ctx := r.Context() if err != nil { ctx = SetStatus(ctx, err.Error()) if errors.Is(err, jwt.ErrTokenExpired) { ctx = SetTokenExpired(ctx, true) } next.ServeHTTP(rw, r.WithContext(ctx)) return } ctx = SetCurrentUser(ctx, user) ctx = SetStatus(ctx, "ok") next.ServeHTTP(rw, r.WithContext(ctx)) }) }