Report an issue

guideUsers

Since multiple users are working on the same document, the information about these users needs to be stored in the editor.

To set and read the users data, use the Users plugin and other related plugins. The users plugin is automatically provided if you load any of the collaboration features plugins.

It is important that the users data is set before collaboration features are loaded. To do that, create a plugin which requires all collaboration features you use and which defines the users.

// An example of a plugin that provides user data for an editor
// that uses `Comments` and `RevisionHistory` plugins.
class UsersIntegration extends Plugin {
    static get requires() {
        return [ 'Comments', 'RevisionHistory' ];
    }

    init() {
        const users = this.editor.plugins.get( 'Users' );

        // Provide user data from your database.
        users.addUser( {
            id: 'u1',
            name: 'Kate Smith'
        } );

        users.addUser( {
            id: 'u2',
            name: 'Joe Doe'
        } );

        // Define the local user.
        users.defineMe( 'u1' );
    }
}

// ...

ClassicEditor.create( document.querySelector( '#editor' ), {
    extraPlugins: [ UsersIntegration ],
    // ...
} );

Keep in mind that in case of real-time collaboration applications, users are set and managed automatically by the real-time collaboration plugins and the Cloud Services server, hence you should not use permissions API.

The real-time collaborative editing plugin will define user data and permissions automatically based on your token data.

# Anonymous user

If for some reason you don’t want to, or you can’t provide the user data, you can use the anonymous user:

const usersPlugin = editor.plugins.get( 'Users' );

usersPlugin.useAnonymousUser();

usersPlugin.me.name; // 'Anonymous'
usersPlugin.me.id; // 'anonymous-user'

The anonymous user’s avatar is a contour of a human face.

The anonymous user’s ID can be set using config.users.anonymousUserId property:

ClassicEditor.create( document.querySelector( '#editor' ), {
    // ...
    users: {
        anonymousUserId: '0'
    }
} );

# User permissions

In many applications, the document creation workflow consists of several precisely defined steps such as: content creation, discussion, proof-reading, final review and acceptance etc. The users of such an application may have certain roles and permissions.

It is possible to change permissions for a given user, which results in enabling or disabling some editor functionalities.

For real-time collaboration applications, please refer to the Roles and permissions guide in the Cloud Services documentation.

Permissions are set using the Permissions plugin. It is automatically provided if you load any of the collaboration features plugins.

It is a good practice to set permissions directly after the users are defined:

class UsersIntegration extends Plugin {
    // ...

    init() {
        const users = this.editor.plugins.get( 'Users' );

        // Provide user data from your database.
        users.addUser( {
            id: 'u1',
            name: 'Kate Smith'
        } );

        users.addUser( {
            id: 'u2',
            name: 'Joe Doe'
        } );

        // Define the local user.
        users.defineMe( 'u1' );

        // Set permissions.
        const permissions = this.editor.plugins.get( 'Permissions' );

        // "Commentator" role.
        permissions.setPermissions( [
        	'comment:write'
        ] );
    }
}

The full list of defined permissions is available in the Permissions plugin description.

Remember that your application should be secured both on front-end and back-end. Even though the users will not be able to do some actions through the editor, you should still take care of securing incoming data in your back-end code.

# Operation authors

The Users#getOperationAuthor() method gives you an ability to check which user created a given operation. This is useful when creating custom features in integrations using real-time collaboration.

There are two cases when the operation author might be null:

  1. For initial operations (fetched from the server when connecting).
  2. For some automatically created operations which are not meaningful (NoOperations).

Below is an example of using getOperationAuthor() to find out which user was the last to edit the document. Note that in this case you should skip NoOperations and some MarkerOperations since they do not affect the document content.

let lastUser = null;

editor.model.on( 'applyOperation', ( evt, args ) => {
    const users = editor.plugins.get( 'Users' );
    const operation = args[ 0 ];

    if ( operation.isDocumentOperation && affectsData( operation ) ) {
        const user = users.getOperationAuthor( operation );

        if ( user && user != lastUser ) {
            lastUser = user;

            console.log( lastUser.name, lastUser, operation );
        }
    }

    function affectsData( operation ) {
        return operation.type != 'noop' && ( operation.type != 'marker' || operation.affectsData );
    }
} );

# Theme customization

It is possible to define colors used to represent the selection of other users.

By default, 8 colors are defined for users. Like in the whole CKEditor 5 Ecosystem PostCSS is used to handle styles with the power of CSS Variables. With Inheritance of CSS Variables you can change the default colors.

A color with an alpha channel (--ck-user-colors--$(number)-alpha) is dedicated for selections (.ck .ck-user__selection--$(number)). The rest of the classes use colors defined as --ck-user-colors--$(number). Feel free to change this color palette to fit your UI.

/* The current color set for users in the collaboration plugins. */
:root {
    --ck-user-colors--0: hsla(235, 73%, 67%, 1);
    --ck-user-colors--0-alpha: hsla(235, 73%, 67%, 0.15);

    --ck-user-colors--1: hsla(173, 100%, 24%, 1);
    --ck-user-colors--1-alpha: hsla(173, 100%, 24%, 0.15);

    --ck-user-colors--2: hsla(0, 46%, 50%, 1);
    --ck-user-colors--2-alpha: hsla(0, 46%, 50%, 0.15);

    --ck-user-colors--3: hsla(256, 54%, 45%, 1);
    --ck-user-colors--3-alpha: hsla(256, 54%, 45%, 0.15);

    --ck-user-colors--4: hsla(95, 50%, 36%, 1);
    --ck-user-colors--4-alpha: hsla(95, 50%, 36%, 0.15);

    --ck-user-colors--5: hsla(336, 78%, 43%, 1);
    --ck-user-colors--5-alpha: hsla(336, 78%, 43%, 0.15);

    --ck-user-colors--6: hsla(0, 80%, 59%, 1);
    --ck-user-colors--6-alpha: hsla(0, 80%, 59%, 0.15);

    --ck-user-colors--7: hsla(184, 90%, 43%, 1);
    --ck-user-colors--7-alpha: hsla(184, 90%, 43%, 0.15);
}

These colors are, among other, used in the users presence list to represent users.

# Adding more user colors

You can define additional colors for users if you find the default set too small.

First, prepare a CSS file with additional color definitions:

// mycolors.css

/* Import the "userColor" mixin to create definitions easily. */
@import "@ckeditor/ckeditor5-collaboration-core/theme/usercolormixin.css";

/**
 * Add some new definitions. The parameters for the "userColor" mixin are:
 *
 * - color without alpha channel (main color),
 * - color with alpha channel (selection marker color),
 * - color ordering number.
 */
@mixin userColor hsla(31, 90%, 43%, 1), hsla(31, 90%, 43%, 0.15), 8;
@mixin userColor hsla(61, 90%, 43%, 1), hsla(61, 90%, 43%, 0.15), 9;

Then, import the above CSS file and specify the colorsCount configuration option:

import './mycolors.css';

ClassicEditor.create( document.querySelector( '#editor' ), {
    // ...
    users: {
        colorsCount: 10
    }
} );