auth and permissions on scalar fields only? By this, I mean:type Customer {
id: ID!
name: String!
sensitiveData: UserSensitiveData!
...
}
type Customer SensitiveData {
id: ID!
customer : Customer !
data1: String! # authorization verification from DB here in resolvers
data2: ... # authorization verification from DB here in resolvers
}
Rules:
export const permissions = shield({
Customer : allow,
CustomerSensitiveData: isUserCustomer
})
EDIT: I now have a feeling/understanding that this could leak fields like id in related type for an authenticated, but unauthorized access. For instance, id in Product is public, so purchasedProducts in type Customer, if not verified for authorization, could leak that id (and other product identifier) to an authenticated customer access trying to access other customer's resources. So, authorization should be on the edges, not on the nodes.
$exists from prisma client in resolvers to check if the user has that item, then only allow deletion). Should this constraint be somehow placed in the shield rule?Hey 馃憢,
I am not sure I understand your question entirely. In particular, what are you referring to with AuthZ? Maybe the example below could give you some ideas on how to tackle the issue.
type Query {
viewer: User
}
type User {
id: ID!
email: String!
tickets: [Ticket!]!
}
type Ticket {
id: ID!
event: PublicEvent!
owner: User!
isValidated: Boolean!
isExpired: Boolean!
}
const isUserTicketOwner = rule({
cache: 'strict',
fragment: 'fragment TicketId on Ticket { id } ',
})(async ({ id }, args, ctx: Context) => {
try {
const userId = getUserId(ctx)
return ctx.prisma.exists.Ticket({
id: id,
owner: { id: userId },
})
} catch (err) {
return false
}
})
export const permissions = shield(
{
Query: {
viewer: allow,
},
User: isUserAuthenticated,
Ticket: or(isUserAdministrator, isUserModerator, isUserTicketOwner),
},
{
debug: process.env.NODE_ENV !== 'production',
fallbackError: 'To pa ne gre...',
fallbackRule: deny,
},
)
That's how I would approach writing permissions. As you can see, User only checks whether user is indeed authenticated, while Ticket also verifies that current user owns it.
I hope this helps you solve your problem 馃檪
@maticzav Sorry for playing cool :( By authZ, I meant "authorization". Have updated my post, sorry!
Also, I had taken ideas from your code repo and have done similar thing, except that against point 2, I have a generic function that takes as argument what to check for ownership in the DB (since, a user could have multiple relations, like tickets: [Ticket!] from your example).
So, basically I was asking then if such a single could do, or should I instead write individual ones e.g. isUserTicketOwner, isUserPostOwner, isUserAddressOwner, isUserPresidentOfUSA, etc.
Please feel free to point me to any more of my stupidity in this approach. Thanks a lot, you have been always very helpful :)
@devautor no worries, I could have guessed that! 馃檲 What you could do is set up an interface type and somehow validate the ownership that way, however, I am not entirely sure how would that work.
@maticzav Doing something similar without type validation in this step, like I added that with a function.
Hey :wave:,
We saw you use our package. To keep our code as accessible as possible, we decided to open source it and are now helping others with their questions.
In a pursuit to continue our work, help us by donating to our collective! :heart:
Most helpful comment
Hey 馃憢,
I am not sure I understand your question entirely. In particular, what are you referring to with
AuthZ? Maybe the example below could give you some ideas on how to tackle the issue.That's how I would approach writing permissions. As you can see,
Useronly checks whether user is indeed authenticated, whileTicketalso verifies that current user owns it.I hope this helps you solve your problem 馃檪