From 12d994275c0a4afa2344805e16998690a1c45a4d Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Wed, 2 Dec 2020 15:35:33 +0100 Subject: [PATCH 1/2] fix: retrieve awareness states after reconnect --- .../extension-collaboration-cursor/src/index.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/extension-collaboration-cursor/src/index.ts b/packages/extension-collaboration-cursor/src/index.ts index d44e33b0..a928b897 100644 --- a/packages/extension-collaboration-cursor/src/index.ts +++ b/packages/extension-collaboration-cursor/src/index.ts @@ -49,8 +49,8 @@ const CollaborationCursor = Extension.create({ */ user: (attributes: { [key: string]: any }): Command => () => { this.options.user = attributes + this.options.provider.awareness.setLocalStateField('user', this.options.user) - this.options.onUpdate(awarenessStatesToArray(this.options.provider.awareness.states)) return true }, @@ -66,6 +66,19 @@ const CollaborationCursor = Extension.create({ this.options.onUpdate(awarenessStatesToArray(this.options.provider.awareness.states)) }) + this.options.provider.awareness.on('update', () => { + this.options.onUpdate(awarenessStatesToArray(this.options.provider.awareness.states)) + }) + + this.options.provider.on('status', (event: { status: string }) => { + if (event.status === 'connected') { + // FIX: Reset the awareness state + // PR: https://github.com/yjs/y-protocols/issues/7 + this.options.provider.awareness.setLocalState({}) + this.options.provider.awareness.setLocalStateField('user', this.options.user) + } + }) + this.options.onUpdate(awarenessStatesToArray(this.options.provider.awareness.states)) return this.options.provider.awareness From 685132bbf8ae8ba34930be7e145ed180acfc7290 Mon Sep 17 00:00:00 2001 From: kriskbx Date: Wed, 2 Dec 2020 15:35:41 +0100 Subject: [PATCH 2/2] update collaborative editing guide --- .../docPages/guide/collaborative-editing.md | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/docs/src/docPages/guide/collaborative-editing.md b/docs/src/docPages/guide/collaborative-editing.md index 90e99c00..bbeb5482 100644 --- a/docs/src/docPages/guide/collaborative-editing.md +++ b/docs/src/docPages/guide/collaborative-editing.md @@ -205,17 +205,55 @@ Yes, it’s magic. As already mentioned, that is all based on the fantastic Y.js ## Store the content Our collaborative editing backend is ready to handle advanced use cases, like authorization, persistence and scaling. Let’s go through a few common use cases here! +### Authentication +With the `onConnect` hook you can write a custom Promise to check if a client is authenticated. That can be a request to an API, to a microservice, a database query, or whatever is needed, as long as it’s executing `resolve()` at some point. You can also pass contextual data to the `resolve()` method which will be accessible in other hooks. + +```js +import { Server } from '@hocuspocus/server' + +const server = Server.configure({ + onConnect(data, resolve, reject) { + const { requestHeaders } = data + // Your code here, for example a request to an API + + // If the user is not authorized … + if (requestHeaders.access_token !== 'super-secret-token') { + return reject() + } + + // Set contextual data + const context = { + user_id: 1234, + } + + // If the user is authorized … + resolve(context) + }, +}) + +server.listen() +``` + ### Authorization -With the `onJoinDocument` hook you can write a custom Promise to check if a client is authorized. That can be a request to an API, to a microservice, a database query, or whatever is needed, as long as it’s executing `resolve()` at some point. +With the `onJoinDocument` hook you can check if a user is authorized to edit the current document. This works in the same way the [Authentication](#authentication) works. ```js import { Server } from '@hocuspocus/server' const server = Server.configure({ onJoinDocument(data, resolve, reject) { - const { documentName, clientID, requestHeaders, clientsCount, document } = data + const { + clientsCount, + context, + document, + documentName, + requestHeaders, + } = data // Your code here, for example a request to an API + // Access the contextual data from the onConnect hook, in this example this will print { user_id: 1234 } + console.log(context) + // If the user is authorized … resolve() @@ -258,8 +296,14 @@ const server = Server.configure({ // executed when the document is changed onChange(data) { - const { documentName, clientID, requestHeaders, clientsCount, document } = data + const { + clientsCount, + document, + documentName, + requestHeaders, + } = data + // Your code here, for example a request to an API }, })