Andrii
01/20/2025, 5:33 PM{
"document_1": {
"editors": [{explicit_user_1: ..}, {explicit_user_2: ...}, {}],
"viewers": [{explicit_user_3: ...}, {implicit_user_1: ...}]
}
}
one of the suggestions I had previously in this chat is to create a new table in the Spanner and just duplicate what I'm sending to SpiceDB. So when I need m2m list - I go do to that table and do JOIN, and when I need to answer a question "if user A is a collaborator on doc C" I can ask SpiceDB
Q2: Is anybody doing that?
and last but not least (tricky one)
Q3: what if some of collaborators have access to the doc not explicitly, but by being admins of folders, groups, organization, etc?
Materialize would return that data too, but in my case I can't pre-compute all of that by myself and store it in the prod DB.
What can you suggest please in this case? (or LookupResources and CheckBulkPermissions are the only options left? <- will slow down the response time)vroldanbet
01/20/2025, 6:10 PMReadRelationships
. The second one requires you to compute permissions, so there is no no way to keep computed permissions in your Spanner table unless you essentially build your own Materialize.
Q3. This touches on what I mentioned on Q2: it's not the same building an API that returns access grants (e.g. a user has a role assigned) versus an API that returns the side-effects of a grant (user1 can perform "edit" because they have been granted role "editor", or because they are org admin). Your schema should make explicit distinction between the roles granted (usually modeled with relation
, and the actions they can perform, usually modeled with a computed permission using permission
).
So assuming you have permissions like edit
, view
and the like, and you assuming you the API example you described wants to show all users organized by permission, then you'd need to do multiple LookupSubjects
calls, one per each permission your want to return as part of the API response. This is likely not going to scale as you'll have to do N times LookupSubjects
. Even if it did, that API response needs some sort of pagination, as the list of users can get pretty large. LookupSubjects
does not currently support pagination, but we have some ideas on how to do it.vroldanbet
01/20/2025, 6:12 PMvroldanbet
01/20/2025, 6:13 PMvroldanbet
01/20/2025, 6:15 PMReadRelationships
(see [the docs](https://authzed.com/docs/spicedb/modeling/access-control-management).))
- an Audit API (i.e. return all the effective permissions for all resources and all permissions) for which I don't know of a way to make it scale without denormalizing everything (like Materialize does)Andrii
01/20/2025, 6:49 PMvroldanbet
01/21/2025, 11:09 AMReadRelationships
as much as possible, and I'd probably tackle it as you described in 2).
Let's assume a design as such:
definition org {
relation owner: user
permission admin = owner
}
definition document {
relation org: org
relation viewer: user
relation editor: user
permission view: viewer + edit
permission edit: editor + org->admin
}
definition user {}
If you wanted to build a UI to manage permission of an individual document (let's say document1
), you could do the following (I'm going to use zed
as a way to issue these calls, but you'd do the equivalent via the API call):
- read all collaborators to document1: zed relationship read document:document1
. This would return all relationsihps for org
, viewer
and editor
relations
- you'd render for each user assigned their corresponding role, e.g. Andrii -> editor, vroldanbet->viewer
- you can do several things to handle the owner scenario:
- you canallow the UI user to add a new user, for which you'd check if they are already an owner (which you could check with zed relationship read org:my_org owner user:candidate_user
, and if that's the case, it will rendered with the highest possible permission.
- alternatively, you could to show the users that have implicit permissions in the list already and not allowing anyone to grant those owner users permission
- another thing you can do is use WriteRelationship
preconditions. For example, you could allow granting a role to a user, but only if the are not an owner in the org.
This way you don't need to think about computed permissions if you stick to the idea of "access grants".
As a side note: I'd recommend explicitly differentiating the concept of grant (e.g. role a user is assigned) from permissions (actions a user can perform on a doc).