Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple-create: Request Validation #2057

Merged
merged 268 commits into from
Apr 25, 2024

Conversation

ayush3797
Copy link
Contributor

@ayush3797 ayush3797 commented Feb 22, 2024

Why make this change?

With support for multiple-create, we introduce additional flexibility in the GraphQL schema where we make the referencing fields in an entity optional because their value can be derived from insertions in the referenced entity. So to say, the values of referencing fields in a referencing entity can have 3 sources of truth. The value for a referencing field can be derived via:

  1. User input data
  2. Insertion in the parent referenced entity (if current entity is a referencing entity for a relationship with its parent entity)
  3. Insertion in the child referenced entity (if the current entity is a referencing entity for a relationship with its child entity)

They can all exist at the same time, or none of them can. Presence of more than one sources of truth leads to possible conflicting values for the referencing column. Thus, at a time, we want exactly one of them to be present - so that we exactly one source of truth. This needs us to do request validation during request execution, so that only valid GQL mutations reach the query generation/query execution stage. This PR adds the logic for the same.

What is this change?

  • Added class MultipleMutationInputValidator.cs to perform the validations for a multiple-create mutation.
  • Added class MultipleMutationEntityInputValidationContext to store relevant information while performing validations on a particular entity.
  • A call to the method MultipleMutationInputValidator.ValidateGraphQLValueNode() will be made just after Authorization - request validation only occurs when the user is authorized to execute the mutation.
  • The method MultipleMutationInputValidator.ValidateGraphQLValueNode() makes recursive call to itself to parse out the entire create mutation request body based on an entity or relationship basis. Meaning, this method will be called on the top-level entity, followed by all the relationships for that entity, followed by all the relationships for the entity's relationships and so on....
  • The actual validation for the input data for an entity (top-level entity or a nested entity) which includes column fields and relationship fields is done by the method GraphQLRequestValidator.ValidateObjectFieldNodes() which is called from the method ValidateGraphQLValueNode().
  • The method ValidateObjectFieldNodes() contains logic to ensure that when the current entity acts as the referencing entity for the relationships with its target entity, then the current entity should not specify a value for the referencing fields - as the values for the referencing fields will be derived from the insertion in the referenced target entity. Note: The determination of referencing entity is done via a call to MultipleCreateOrderHelper.GetReferencingEntityName() method added via: Multiple-create: Order determination for insertions #2056.
  • The method ValidateObjectFieldNodes() makes calls to
    1. ValidateAbsenceOfReferencingColumnsInTargetEntity(): To validate that the current entity does not specify value for referencing columns to its parent entity (when parent entity is the referenced entity).
    2. ProcessRelationshipField(): To process a relationship field and does several things. Please refer to method summary.
    3. ValidateAbsenceOfRepeatedReferencingColumn(): This method is called for all the relationships with the current entity which are included in the request body. This ensures that referencing columns in the referencing entity (whichever entity, either source or target turns out as the referencing entity) does not hold references to multiple columns in the referenced entity - to avoid multiple sources of truth for the referencing column's value. (Issue: Allow a referencing column to reference only one referenced column in relationships #2019)
    4. ValidatePresenceOfRequiredColumnsForInsertion(): To ensure that we have one source of truth for values for referencing fields.
    5. ValidateRelationshipFields(): Recursively perform the same validations for all the relationships with the current entity included in the mutation request body.
    `

How was this tested?

  • Integration Tests - Added tests to MultipleMutationIntegrationTests.cs to validate:
    1. Throwing exception for absence of source of truth for referencing column for create one mutations
    2. Throwing exception for absence of source of truth for referencing column for create multiple mutations.
    3. Throwing exception for presence of multiple sources of truth for referencing column for create one mutations.
    4. Throwing exception for presence of multiple sources of truth for referencing column for create one mutations.

Sample Request(s)

  1. Request:
    image
    Response:

image

  1. Request:
    image

Response:
image

  1. Request and response:
    image

@seantleonard
Copy link
Contributor

/azp run

Base automatically changed from dev/agarwalayush/nestedInsertionOrderHelper to main April 22, 2024 21:42
Copy link
Contributor

@seantleonard seantleonard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added feedback to clarify intent / comments/ add some more tests.

Copy link
Contributor

@seantleonard seantleonard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pending more tests and further resolution of open feedback threads + resolving merge conflicts.

Copy link
Contributor

@severussundar severussundar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit suggestion to re-name GraphQLRequestValidator to MultipleMutationInputValidator in the PR description.

LGTM, after addressing this and pending suggestions.

Thank you for adding logic to validate the Multiple Create mutation request :)

@ayush3797 ayush3797 enabled auto-merge (squash) April 25, 2024 07:18
@ayush3797 ayush3797 merged commit 54308cc into main Apr 25, 2024
7 checks passed
@ayush3797 ayush3797 deleted the dev/agarwalayush/requestValidationForNestedInsertions branch April 25, 2024 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Multiple mutations Fixes/enhancements related to nested mutations.
Projects
None yet
4 participants