KGraphQL icon indicating copy to clipboard operation
KGraphQL copied to clipboard

Property resolver with context

Open StefanLiebig opened this issue 7 years ago • 8 comments

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)

StefanLiebig avatar Dec 17 '18 08:12 StefanLiebig

Can you give a use case of where this would be used? (I am new to GraphQL and Kotlin :))

shamresh avatar Dec 17 '18 16:12 shamresh

The context could hold a security context which could be used to check permissions, e.g. restrict visibility of data.

StefanLiebig avatar Dec 17 '18 16:12 StefanLiebig

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

AlphonseSantoro avatar Dec 18 '18 12:12 AlphonseSantoro

Ah, ok - Thanks!

.. but i dont want the user to edit posts of other users

Is this about mutations?

StefanLiebig avatar Dec 18 '18 14:12 StefanLiebig

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.

AlphonseSantoro avatar Dec 18 '18 15:12 AlphonseSantoro

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.

StefanLiebig avatar Dec 20 '18 10:12 StefanLiebig

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?

pgutkowski avatar Jan 10 '19 09:01 pgutkowski

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?

NataliiaVallander avatar Jan 11 '19 08:01 NataliiaVallander