[PLAT-191] resource level sharing
Allows user to have access to only certain resources, for now limited to explore and canvas. Resources can be shared directly for a user or a usergroup.
Resource restriction works independently of the roles i.e. user or usergroup role can change but resource restrictions remains the same. This also allows to add user with a role with access to no resources at all. So this is possible
# Use --restrict-resources to not grant access to all resources
rill user add --project foo --email [email protected] --role viewer --restrict-resources
# Then set the resources they should have access to
rill user set-resources --project foo --email [email protected] --explore d1 --canvas d2 --canvas d3
Similar cmds for usergroups.
Existing APIs like AddProjectMemberUser and SetProjectMemberUserRole (and similar for usergroups) now accepts additional resource names and restrict-resources bool flag, if there are more than 0 resources in the call then restrict-resources is automatically set to true. The APIs works in PUT style i.e. with each call full list of resources should be provided and it just replaces the existing list, this means if resources are not set then resource list will be empty or if restrict resources flag is not set then essentially it give access to everything.
Permission Resolution
If all roles for a user/group have restrict resources set to true (AND of all flags) then only resource restrictions will apply and the effective resources will be union of all resources from role and groups.
Backwards compatibility
Since the APIs now accept additional params, UI needs to populate them always by first fetching current resource list and restrict resource flag otherwise it may unintentionally give access to everything. If application changes cannot go in with these changes then we may change the flag to be optional and if not set then fetch current resources/flag and use those. Also restrict APIs being called from older versions of CLI.
Follow up (Component level sharing)
An interesting follow up could be have component level sharing so that specific components from the canvas can be shared, this will require refactoring component's ResolveTransitiveAccess and then at canvas level it will just merge component level transitive accesses.
Checklist:
- [x] Covered by tests
- [x] Ran it and it works as intended
- [x] Reviewed the diff before requesting a review
- [x] Checked for unhandled edge cases
- [x] Linked the issues it closes
- [x] Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
- [ ] Intend to cherry-pick into the release branch
- [ ] I'm proud of this work!
@begelundmuller Going through the comments wanted to discuss few high level things-
- Merging project invites/setting roles with setting resources - I purposefully separated them, I don't remember exactly but it was adding too much logic in a single API. With separation its easy to just reject requests when there is pending invite with full role and then a resource level addition is done or ignore resource request when there is already a full role and there is not confusion around what role to set when resource sharing is done etc. So it just make things simpler I guess but I can club them together if you feel so.
- Clearing of resources on setting full role like viewer and removing viewer role when all resources are removed - Are we not okay with these two behaviour?
- Don't we want to clear all resources on setting any full role? Even a viewer role gives access to everything. Do we want to preserve shared resources list even when a full role is assigned to a user using some flag? But what is the use of this state? Do we expect that when the full role is removed we revert back to resource level access? that seems too much automatic things happening.
- When all resources are removed we just remove entire viewer role so that they don't accidentally get access to everything.
- It seems like from your comment above around
--restrict-resourceswe would want a state where they have viewer role but access to no resources but what is the use of this state? And we would want to add resources in 2 steps - first add user with--restrict-resourcesand the useset-resources?
- Incremental addition/removal of resources - We want to override resource list on each call?