OpenSearch-Dashboards
OpenSearch-Dashboards copied to clipboard
[RFC] Sharing Saved Objects Across Workspaces
Summary
This RFC proposes a design for sharing saved objects across workspaces in order to enable efficient sharing and collaboration between users across different workspaces. This RFC is created with taking object permission control(ACL) into consideration, but it should also applicable when ACL is disabled.
Background
- Workspace is a newly introduced feature which allows user to isolate saved objects by workspaces, documentation for workspace
- Object permission control(ACL) as describe here, it is a feature to allow user to manage the access to saved objects at individual object level or at workspace level.
Current design
When a saved object is initially created within a workspace, the saved object stores the workspace id in workspaces field, and the permission to this saved object inherits
{
id: <object-id>,
...
workspaces: [<workspace-a>]
}
When the object is shared into another workspace, the target workspace is added to the workspaces list. The permission of the saved object inherits that of the target workspace upon sharing. For example, if an user has write permission to workspace-b, the user will have write permission to the shared saved object as well:
{
id: <object-id>,
...
workspaces: [<workspace-a>, <workspace-b>]
}
Limitations
- The object permission inherit the workspace permission, this may not always be the desired behavior. We need to support readonly-share which the shared object can only be updated from the original workspace.
- The current design may make the object governance difficult, imagine a situation that an object been “shared” to multiple workspaces, and anyone with permission to any of the workspaces can update the object. Governance challenges arise when multiple workspaces have write access to shared objects.
- Once the object is “shared”, there is no way to tell the original workspace where it’s created. Loosing such metadata may limit us from extending the UI, for example, we may want to differentiate an ordinary object and a “shared” object from UI.
Proposed design
Option A
Instead of adding
{
id: <object-id>,
...
workspaces: [<workspace-a>, REF/<workspace-b>]
}
With this design, the permission of the object will no longer inherit from the workspace where the object was “shared” to, in other words, we can say the object is referenced in workspace-b, but only the original workspace defines the permission to this object.
Pros
- Supports readonly-share when ACL is enabled as the object permission is only defined by the original workspace.
- The object can only be updated from the original workspace which streamlined the object governance.
- Enables differentiation between original and shared workspaces for UI extension.
Cons
- It requires extra code logic to handle the prefix
REF/<workspace-id>
Option B
Refactor the current permission model to include workspace-specific permissions within the permissions field.
permissions: {
read: {
users: [],
groups: [],
workspaces: [
"workspaceA-read" /* Users with read permission to workspaceA has permission to read this object */,
"workspaceB-write" /* Users with write permission to workspaceB has permission to read this object */
]
},
write: {
users: [],
groups: [],
workspaces: []
}
},
workspaces: [workspaceA, workspaceB]
Pros
- Unifies permission modes and simplifies permission management.
- Provides a clean and structured approach to handling permissions.
Cons
- Coupled with permission control which is not intuitive.
- Requires more effort in implementation.
- multiple
workspacerelated fields which may be confusing:- The workspaces field in permissions indicates the permission control of the object.
- The workspaces field in object indicates if the object belongs to the specific workspaces.
This RFC is based on the discussion with @SuZhou-Joe @Hailong-am @xluo-aws @yubonluo
@AMoo-Miki @seraphjiang @zengyan-amazon @ashwin-pc @Flyingliuhub @kavilla would be really nice to have your thoughts :)
I'm onboard with Option A you have provided. Or we can do option A but change it does be an object like:
id: object-id
workspaces: [{ id: workspace-a, permissions: inherited (default if not included) } , { id: workspace-b; permissions: none } ]
But that might be too much extra work. So that said option A makes a lot of sense to me on a technical level as well and makes it easier to see that it's only a reference internally.
Will raise up in triage tmrw for others opinions as well.
A third option could be:
- Add an additional key to hold workspaces which can consume the saved object without making any changes to it:
{ id: <object-id>, ... workspace: <owning-workspace-id>, sharedWith: [<workspace-a>, <workspace-b>, ...] } - Workspace A and B can use the saved object without any access to change it
- Users of those workspaces who want to use a modified version of this saved object can clone it. Doing so, a new saved object is created where
workspaceis the ID of the new owning workspace andsharedWithis empty.
- Users of those workspaces who want to use a modified version of this saved object can clone it. Doing so, a new saved object is created where
Pros
- Unified experience and reduced friction due to ACL. Users understand that anything shared with them is read-only and can be cloned to make changes to.
Cons
- Involves some code change to turn the array of
workspacesinto a string ofworkspace.
- Users understand that anything shared with them is read-only and can be cloned to make changes to.
i think share both have read-only share and write share, with this we need a way to differentiate them.
i think share both have read-only share and write share, with this we need a way to differentiate them.
With option 3, we simplify that. No shared object is writable; they are all read-only. While it is nice to provide users with as many options as we can, too many options can distract and confuse users. A simple definition where a shared object is read-only, yet clone-able, would be easier for the users to understand and use.