-
-
Notifications
You must be signed in to change notification settings - Fork 171
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
Cue validation for query and mutations variables #361
Conversation
examples:queryquery @validation(cue:$validation) {
users(where: {id:$id},limit:$limit) {
id
email
}
} variables: {
"id":5,
"limit":1,
"validation": "id: int, limit: int & <10"
} mutationmutation @validation(cue:$validation) {
users(insert:$inp) {
id
email
}
} variables: {
"inp":{ "id":101, "email":"mail3@example.com", "full_name":"Full Name", "created_at":"now", "updated_at":"now" },
"validation": "inp: {id?: int & >100 & <102, full_name: string , created_at:\"now\", updated_at:\"now\", email: string}"
} |
This is truly amazing I had never really looked into cuelang. I think this will make our validations turning complete :) One bug I can see is that while you're correctly compiling the cue script at compile time and saving the compiled object into the In production compiling is only done once and from then on variables are converted to sql values and directly sent to the db prepared statement validation will be skipped. The fix here is to do the validation (below code) in the
|
Thanks! I'm glad to help. I think one of the reason that this amazing project is under-rated is the lack of contribution guide in wiki. also some part of the wiki is outdated. for example there is no |
examples for prepared queries in productioncreate name: getUserWithValidation
query: |-
query getUserWithValidation @validation(cue:"close({limit:int & <=10})") {
users(order_by: {created_at: desc}, limit: $limit) {
...User
}
}
vars: '{}' in cue schema an other example with validation as var (in this case we will not have name: getUserWithValidationVar
query: |-
query getUserWithValidationVar @validation(cue:$schema) {
users(order_by: {created_at: desc}, limit: $limit) {
...User
}
}
vars: |-
{
"schema":"close({limit: \"4\" | \"5\" })"
} cue schema explanation : only |
I totally agree and my main focus is to fix documentation. I'm currently exploring using
I'm not sure what format GraphQL client like Apollo and URQL expect with errors if any. But I'm up for moving to this format I agree more information is better with errors.
We have a feature called https://pkg.go.dev/github.com/dosco/graphjin/core#OptionSetNamespace |
I like this ^^^ the best it fits the model of how GraphJin does things better.
This wont work since only var are only stored when using a json object with mutations this is so that you don't have to write out the mutation in eg Example 1 - Mutation using JSON GQL
Variable JSON
Example 2 - Inline mutation GQL
Variable JSON
|
the docs should move to the site for sure, Github pages are not suitable for big projects or the ones that reader want navigate a lot. also it helps with SEO. docs that we can leave comments on them are +1 and will improve faster. about the errors, we can get help from gqlgen, I worked with it. worked fine with Apollo Client and graphql-request. namespaces are even better, if we can use them with k8s pods, for example having some pod that response to 'A' & 'B' namespaces and some other pods that only response to 'C' namespace. and how to target them with request we send? looking forward to read about this at new docs! about the contribution guide I like to leave a comment of how I did it: for prod build had to do the whole thing again (except downloading mods) with for testing, docker didn't help at all. I cd into |
mutation worked too: name: createUserWithProducts
query: |-
mutation createUserWithProducts @validation(cue:$schema){
users(insert: $data) {
id
}
}
vars: |-
{
"schema":"data:id: >100, data:products:[{id:>10}, ...]",
"data": {
"id": 0.0,
"email": "",
"full_name": "",
"created_at": "",
"updated_at": "",
"products": [
{
"id": 0.0,
"category_ids": [0.0],
"created_at": "",
"updated_at": ""
}
]
}
} req query : {
"data": {
"id": 103,
"email": "email3@example.com",
"full_name": "Bob",
"created_at": "now",
"updated_at": "now",
"products": [
{
"id": 13,
"category_ids": [
1
],
"created_at": "now",
"updated_at": "now"
}
]
}
} res data: {
"data": {
"users": [
{
"id": 103
}
]
}
} there was no way to miniplate the schema var, even the user can not see the value of it to find a possible bug, that's what I like about it. |
This wont work since the dev web app (Apollo / URQL) will have the whole GraphQL query in it with the clue lang value of If you want to store this validation in the backend and hide it from users then just set it in the dev.yml
GQL
https://github.com/dosco/graphjin/wiki/Guide-to-Config-Files |
the update: I'm working on it to find a way to pass the schema value into query file. |
two new bugs I found during playing with prepared queries:
|
The allow list files are not meant to be hand-edited they are auto-generated from the queries executed in dev mode. They are not the right place to put prefixed variables those should be in the yml config files. The second your app while developing executes the same query (like when you reload the page) your allow list file for that query will be over-written and you will loose the schema value that you had manually set.
Yes in production it only uses the name of the query and variables which is why this works. |
For 99% of the folks out there the same client code makes the query in dev and production there is no way people will have two code paths (client side) this path to use just the name in production queries is not the way we should proceed. If folks want to make lightweight calls they use APQ which is supported by GraphJin. https://www.apollographql.com/docs/apollo-server/performance/apq/ |
If this is the problem you're trying to solve either we can make the parser support double quotes or use single quotes for the schema and then double quotes will be supported inside. |
If you are ok with merging this without the |
I implemented a way that makes
result example: name: myMutation
query: |-
mutation myMutation @validation(cue:$_schema) {
users(insert:$data) {
id
}
}
vars: |-
{
"_schema": "data:id:>10",
"data": {
"created_at": "",
"email": "",
"full_name": "",
"id": 0,
"updated_at": ""
},
"extra_var_in_req": 0
} |
the double quote problem is not a deal breaker. and it doesn't worth the effort to change the parser. the problem is just for strings inside cue schema passed through graphql, not variables. at the end of the day, schema should be passed with vars for safety (and keeping it hidden). |
I'll highly recommend we keep this merge simple and not focus on changing how the allow-list works. Keeping the validations secret can be something we work on in second pass. For now we can just use config variables to keep the validations secret. I really don't want to introduce this new complex behaviour to the allow list without some though. I'll give this some though to how can have secret variables that as passed in as part of the same dev query after we merge this. Also updating the parser to support double quotes etc is not hard I can handle that. See this below link for how config variables work: |
all right, it passed the tests and as long as cue works fine, it works fine. I'm ok with merging now if you are. we can improve it in future PRs. |
checkout tests for examples.
limitations: