Search in sources :

Example 1 with SchemaTransformer

use of graphql.schema.SchemaTransformer in project graphql-java by graphql-java.

the class Anonymizer method anonymizeSchemaAndQueries.

public static AnonymizeResult anonymizeSchemaAndQueries(GraphQLSchema schema, List<String> queries, Map<String, Object> variables) {
    assertNotNull(queries, () -> "queries can't be null");
    AtomicInteger defaultStringValueCounter = new AtomicInteger(1);
    AtomicInteger defaultIntValueCounter = new AtomicInteger(1);
    Map<GraphQLNamedSchemaElement, String> newNameMap = recordNewNamesForSchema(schema);
    // stores a reverse index of anonymized argument name to argument instance
    // this is to handle cases where the fields on implementing types MUST have the same exact argument and default
    // value definitions as the fields on the implemented interface. (argument default values must match exactly)
    Map<String, GraphQLArgument> renamedArgumentsMap = new HashMap<>();
    SchemaTransformer schemaTransformer = new SchemaTransformer();
    GraphQLSchema newSchema = schemaTransformer.transform(schema, new GraphQLTypeVisitorStub() {

        @Override
        public TraversalControl visitGraphQLTypeReference(GraphQLTypeReference graphQLTypeReference, TraverserContext<GraphQLSchemaElement> context) {
            GraphQLNamedSchemaElement type = (GraphQLNamedSchemaElement) schema.getType(graphQLTypeReference.getName());
            String newName = newNameMap.get(type);
            GraphQLTypeReference newReference = GraphQLTypeReference.typeRef(newName);
            return changeNode(context, newReference);
        }

        @Override
        public TraversalControl visitGraphQLArgument(GraphQLArgument graphQLArgument, TraverserContext<GraphQLSchemaElement> context) {
            String newName = assertNotNull(newNameMap.get(graphQLArgument));
            if (context.getParentNode() instanceof GraphQLFieldDefinition) {
                // arguments on field definitions must be identical across implementing types and interfaces.
                if (renamedArgumentsMap.containsKey(newName)) {
                    return changeNode(context, renamedArgumentsMap.get(newName).transform(b -> {
                    }));
                }
            }
            GraphQLArgument newElement = graphQLArgument.transform(builder -> {
                builder.name(newName).description(null).definition(null);
                if (graphQLArgument.hasSetDefaultValue()) {
                    Value<?> defaultValueLiteral = ValuesResolver.valueToLiteral(graphQLArgument.getArgumentDefaultValue(), graphQLArgument.getType());
                    builder.defaultValueLiteral(replaceValue(defaultValueLiteral, graphQLArgument.getType(), newNameMap, defaultStringValueCounter, defaultIntValueCounter));
                }
                if (graphQLArgument.hasSetValue()) {
                    Value<?> valueLiteral = ValuesResolver.valueToLiteral(graphQLArgument.getArgumentValue(), graphQLArgument.getType());
                    builder.valueLiteral(replaceValue(valueLiteral, graphQLArgument.getType(), newNameMap, defaultStringValueCounter, defaultIntValueCounter));
                }
            });
            renamedArgumentsMap.put(newName, newElement);
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLAppliedDirectiveArgument(GraphQLAppliedDirectiveArgument graphQLArgument, TraverserContext<GraphQLSchemaElement> context) {
            String newName = assertNotNull(newNameMap.get(graphQLArgument));
            GraphQLAppliedDirectiveArgument newElement = graphQLArgument.transform(builder -> {
                builder.name(newName).description(null).definition(null);
                if (graphQLArgument.hasSetValue()) {
                    Value<?> valueLiteral = ValuesResolver.valueToLiteral(graphQLArgument.getArgumentValue(), graphQLArgument.getType());
                    builder.valueLiteral(replaceValue(valueLiteral, graphQLArgument.getType(), newNameMap, defaultStringValueCounter, defaultIntValueCounter));
                }
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType graphQLInterfaceType, TraverserContext<GraphQLSchemaElement> context) {
            if (Introspection.isIntrospectionTypes(graphQLInterfaceType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLInterfaceType));
            GraphQLInterfaceType newElement = graphQLInterfaceType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            GraphQLCodeRegistry.Builder codeRegistry = assertNotNull(context.getVarFromParents(GraphQLCodeRegistry.Builder.class));
            TypeResolver typeResolver = codeRegistry.getTypeResolver(graphQLInterfaceType);
            codeRegistry.typeResolver(newName, typeResolver);
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLEnumType(GraphQLEnumType graphQLEnumType, TraverserContext<GraphQLSchemaElement> context) {
            if (Introspection.isIntrospectionTypes(graphQLEnumType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLEnumType));
            GraphQLEnumType newElement = graphQLEnumType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLEnumValueDefinition(GraphQLEnumValueDefinition enumValueDefinition, TraverserContext<GraphQLSchemaElement> context) {
            String newName = assertNotNull(newNameMap.get(enumValueDefinition));
            GraphQLEnumValueDefinition newElement = enumValueDefinition.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition graphQLFieldDefinition, TraverserContext<GraphQLSchemaElement> context) {
            String newName = assertNotNull(newNameMap.get(graphQLFieldDefinition));
            GraphQLFieldDefinition newElement = graphQLFieldDefinition.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLDirective(GraphQLDirective graphQLDirective, TraverserContext<GraphQLSchemaElement> context) {
            if (Directives.DEPRECATED_DIRECTIVE_DEFINITION.getName().equals(graphQLDirective.getName())) {
                GraphQLArgument reason = newArgument().name("reason").type(Scalars.GraphQLString).clearValue().build();
                GraphQLDirective newElement = graphQLDirective.transform(builder -> {
                    builder.description(null).argument(reason);
                });
                changeNode(context, newElement);
                return TraversalControl.ABORT;
            }
            if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective.getName())) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLDirective));
            GraphQLDirective newElement = graphQLDirective.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLAppliedDirective(GraphQLAppliedDirective graphQLDirective, TraverserContext<GraphQLSchemaElement> context) {
            if (Directives.DEPRECATED_DIRECTIVE_DEFINITION.getName().equals(graphQLDirective.getName())) {
                GraphQLAppliedDirectiveArgument reason = GraphQLAppliedDirectiveArgument.newArgument().name("reason").type(Scalars.GraphQLString).clearValue().build();
                GraphQLAppliedDirective newElement = graphQLDirective.transform(builder -> {
                    builder.description(null).argument(reason);
                });
                changeNode(context, newElement);
                return TraversalControl.ABORT;
            }
            if (DirectiveInfo.isGraphqlSpecifiedDirective(graphQLDirective.getName())) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLDirective));
            GraphQLAppliedDirective newElement = graphQLDirective.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField graphQLInputObjectField, TraverserContext<GraphQLSchemaElement> context) {
            String newName = assertNotNull(newNameMap.get(graphQLInputObjectField));
            Value<?> defaultValue = null;
            if (graphQLInputObjectField.hasSetDefaultValue()) {
                defaultValue = ValuesResolver.valueToLiteral(graphQLInputObjectField.getInputFieldDefaultValue(), graphQLInputObjectField.getType());
                defaultValue = replaceValue(defaultValue, graphQLInputObjectField.getType(), newNameMap, defaultStringValueCounter, defaultIntValueCounter);
            }
            Value<?> finalDefaultValue = defaultValue;
            GraphQLInputObjectField newElement = graphQLInputObjectField.transform(builder -> {
                builder.name(newName);
                if (finalDefaultValue != null) {
                    builder.defaultValueLiteral(finalDefaultValue);
                }
                builder.description(null);
                builder.definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLInputObjectType(GraphQLInputObjectType graphQLInputObjectType, TraverserContext<GraphQLSchemaElement> context) {
            if (Introspection.isIntrospectionTypes(graphQLInputObjectType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLInputObjectType));
            GraphQLInputObjectType newElement = graphQLInputObjectType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLObjectType(GraphQLObjectType graphQLObjectType, TraverserContext<GraphQLSchemaElement> context) {
            if (Introspection.isIntrospectionTypes(graphQLObjectType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLObjectType));
            GraphQLObjectType newElement = graphQLObjectType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLScalarType(GraphQLScalarType graphQLScalarType, TraverserContext<GraphQLSchemaElement> context) {
            if (ScalarInfo.isGraphqlSpecifiedScalar(graphQLScalarType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLScalarType));
            GraphQLScalarType newElement = graphQLScalarType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            return changeNode(context, newElement);
        }

        @Override
        public TraversalControl visitGraphQLUnionType(GraphQLUnionType graphQLUnionType, TraverserContext<GraphQLSchemaElement> context) {
            if (Introspection.isIntrospectionTypes(graphQLUnionType)) {
                return TraversalControl.ABORT;
            }
            String newName = assertNotNull(newNameMap.get(graphQLUnionType));
            GraphQLUnionType newElement = graphQLUnionType.transform(builder -> {
                builder.name(newName).description(null).definition(null);
            });
            GraphQLCodeRegistry.Builder codeRegistry = assertNotNull(context.getVarFromParents(GraphQLCodeRegistry.Builder.class));
            TypeResolver typeResolver = codeRegistry.getTypeResolver(graphQLUnionType);
            codeRegistry.typeResolver(newName, typeResolver);
            return changeNode(context, newElement);
        }
    });
    List<String> newQueries = new ArrayList<>();
    for (String query : queries) {
        String newQuery = rewriteQuery(query, schema, newNameMap, variables);
        newQueries.add(newQuery);
    }
    AnonymizeResult result = new AnonymizeResult(newSchema, newQueries);
    return result;
}
Also used : OperationDefinition(graphql.language.OperationDefinition) Value(graphql.language.Value) QueryVisitorInlineFragmentEnvironment(graphql.analysis.QueryVisitorInlineFragmentEnvironment) ValuesResolver(graphql.execution.ValuesResolver) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) QueryTraverser(graphql.analysis.QueryTraverser) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) FragmentSpread(graphql.language.FragmentSpread) GraphQLInterfaceType(graphql.schema.GraphQLInterfaceType) GraphQLInputObjectField(graphql.schema.GraphQLInputObjectField) GraphQLUnionType(graphql.schema.GraphQLUnionType) GraphQLEnumValueDefinition(graphql.schema.GraphQLEnumValueDefinition) GraphQLNamedSchemaElement(graphql.schema.GraphQLNamedSchemaElement) GraphQLTypeUtil.unwrapNonNullAs(graphql.schema.GraphQLTypeUtil.unwrapNonNullAs) Directives(graphql.Directives) GraphQLAppliedDirective(graphql.schema.GraphQLAppliedDirective) QueryVisitorFieldEnvironment(graphql.analysis.QueryVisitorFieldEnvironment) Type(graphql.language.Type) DirectiveInfo(graphql.schema.idl.DirectiveInfo) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) QueryVisitorFragmentSpreadEnvironment(graphql.analysis.QueryVisitorFragmentSpreadEnvironment) BigInteger(java.math.BigInteger) TypeName(graphql.language.TypeName) TypeResolver(graphql.schema.TypeResolver) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLDirective(graphql.schema.GraphQLDirective) GraphQLNamedOutputType(graphql.schema.GraphQLNamedOutputType) GraphQLNonNull(graphql.schema.GraphQLNonNull) ObjectField(graphql.language.ObjectField) GraphQLInputType(graphql.schema.GraphQLInputType) Set(java.util.Set) GraphQLArgument(graphql.schema.GraphQLArgument) String.format(java.lang.String.format) AstPrinter(graphql.language.AstPrinter) List(java.util.List) QueryVisitor(graphql.analysis.QueryVisitor) ArrayValue(graphql.language.ArrayValue) Optional(java.util.Optional) FragmentDefinition(graphql.language.FragmentDefinition) NonNullType(graphql.language.NonNullType) GraphQLEnumType(graphql.schema.GraphQLEnumType) ListType(graphql.language.ListType) AstTransformer(graphql.language.AstTransformer) ObjectValue(graphql.language.ObjectValue) GraphQLSchemaElement(graphql.schema.GraphQLSchemaElement) GraphQLCodeRegistry(graphql.schema.GraphQLCodeRegistry) GraphQLNamedType(graphql.schema.GraphQLNamedType) Node(graphql.language.Node) SchemaTransformer(graphql.schema.SchemaTransformer) TreeTransformerUtil.changeNode(graphql.util.TreeTransformerUtil.changeNode) GraphQLScalarType(graphql.schema.GraphQLScalarType) QueryVisitorFieldArgumentEnvironment(graphql.analysis.QueryVisitorFieldArgumentEnvironment) QueryVisitorFieldArgumentInputValue(graphql.analysis.QueryVisitorFieldArgumentInputValue) EnumValue(graphql.language.EnumValue) HashMap(java.util.HashMap) GraphQLType(graphql.schema.GraphQLType) ArrayList(java.util.ArrayList) Introspection(graphql.introspection.Introspection) LinkedHashMap(java.util.LinkedHashMap) Scalars(graphql.Scalars) Parser(graphql.parser.Parser) Definition(graphql.language.Definition) VariableReference(graphql.language.VariableReference) BiConsumer(java.util.function.BiConsumer) GraphQLSchema(graphql.schema.GraphQLSchema) GraphQLAppliedDirectiveArgument(graphql.schema.GraphQLAppliedDirectiveArgument) QueryVisitorFieldArgumentValueEnvironment(graphql.analysis.QueryVisitorFieldArgumentValueEnvironment) LinkedHashSet(java.util.LinkedHashSet) NodeVisitorStub(graphql.language.NodeVisitorStub) SchemaGenerator.createdMockedSchema(graphql.schema.idl.SchemaGenerator.createdMockedSchema) ScalarInfo(graphql.schema.idl.ScalarInfo) CONTINUE(graphql.util.TraversalControl.CONTINUE) GraphQLArgument.newArgument(graphql.schema.GraphQLArgument.newArgument) Field(graphql.language.Field) GraphQLImplementingType(graphql.schema.GraphQLImplementingType) GraphQLTypeVisitorStub(graphql.schema.GraphQLTypeVisitorStub) SchemaUtil(graphql.schema.impl.SchemaUtil) AssertException(graphql.AssertException) Directive(graphql.language.Directive) Consumer(java.util.function.Consumer) Argument(graphql.language.Argument) Document(graphql.language.Document) TypeUtil(graphql.schema.idl.TypeUtil) VariableDefinition(graphql.language.VariableDefinition) GraphQLList(graphql.schema.GraphQLList) StringValue(graphql.language.StringValue) GraphQLTypeReference(graphql.schema.GraphQLTypeReference) GraphQLTypeUtil.unwrapNonNull(graphql.schema.GraphQLTypeUtil.unwrapNonNull) PublicApi(graphql.PublicApi) IntValue(graphql.language.IntValue) Assert.assertNotNull(graphql.Assert.assertNotNull) GraphQLTypeVisitor(graphql.schema.GraphQLTypeVisitor) GraphQLTypeUtil.unwrapOneAs(graphql.schema.GraphQLTypeUtil.unwrapOneAs) InlineFragment(graphql.language.InlineFragment) Collections(java.util.Collections) GraphQLTypeReference(graphql.schema.GraphQLTypeReference) GraphQLUnionType(graphql.schema.GraphQLUnionType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeResolver(graphql.schema.TypeResolver) ArrayList(java.util.ArrayList) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) GraphQLInterfaceType(graphql.schema.GraphQLInterfaceType) GraphQLTypeVisitorStub(graphql.schema.GraphQLTypeVisitorStub) GraphQLSchemaElement(graphql.schema.GraphQLSchemaElement) GraphQLAppliedDirectiveArgument(graphql.schema.GraphQLAppliedDirectiveArgument) GraphQLCodeRegistry(graphql.schema.GraphQLCodeRegistry) GraphQLNamedSchemaElement(graphql.schema.GraphQLNamedSchemaElement) GraphQLEnumType(graphql.schema.GraphQLEnumType) GraphQLEnumValueDefinition(graphql.schema.GraphQLEnumValueDefinition) GraphQLArgument(graphql.schema.GraphQLArgument) SchemaTransformer(graphql.schema.SchemaTransformer) GraphQLDirective(graphql.schema.GraphQLDirective) GraphQLAppliedDirective(graphql.schema.GraphQLAppliedDirective) GraphQLSchema(graphql.schema.GraphQLSchema) GraphQLScalarType(graphql.schema.GraphQLScalarType) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GraphQLInputObjectField(graphql.schema.GraphQLInputObjectField) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) Value(graphql.language.Value) ArrayValue(graphql.language.ArrayValue) ObjectValue(graphql.language.ObjectValue) QueryVisitorFieldArgumentInputValue(graphql.analysis.QueryVisitorFieldArgumentInputValue) EnumValue(graphql.language.EnumValue) StringValue(graphql.language.StringValue) IntValue(graphql.language.IntValue) GraphQLObjectType(graphql.schema.GraphQLObjectType)

Aggregations

Assert.assertNotNull (graphql.Assert.assertNotNull)1 AssertException (graphql.AssertException)1 Directives (graphql.Directives)1 PublicApi (graphql.PublicApi)1 Scalars (graphql.Scalars)1 QueryTraverser (graphql.analysis.QueryTraverser)1 QueryVisitor (graphql.analysis.QueryVisitor)1 QueryVisitorFieldArgumentEnvironment (graphql.analysis.QueryVisitorFieldArgumentEnvironment)1 QueryVisitorFieldArgumentInputValue (graphql.analysis.QueryVisitorFieldArgumentInputValue)1 QueryVisitorFieldArgumentValueEnvironment (graphql.analysis.QueryVisitorFieldArgumentValueEnvironment)1 QueryVisitorFieldEnvironment (graphql.analysis.QueryVisitorFieldEnvironment)1 QueryVisitorFragmentSpreadEnvironment (graphql.analysis.QueryVisitorFragmentSpreadEnvironment)1 QueryVisitorInlineFragmentEnvironment (graphql.analysis.QueryVisitorInlineFragmentEnvironment)1 ValuesResolver (graphql.execution.ValuesResolver)1 Introspection (graphql.introspection.Introspection)1 Argument (graphql.language.Argument)1 ArrayValue (graphql.language.ArrayValue)1 AstPrinter (graphql.language.AstPrinter)1 AstTransformer (graphql.language.AstTransformer)1 Definition (graphql.language.Definition)1