ChilliCream / ChilliCream/graphql-platform

Infer FilterInputType from defined ObjectType

Open
#7,170 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🌶️ hot chocolate Area: Data
Dominant language
C#
Stars
5.8k
Forks
810
Avg merge
15h 39m
Merged PRs (30d)
98

Description

Product

Hot Chocolate

Is your feature request related to a problem?

I'm facing unexpected behavior when defining my GraphQL types. We are using the code-first approach with explicit field-binding behavior so we do not accidentally expose fields to our schema.


public class User
{
    public string LoginId { get; set; }

    public string DisplayName { get; set; }

    public string Password { get; set; }
}

public class UserType : ObjectType<User>
{
    protected override void Configure(IObjectTypeDescriptor<User> descriptor)
    {
        base.Configure(descriptor);
        descriptor.BindFieldsExplicitly();
        descriptor.Field(x => x.DisplayName);
        descriptor.Field(x => x.LoginId);
    }
}

We later call UseFiltering() in our resolver for this type, expecting that the available fields for filtering would follow the fields exposed for selection (in short, should not be able to filter by an user's password if the field is already not being exposed). Yet, this does not seem to be achievable without specifying an explicit FilterInputType for the User type

public class UserFilterInputType : FilterInputType<User>
{
    protected override void Configure(IFilterInputTypeDescriptor<User> descriptor)
    {
        base.Configure(descriptor);
        descriptor.BindFieldsExplicitly();
        descriptor.Field(x => x.DisplayName);
        descriptor.Field(x => x.LoginId);
    }
}

This doesn't look like a problem at first glance but as our schema grows (both in number of types being exposed and number of fields for each type) we will end up with lots of duplicate code by having to explicitly define each field at least twice.

Nevertheless, the way we expect this to work is accomplished by using the annotation-based approach, since

public class User
{
    public string LoginId { get; set; }

    public string DisplayName { get; set; }

    [GraphQLIgnore]
    public string Password { get; set; }
}

does exclude the field both from the selection set and the filter type with no need to configure each schema type separately.

The solution you'd like

The implicitly defined FilterInputType that is generated when calling UseFiltering() on a type that already has been configured by an ObjectType<T> should only consider fields defined in the type configuration when using explicit field-binding behavior in the code-first approach, similar to how annotation-based approach handles exposed and ignored fields.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the implicit FilterInputType generation used by UseFiltering and how ObjectType explicit field binding is represented. The change is complete when generated filter input fields follow the configured object fields, excluding fields such as Password, with regression coverage for the shown UserType scenario.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.