最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Automatically enforcing GraphQL directives with Spring GraphQL - Stack Overflow

programmeradmin3浏览0评论

I wondering if it is possible to automatically enforce GraphQL directive in Spring GraphQL.

My schema is

directive @validateUserId on ARGUMENT_DEFINITION
type Mutation {
  addBook(userId: ID! @validateUserId , name:String, pageCount:Int, author:NewAuthorInput): Book
}

Mutation handler in my controller:

@MutationMapping
  public Book addBook(@Argument UUID userId, @Argument String name, @Argument Integer pageCount, @NotNull @Argument NewAuthorInput author, DataFetchingEnvironment environment) {
    ValidateUserIdDirective.validateUserId(environment);

    Author newAuthor = bookService.addAuthor(author.getFirstName(), author.getLastName());
    return bookService.addBook(name, pageCount, newAuthor);
  }

and my directive wiring:

@Component
public class ValidateUserIdDirective implements SchemaDirectiveWiring {

  @Override
  public GraphQLArgument onArgument(SchemaDirectiveWiringEnvironment<GraphQLArgument> environment) {
    return environment.getElement();
  }

  public static void validateUserId(DataFetchingEnvironment environment) {
    UUID providedUserId = UUID.fromString(Objects.requireNonNull(environment.getArgument("userId")));
   // do something with user id
  
  }
}

In this code I explicitly calling ValidateUserIdDirective.validateUserId(environment); in my mutation handler. I am wondering if there is a way to automatically validate user directive without making any explicit calls?

I wondering if it is possible to automatically enforce GraphQL directive in Spring GraphQL.

My schema is

directive @validateUserId on ARGUMENT_DEFINITION
type Mutation {
  addBook(userId: ID! @validateUserId , name:String, pageCount:Int, author:NewAuthorInput): Book
}

Mutation handler in my controller:

@MutationMapping
  public Book addBook(@Argument UUID userId, @Argument String name, @Argument Integer pageCount, @NotNull @Argument NewAuthorInput author, DataFetchingEnvironment environment) {
    ValidateUserIdDirective.validateUserId(environment);

    Author newAuthor = bookService.addAuthor(author.getFirstName(), author.getLastName());
    return bookService.addBook(name, pageCount, newAuthor);
  }

and my directive wiring:

@Component
public class ValidateUserIdDirective implements SchemaDirectiveWiring {

  @Override
  public GraphQLArgument onArgument(SchemaDirectiveWiringEnvironment<GraphQLArgument> environment) {
    return environment.getElement();
  }

  public static void validateUserId(DataFetchingEnvironment environment) {
    UUID providedUserId = UUID.fromString(Objects.requireNonNull(environment.getArgument("userId")));
   // do something with user id
  
  }
}

In this code I explicitly calling ValidateUserIdDirective.validateUserId(environment); in my mutation handler. I am wondering if there is a way to automatically validate user directive without making any explicit calls?

Share Improve this question asked Mar 25 at 19:45 MrkKMrkK 9033 gold badges12 silver badges25 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

Instead of manually calling ValidateUserIdDirective.validateUserId(environment) in your @MutationMapping method, you can modify your ValidateUserIdDirective to intercept the DataFetcher for the field and apply the validation logic automatically.

This is done by wiring the directive at the schema level and modifying the DataFetcher behavior.

import graphql.schema.*;
import .springframework.graphql.execution.SchemaDirectiveWiring;
import .springframework.stereotype.Component;
import graphql.schema.idl.SchemaDirectiveWiringEnvironment;

import java.util.Objects;
import java.util.UUID;

@Component
public class ValidateUserIdDirective implements SchemaDirectiveWiring {

    @Override
    public GraphQLArgument onArgument(SchemaDirectiveWiringEnvironment<GraphQLArgument> environment) {
        GraphQLArgument argument = environment.getElement();
        GraphQLFieldDefinition field = environment.getFieldDefinition();

        DataFetcher<?> originalDataFetcher = environment.getCodeRegistry().getDataFetcher(
            (GraphQLObjectType) field.getParentType(), field);

        DataFetcher<?> wrappedDataFetcher = dataFetchingEnvironment -> {
            String userIdArg = dataFetchingEnvironment.getArgument("userId");
            validateUserId(userIdArg);
            return originalDataFetcher.get(dataFetchingEnvironment);
        };

        // Register the wrapped DataFetcher in the CodeRegistry
        environment.getCodeRegistry().dataFetcher(
            (GraphQLObjectType) field.getParentType(), field, wrappedDataFetcher);

        return argument; 
    }

    private void validateUserId(String userId) {
        UUID providedUserId = UUID.fromString(Objects.requireNonNull(userId));
        // Add your validation logic here
        System.out.println("Validated userId: " + providedUserId);
    }
}

I solved the problem by correct registration of my wiring directive:

@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer(ValidateUserIdDirective validateUserIdDirective) {
  return wiringBuilder -> wiringBuilder
          .directive("validateUserId", validateUserIdDirective);
}
发布评论

评论列表(0)

  1. 暂无评论