Skip to main content

Permissions

The server makes sure that users have permissions to perform certain actions.

By default, the following rules are set:

Document permissions

  • 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

Annotation permissions

  • 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

Snapshot permissions

  • 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.

How permissions work#

Permissions behave slightly different depending on if the user is trying to read or write data.

Reading 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).

Writing data

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.

Customizing permissions#

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).

The permissions object has three properties, CollabServer.Permissions.Entities.DOCUMENT, CollabServer.Permissions.Entities.ANNOTATION, and CollabServer.Permissions.Entities.SNAPSHOT. All of these are optional.

import CollabServer from '@pdftron/collab-server';
const server = new CollabServer({
...otherOptions,
permissions: {
[CollabServer.Permissions.Entities.DOCUMENT]: {
},
[CollabServer.Permissions.Entities.ANNOTATION]: {
},
[CollabServer.Permissions.Entities.SNAPSHOT]: {
}
}
});

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:

import CollabServer from '@pdftron/collab-server';
const server = new CollabServer({
...otherOptions,
permissions: {
[CollabServer.Permissions.Entities.DOCUMENT]: {
[CollabServer.Permissions.Actions.EDIT]: CollabServer.Permissions.Roles.DOCUMENT_MEMBER
},
}
});

Actions#

The possible actions are listed below (you can also view the API docs here)

NameDescription
CollabServer.Permissions.Actions.ADDadding an entity
CollabServer.Permissions.Actions.EDITediting an entity
CollabServer.Permissions.Actions.READreading/viewing an entity
CollabServer.Permissions.Actions.DELETEdeleting an entity
CollabServer.Permissions.Actions.INVITEinviting someone to an entity

Roles#

The possible roles are listed below (you can also view the API docs here)

NameDescription
CollabServer.Permissions.Roles.ANNOTATION_AUTHORThe user must be the auth of the annotation to perform the action
CollabServer.Permissions.Roles.DOCUMENT_AUTHORThe user must be the document of the author to perform the action
CollabServer.Permissions.Roles.DOCUMENT_MEMBERThe user must be a member of the document to perform the action
CollabServer.Permissions.Roles.SNAPSHOT_AUTHOROnly applies to snapshots. Only the author of the snapshot can perform the action
CollabServer.Permissions.Roles.ANYAnyone can perform the action

Custom roles#

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:

import CollabServer from '@pdftron/collab-server';
const whitelist = [
'joe@email.com',
'bob@email.com'
]
const server = new CollabServer({
...otherOptions,
permissions: {
[CollabServer.Permissions.Entities.DOCUMENT]: {
[CollabServer.Permissions.Actions.ADD]: (document, userId) => {
const user = await myDB.query(`SELECT * FROM users WHERE id = ${userId} LIMIT 1`);
const { email } = user;
return whitelist.includes(email);
}
},
}
});

Permission caching#

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
info

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).

const server = new CollabServer({
...otherOptions,
permissionCacheSettings: {
// The maximum amount of time an entry can remain in the cache (in MS). Defaults to one hour
ttl: 1000 * 60,
// The maximum number of entries that can be stored in the cache at one time. Defaults to 5000
maxCacheSize: 1000,
// If set, reading a value from the cache will reset the TTL. Defaults to false
resetAgeOnCheck: true
}
});

This is an in-memory cache, so restarting the server will clear the cache.

Troubleshooting permissions#

If you are seeing unexpected behavior related to permissions, turn on debug logs by adding the following lines to your server constructor:

import CollabServer from '@pdftron/collab-server'
new CollabServer({
...otherOptions,
logLevel: CollabServer.LogLevels.DEBUG,
filterLogsByTag: CollabServer.LogTags.PERMISSIONS,
})

Troubleshooting permission caching

import CollabServer from '@pdftron/collab-server'
new CollabServer({
...otherOptions,
logLevel: CollabServer.LogLevels.DEBUG,
filterLogsByTag: CollabServer.LogTags.PERMISSION_CACHE,
})