-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
feat(GraphQL): Support auth with custom DQL #7775
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 9 files at r1.
Reviewable status: 1 of 9 files reviewed, 8 unresolved discussions (waiting on @minhaj-shakeel and @pawanrawal)
graphql/dgraph/graphquery.go, line 217 at r1 (raw file):
writeFilterArguments(b, q.Func.Args, q.Func.Attr, q.Func.Name)
maybe just pass q.Func
and use that in the function
graphql/dgraph/graphquery.go, line 223 at r1 (raw file):
} func maybeQuoteArg(fn string, arg interface{}) string {
I think we have a similar function in resolve
pkg. Can't we reuse that here?
If it's a package dependency issue, we can move that function to a higher level package in the dependency tree (schema
pkg), or in the packagex
.
graphql/e2e/auth/schema.graphql, line 991 at r1 (raw file):
$search: string
stale
graphql/e2e/auth/schema.graphql, line 997 at r1 (raw file):
orderdesc: val(age)
can this directly work here? as the map age
is a map from owner uid to age value, while the root func here is iterating over the Issue uids. So, I think this might not produce the intended results after all.
This var query might be needed:
iss as var(func: type(Issue)) @filter(has(Issue.owner)) {
Issue.owner {
age as User.age
}
ownerAge as max(val(age))
}
Then use val(ownerAge)
in the orderdesc
.
graphql/resolve/custom_auth_query_test.yaml, line 26 at r1 (raw file):
} - name : "custom DQL query with var block RBAC rules true"
can we also add another test where there are multiple var blocks in the DQL, and all of them are used in the user's query?
graphql/resolve/custom_auth_query_test.yaml, line 75 at r1 (raw file):
iss as var(func: uid(0x1)) @filter((uid(0x2) AND has(Issue.owner)))
👍
why is the AND has(Issue.owner)
here?
graphql/resolve/query_rewriter.go, line 641 at r1 (raw file):
Quoted 12 lines of code…
args := query.Arguments() vars := make(map[string]string) for k, v := range args { // dgoapi.Request{}.Vars accepts only string values for variables, // so need to convert all variable values to string vStr, err := convertScalarToString(v) if err != nil { return nil, err } // the keys in dgoapi.Request{}.Vars are assumed to be prefixed with $ vars["$"+k] = vStr }
we should put this in a function, this piece of code is being used at two places
graphql/resolve/query_rewriter.go, line 680 at r1 (raw file):
typeName = extractTypeFromFilter(dgQuery.Filter) return typeName
return extractTypeFromFilter(dgQuery.Filter)
also, should we try to extract type from order
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 10 files reviewed, 8 unresolved discussions (waiting on @abhimanyusinghgaur and @pawanrawal)
graphql/dgraph/graphquery.go, line 217 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
writeFilterArguments(b, q.Func.Args, q.Func.Attr, q.Func.Name)
maybe just pass
q.Func
and use that in the function
Done.
graphql/dgraph/graphquery.go, line 223 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
I think we have a similar function in
resolve
pkg. Can't we reuse that here?
If it's a package dependency issue, we can move that function to a higher level package in the dependency tree (schema
pkg), or in the packagex
.
Done.
graphql/e2e/auth/schema.graphql, line 991 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
$search: string
stale
Done.
graphql/e2e/auth/schema.graphql, line 997 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
orderdesc: val(age)
can this directly work here? as the map
age
is a map from owner uid to age value, while the root func here is iterating over the Issue uids. So, I think this might not produce the intended results after all.
This var query might be needed:iss as var(func: type(Issue)) @filter(has(Issue.owner)) { Issue.owner { age as User.age } ownerAge as max(val(age)) }
Then use
val(ownerAge)
in theorderdesc
.
Done.
graphql/resolve/custom_auth_query_test.yaml, line 26 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
can we also add another test where there are multiple var blocks in the DQL, and all of them are used in the user's query?
Done.
graphql/resolve/custom_auth_query_test.yaml, line 75 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
iss as var(func: uid(0x1)) @filter((uid(0x2) AND has(Issue.owner)))
👍
why is theAND has(Issue.owner)
here?
because it is attached in the query.
graphql/resolve/query_rewriter.go, line 641 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
args := query.Arguments() vars := make(map[string]string) for k, v := range args { // dgoapi.Request{}.Vars accepts only string values for variables, // so need to convert all variable values to string vStr, err := convertScalarToString(v) if err != nil { return nil, err } // the keys in dgoapi.Request{}.Vars are assumed to be prefixed with $ vars["$"+k] = vStr }
we should put this in a function, this piece of code is being used at two places
Done.
graphql/resolve/query_rewriter.go, line 680 at r1 (raw file):
Previously, abhimanyusinghgaur (Abhimanyu Singh Gaur) wrote…
typeName = extractTypeFromFilter(dgQuery.Filter) return typeName
return extractTypeFromFilter(dgQuery.Filter)
also, should we try to extract type from
order
?
Done. Added an example of order also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -112,7 +133,40 @@ func writeQuery(b *strings.Builder, query *gql.GraphQuery, prefix string) { | |||
} | |||
} | |||
|
|||
func writeUIDFunc(b *strings.Builder, uids []uint64, args []gql.Arg) { | |||
func writeNeedVar(b *strings.Builder, query *gql.GraphQuery) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment
} | ||
|
||
func writeFilterArguments(b *strings.Builder, args []gql.Arg) { | ||
for i, arg := range args { | ||
func writeFilterArguments(b *strings.Builder, q *gql.Function) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment. check if the condition needs to be updated.
|
||
type Query { | ||
|
||
queryIssueSortedByOwnerAge: [Issue] @custom(dql: """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix indentation if possible.
graphql/e2e/auth/auth_test.go
Outdated
result: `{"queryProjectsOrderByName":[{"name": "Project1"},{"name": "Project2"}]}`, | ||
}, | ||
{ | ||
name: "RBAC OR filter query; RBAC fail", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: RBAC false or user1 projects.
graphql/e2e/auth/auth_test.go
Outdated
{ | ||
name: "RBAC OR filter query; RBAC Pass", | ||
query: ` | ||
query{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: indent
} | ||
} | ||
|
||
- name : "Auth rules with deep filter missing JWT" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add an explanation field for easier understanding.
Variables: vars, | ||
} | ||
parsedResult, err := gql.Parse(dqlReq) | ||
for _, qry := range parsedResult.Query { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment
@@ -806,7 +995,7 @@ func (authRw *authRewriter) addAuthQueries( | |||
|
|||
// Adding the case of Query on interface in which None of the implementing type have | |||
// Auth Query Rules, in that case, we also return simple query. | |||
if typ.IsInterface() == true && implementingTypesHasAuthRules == false { | |||
if typ.IsInterface() && !implementingTypesHasAuthRules { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return false | ||
} | ||
|
||
func getFieldName(attr string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be add a TODO here or in query rewriter that dgraph directive with custom DQL auth won't work and is to be added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 10 files reviewed, 15 unresolved discussions (waiting on @abhimanyusinghgaur, @minhaj-shakeel, @pawanrawal, and @vmrajas)
graphql/e2e/auth/schema.graphql, line 990 at r2 (raw file):
Previously, vmrajas wrote…
Fix indentation if possible.
Done.
graphql/resolve/custom_auth_query_test.yaml, line 154 at r2 (raw file):
Previously, vmrajas wrote…
add an explanation field for easier understanding.
Done.
graphql/resolve/query_rewriter.go, line 648 at r2 (raw file):
Previously, vmrajas wrote…
Add a comment
Done.
graphql/resolve/query_rewriter.go, line 998 at r2 (raw file):
Previously, vmrajas wrote…
👍
Done.
graphql/resolve/query_rewriter.go, line 1728 at r2 (raw file):
Previously, vmrajas wrote…
May be add a TODO here or in query rewriter that dgraph directive with custom DQL auth won't work and is to be added.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 10 files reviewed, 7 unresolved discussions (waiting on @abhimanyusinghgaur, @minhaj-shakeel, @pawanrawal, and @vmrajas)
Fixes GRAPHQL-1171.
or the query:
|
Would be great if there was some example syntax. If I'm creating a |
Fixes GRAPHQL-1171.
This PR adds support for @auth on custom DQL queries.
This PR also adds the parsing step to the DQL query.
The Algorithm tries to figure out the
queried type
at the root of the query either from theroot func
orfilters
.Suppose if the root func is
func: type(Person)
orfunc: has(Person.name)
orfunc: eq(Person.age, 10)
thenit infers that the queried type is
Person
.However, there are certain DQL queries on which @auth rules are not added currently since the queried type is not clear.
for eg:
or the query:
This change is