The server makes sure that users have permissions to perform certain actions.
By default, the following rules are set:
- Any user can create a document
- Only the author of a document can edit it
- Only document members (people who were invited) can view a document (unless the document is public)
- Only the author of a document can delete it
- Only the author of a document can invite users to it
- Only members of the document can add annotations to it
- Only the author of the annotation can edit it
- Only members of the document can view it
- Only the author of the annotation can delete it
- Only members of the document can create snapshots
- Only the author of the snapshot can edit it
- Any member of the document can read snapshots
- Only the author of the snapshot can delete it
- Only the document owner can revert a document to a snapshot
If you are not happy with these defaults, you can customize them as per the guide below.
Permissions behave slightly different depending on if the user is trying to read or write data.
If a user tries to read data that they do not have permissions for, that data is simply ignored / filtered out. For example, if a user loads a document but they do not have permission to read annotations, the document will still be loaded but no annotations will be displayed.
Permissions are also checked before firing real-time events. For example, imagine user 1 and user 2 are both viewing a document. User 1 creates a new annotation, but user 2 does not have read permissions. In this case, user 2 will not receive a real time update (because they do not have permission to view annotations).
If a user tries to write data and they do not have the proper permissions to do so, an error will be thrown on both the server and client. These errors can be caught on the client with the permission error events.
You can change the default permissions by passing a
permissions object to the server constructor.
The permissions object let you set entity level permissions for each action type (add, edit, delete, invite).
permissions object has three properties,
CollabServer.Permissions.Entities.SNAPSHOT. All of these are optional.
Permissions in the
DOCUMENT object apply to documents, and permissions in the
ANNOTATION object apply to annotations, and so on.
From here you can set permissions based on actions (add, edit, delete, invite). To do this set the key of the object to whatever action permission you want to set, and set the value to the role that the user must be to execute that action.
For example, to make it so that any member of a document can edit it, you would do:
The possible actions are listed below (you can also view the API docs here)
|CollabServer.Permissions.Actions.ADD||adding an entity|
|CollabServer.Permissions.Actions.EDIT||editing an entity|
|CollabServer.Permissions.Actions.READ||reading/viewing an entity|
|CollabServer.Permissions.Actions.DELETE||deleting an entity|
|CollabServer.Permissions.Actions.INVITE||inviting someone to an entity|
The possible roles are listed below (you can also view the API docs here)
|CollabServer.Permissions.Roles.ANNOTATION_AUTHOR||The user must be the auth of the annotation to perform the action|
|CollabServer.Permissions.Roles.DOCUMENT_AUTHOR||The user must be the document of the author to perform the action|
|CollabServer.Permissions.Roles.DOCUMENT_MEMBER||The user must be a member of the document to perform the action|
|CollabServer.Permissions.Roles.SNAPSHOT_AUTHOR||Only applies to snapshots. Only the author of the snapshot can perform the action|
|CollabServer.Permissions.Roles.ANY||Anyone can perform the action|
If you want more fine tuned control over the permissions, you can pass an auth function instead of a role that determines if the user is allowed to perform the action.
The function can be async and must resolve with true if the user is allowed to make the operation, or false otherwise.
authFunction(entity, userId, context): Promise<boolean>#
entity(Annotation | Document | Snapshot) the entity being operated on.
userId(string) the ID of the user who is trying to read or write the data
context(Context) context about the user. See the context guide for more info.
You can pass an
authFunction to any permission setting.
For example, if you want to make a whitelist of emails who can create documents, you could do this:
The Collaboration server heavily caches permission checks to help prevent making unnecessary queries to your database. The server currently caches the following information:
- Document membership status
- Document author status
- Annotation membership status
- Annotation author status
- Annotation ID to document ID relationships
If a custom permission function is provided, we do not cache the result, as the results could change from call to call. We recommend caching the results of custom roles yourself.
By default, the server will store a maximum of 5000 permission checks with a TTL of one hour using a first in first out method. However, these values can be configured using the
permissionCacheSettings option (these settings are all optional).
This is an in-memory cache, so restarting the server will clear the cache.
If you are seeing unexpected behavior related to permissions, turn on debug logs by adding the following lines to your server constructor:
Troubleshooting permission caching