Property resolver with context
While it is possible to pass an optional context object to the "execute" function of the Schema which than will be propagated to the "suspendResolver"/"resolver" functions of the "query" block, I have not found a way how this context object gets passed to the property resolvers.
(using version 0.3.0)
Can you give a use case of where this would be used? (I am new to GraphQL and Kotlin :))
The context could hold a security context which could be used to check permissions, e.g. restrict visibility of data.
You can access the context by using
type<Post>{
property(Post::id){
accessRule { post, ctx ->
if(post.id == ctx.get<String>()) null else IllegalAccessException()
}
}
}
and
query("black_mamba") {
resolver { -> Player("KOBE") }
accessRule { ctx -> if (ctx.get<String>().equals("LAKERS")) null else IllegalAccessException() }
}
What I'm missing is that you can access the properties and context in the query itself. e.g. I want a user to be able to read all posts but i dont want the user to edit posts of other users
Ah, ok - Thanks!
.. but i dont want the user to edit posts of other users
Is this about mutations?
Is this about mutations?
Both, it's about accessing properties in each query/mutation. When using the first example I gave, the access rule applies to all queries/mutations to that type. As of now i can't see there is any property access on query/mutation level.
Ok, I got your point! I have not yet used mutations, so I did not stumble upon this problem.
This 'accessRule' looks nice, but it prevents my use case. I do not want to do the permission checking in the graphql layer but a little bit deeper in the 'data' layer because a parallel REST-API also uses this 'data' layer.
So I would like to have the possibility to pass the context (more precise: just the authorization part of it) to the 'data' layer. The suspendResolver/resolver function inside a query accepts a context object as parameter so that I can forward it:
query("timeEntries") {
suspendResolver { ctx: Context, year: Int?, month: Int?, userId: UserId?, topicFK: Int?, timeEntryTypeFK: Int? ->
// forward "ctx" to the "data" layer.
}
}
Unfortunatlly, this is not possible with the property resolver.
Hi @StefanHub and @AlphonseSantoro
You can use Context in resolvers of queries, extension properties and transformations (I have to update the documentation), see: https://github.com/pgutkowski/KGraphQL/blob/780eda81b740dfe38631a615c1620de7aace05ae/src/test/kotlin/com/github/pgutkowski/kgraphql/schema/SchemaBuilderTest.kt#L321
But if I understand correctly, you would like to declare "resolver" for Kotlin properties as well, with access to property and context?
DSL example (not implemented yet):
type<Actor> {
property(Actor::name) {
resolver { actor : Actor, ctx: Context ->
if(ctx.get<UserData>()?.canAccessActorName){
actor.name
} else {
throw UnauthorizedAccessException()
}
}
}
}
Would this solve your use case?
UPDATE: Working from locally built version. Probably last release is too old
@pgutkowski This works, but still there is a problem -- schema became invalid. I am getting this in qraphiql:
Error: Invalid or incomplete schema, unknown type: null. Ensure that a full introspection query is used in order to build a client schema.
As I understand this is because Context become input type which is not defined.
If I am trying to define it as Input Type am getting an error that generic classes are not supported from handleInputValues method.
Do you have any suggestions how to fix this?