type User {
username: String! @id
adminGroup: AdminGroup!
adminOf: [AdminGroup]
isAdmin: Boolean @depracated(reason:"admins are handled by AdminGroups")
}
type AdminGroup {
id: ID!
slug: String! @id #useful for reference without uid
overUsers: [User] @hasInverse(field:"adminGroup")
admins: [User] @hasInverse(field:"adminOf")
}
- Every user must be in an adminGroup
- Every AdminGroup should have an admin
- An AdminGroup can have multiple admins
On the User add the auth query rule:
@auth(query: {
or: [
# query own user
{ rule: "query ($USERNAME: String!) { queryUser(filter: { username: { eq: $USERNAME } }) { username } }" },
# admin can see all users they are over
{ rule: "query ($USERNAME: String!) { queryUser { adminGroup { admins(filter: { username: { eq: $USERNAME } }) { username } } } } " }
]
})
you could add another rule to let users see who their admins are if that is wanted/needed
But I think the OP aligns with this request:
Without this, implementing this across many types would entail a lot of boilerplate not to mention needing to always links nodes to an adminGroup. It would also be a faster query if we could just run an adhoc query and evaluate it as a rule.
Right now, rule
holds both RBAC and ABAC GraphQL query. ABAC is ran for all data trying to be accessed on a node based level and uses cascade under the hood.
It would be better if, rule
was split into rbac
and abac
and another was added for eval
and in eval, it did something sort of like a query with test condition.
E.G. run a query using USERNAME and expect result to contain data.queryUser.username
. I think a GraphQL testing library might be a good reference for exact syntax of an eval rule.