According to https://github.com/maticzav/graphql-shield#rules-on-input-types-or-arguments, it's possible to use rules to validate argument value.
How to apply rules to input types (and specific fields of input types)? In the https://github.com/maticzav/graphql-shield#rules-on-input-types-or-arguments example the rule is in fact applied to the argument, not the input type, and validates the argument as a nested object, instead of applying rules to the fields of the input type.
How to apply rules to arguments and input types (and specific fields of input types) for authorization (permission validation), not value validation?
Suppose there is the following schema:
type Mutation {
createUser(name: String, email: String, age: Int, verified: Boolean): User!
updateUser(id: ID!, name: String, email: String, age: Int, verified: Boolean): User!
deleteUser(id: ID!): User
...
}
It's possible to restrict the whole mutation, e.g.:
const permissions = shield({
Mutation: {
updateUser: isAdmin,
}
})
But what if I want to restrict only updating of the verified field (but allow updating the rest fileds) in the updateUser mutation, not the whole mutation (by applying the rule to the argument)?
Is it possible to do something like the following?
const permissions = shield({
Mutation: {
updateUser(
verified: isAdmin
)
}
})
The mutation arguments may be extracted to separate input types (hello, Prisma! :wave:). In this case the rules should be applied to input type fields. Something like:
type Mutation {
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User!
...
}
...
input UserUpdateInput {
name: String
email: String
age: Int
verified: Boolean
}
const permissions = shield({
UserUpdateInput: {
email: or(isOwner, isAdmin)
verified: isAdmin
}
})
Is it possible?
The _partial response_ is one of the basic principles of GraphQL: a response may contain both a partial data as well as encountered errors in the case that a field error occurred on a field which was replaced with null.
If a field’s resolve function throws an error, the error will be inserted into the response’s errors key and the field will resolve to null.
If the null value returns in a resolver for a non-null field, the null result bubbles up to the nearest nullable parent.
This is what concerns data querying (reading). But what about data mutating (writing)?
Suppose there is a mutation that has 3 arguments, and we add validations to all these arguments.
Current behavior: if at least one of the mutation arguments fails validation, the entire mutation will not be executed. Right?
But what if this argument (which failed validation) is not non-null (optional / not required)? In this case the mutation could be executed with two rest arguments.
Is it possible to just remove this argument from mutation if it fails validation?
The argument can be input type (nested object) i.e. contains other input types with its own fields that can also be input types, and so on.
If the field from depth (deep nested input type) fails (permission or value) validation and this field is not non-null (optional / not required), this field should just be removed.
If the field from depth (deep nested input type) fails (permission or value) validation and this field is non-null (required), the null should bubbles up to the nearest nullable parent.
In the case of field (optional or required) was removed, the response should contain both a mutation response as well as encountered errors in the case that a field error occurred on a input field which was removed.
Hey @FluorescentHallucinogen :wave:,
Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our Open Collective and consider backing us.
https://opencollective.com/graphql-shield
PS.: We offer
prioritysupport for all backers. Don't forget to addprioritylabel when you start backing us :smile:
I am not sure I understand the idea behind your issue. Could you read my summary and verify that I correctly understand your problem?
First, let me clarify that docs in README are in a way misleading towards input types. You cannot apply rules to InputType however my reasoning behind it is that it makes very little difference in usage and a significant one in implementation of graphql-middleware and graphql-shield if we were to support "the" input types, as opposed to merely verifying arguments.
Back to the point, if I understand correctly, you would want to limit the arguments in a way that would delete the provided fields if they don't match the rule. Is this the expected behaviour that you are explaining? 🙂
@maticzav
you would want to limit the arguments in a way that would delete the provided fields if they don't match the rule. Is this the expected behaviour that you are explaining?
Yes.
docsin README are in a way misleading towards input types. You cannot apply rules toInputType
It would be nice to clarify the docs. :slightly_smiling_face:
@maticzav
it makes very little difference in usage and a significant one in implementation of
graphql-middlewareandgraphql-shieldif we were to support "the" input types, as opposed to merely verifying arguments.
My reasoning is applying rules directly to the input types (instead of arguments) is more natural and intuitive. This is how for example the another approach with GraphQL custom directives works (input types can be nested and reusable between more than one query/mutation and directives applies directly to the input types).
@maticzav
if we were to support "the" input types, as opposed to merely verifying arguments.
_in addition to_, not _as opposed to_. :wink:
Sometimes it may be useful to apply the rules to the argument instead of input types e.g. to
keep the "context" of input type in the case when the input types are reusable between more than one query/mutation (since input types are not self-sufficient things and can be used only in the "context" of specific queries/mutations).
compounded validation: checking (using) the values of multiple fields at the same time inside the rule.
@maticzav PTAL at the implementation by @uxname:
https://github.com/uxname/uxbackend/blob/master/src/helper/InputSheldFilter.js
Could you please integrate it (or something similar) into graphql-shield?
Hey đź‘‹,
Excuse my absence, I had final examinations at school, back at programming now. My point with nesting input types etc., stemmed from the idea that you can also reuse rules across your rule tree. Therefore, I don't see benefit in having rules applicable to input types if we could make them more declarative by applying the same rule in multiple places.
Perhaps I haven't thought this through completely, is the problem here that you cannot nest input rules when inputs take ”objects” as parameters?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.