Fork me on GitHub
#pathom
<
2022-11-02
>
Eric Dvorsak19:11:17

is it possible to limit which resolvers can be used as entry points for a parser while still using all of them for the resolution of attributes? eg it's really complex to come up with an authorization system that would efficiently (both in terms of code and execution time) protect attributes some resolvers could be used directly in a query and require complex authorization code when in practice they are always used from a context where parent attributes have already been authorized

roklenarcic21:11:59

that would break the general idea of it all it seems

Eric Dvorsak09:11:38

@U2J4FRT2T yes I think the wrapped parser from the readme could be an interesting approach. Just not sure how to make it performant eg. work well with batched queries. In my case the user have access to some top level entities. I will need to find a solution so that when the child entities are accessed within the context of a top level entity this is grabbed from the env. When a child is accessed directly the resolver should find the parent (sometimes a few levels of nesting)

Pragyan Tripathi15:11:09

I have gotten around it by creating environment dynamically based on the permissions the user has. We register the pathom environment as one of the middleware step. and then use that environment to resolve the queries. As environment doesn’t have resolvers that the user is not supposed to resolve… It fails with 404…

caleb.macdonaldblack17:11:36

@U03K8V573EC My thoughts are that the index is a graph, not a tree. So there may not be a parent as it could be cyclic. :house/occupants -> occupant/house -> house/occupant.

Eric Dvorsak17:11:36

well in my model that would rather be: :house/occupants -> user/house (it looks like a many-to-one relationship) if we go deeper let's say you have house/rooms -> room/house and room/windows -> window/room only occupants of the house should be able to access these items only an occupant should be able to query {[:window/id x] [:window/attributeX]}

Eric Dvorsak17:11:57

so I'm looking for a way to make this as automated as possible the approach I'm experimenting with is to leverage resolvers so the window/authorized? resolver will need room/authorized? resolver as input and the room/authorized? will need house/authorized? house/authorized? simply checks that the current user is an occupant this won't work with resolvers alone because if authorized? is an input of the id-resolvers, you can't resolve eg the window/room to resolve room/authorized? so what I'd try is to augment the query to add :authorized attribute to the queries and then clean up results when it's false, preferably at entity level rather than after full resolution alternatively something I already got working but didn't like was to have an unauthorized resolver for entities, which nests attributes in eg :window/unauthorized, then a resolver that takes that nested input + parent/authorized as input and returns the regular output attributes. this resolves the parents authorization recursively (you'd have to also forbid direct access to the unauthorized resolvers else someone can request window/unauthorized attributes to bypass)

caleb.macdonaldblack23:11:31

I would solve this by creating an index based on permissions before processing the query. Find what top level resolvers the user has permissions for and then traverse the plan to figure out what can be accessed. Once you know what resolvers can be accessed, create a new index with just those resolvers and run the query

caleb.macdonaldblack23:11:16

Maybe you can tag resolvers with some meta data or something to denote whether or not it’s a resolver that requires permissions. You would need to be careful because it seems like it would be easy to unintentionally make a connection from a resolver it has permission for, to one it doesn’t.

caleb.macdonaldblack23:11:53

And your plan traversal would just assume it’s permitted because there is a relationship.

caleb.macdonaldblack23:11:10

And if you want to use Pathom to to solve the problem of what resources your user has access to, then you can create a separate index for that for internal use only where the query is controlled.

caleb.macdonaldblack23:11:10

So one index determines the permissions and is only internally accessible. Then use the result of that to dynamically filter your other index of resolvers it can access.

caleb.macdonaldblack23:11:16

The main thing being the creation of the environment/index based on user permissions. Essentially what @U02JRAM6CBA is suggesting

👍 1
Eric Dvorsak10:11:49

A separate index would not work, because the permissions are per entity not resolvers. So as the occupant of a house I should be able to query a room/window by indent IF it's in my house, but I shouldn't be able to query the neighbor's

Eric Dvorsak10:11:56

what I like about my current poc is that it lets pathom deal with figuring out permissions. This means that i also benefits from caching and batching mechanisms (I'm using pathom3 which is much better at batching than pathom2)

roklenarcic13:11:59

How do you expect pathom planner to work around your system. Resolvers describe which attributes can be derived from other attributes, and you are attempting to twist that into something that gatekeeps access to a particular instance of information such as house/window 44 . It will not work. Ideas like hacking the index also don’t work. You’ll need to just check if entity is accessible in the resolvers. It’s just straightforward like that.

Eric Dvorsak13:11:50

@U66G3SGP5 right now the only thing that doesn't work is that the runner uses the incomplete nested input, and I suspect it is related to https://github.com/wilkerlucio/pathom3/issues/167

Eric Dvorsak14:11:21

> Resolvers describe which attributes can be derived from other attributes which is the reason I want to try to do it that way, because authorization in my use-case is derived from other attributes > you are attempting to twist that into something that gatekeeps access to a particular instance of information what I'm doing is resolving attributes in 2 steps, first step is a simple resolver that gets the attribute but is nesting them in an attribute/unauthorized key, second step is a resolver that takes the nested attributes as input and an authorization attribute and un-nests the attributes. the authorization attribute is resolved using the nested attributes, eg window/authorized? will take window/id and room/authorized? as input, room/authorized? will take room/id and house/authorized? house/authorized? will take house/id so let's say you get window/material for [window/id 1]:

regular resolver
{:window/unauthorized {:window/id 1 :window/material :wood :window/room 6}}
room resolver
{:window/unauthorized {:window/id 1 :window/material :wood :window/room 6 :room/unauthorized {:room/id 6 :room/house 2}}}
house-authorized (if not authorized, will throw and rest of query can't continue)
{:window/unauthorized {:window/id 1 :window/material :wood :window/room 6 :room/unauthorized {:room/id 6 :room/house 2 :house/authorized? true}}}
room authorized
{:window/unauthorized {:window/id 1 :window/material :wood :window/room 6  :room/id 6 :room/house 2  room/authorized? true :house/authorized? true}}}
window authorized
 {:window/id 1 :window/material :wood :window/room 6  :room/id 6 :room/house 2  room/authorized? true :house/authorized? true :window/authorized? true}}}

Eric Dvorsak14:11:26

ofc you need to purge the query of attribute/unauthorized keys

Eric Dvorsak14:11:10

actually I don't think my current issue is with indexed nested attributes but rather batches terminating too early

caleb.macdonaldblack21:11:44

@U03K8V573EC how did you go with this auth stuff?

Eric Dvorsak22:11:17

It works if you don't do batch resolvers

Eric Dvorsak23:11:24

I'm trying to find what is going wrong in batches, i had a workaround that was working 1 time ou of 3 😅

Eric Dvorsak23:11:56

It would be huge because it would be close to impossible to have that granularity of authorizations with grapqhl, especially while leveraging batches for performance at the same time

Eric Dvorsak23:11:34

Of course you can always denormalize things a bit