diff --git a/packages/backend/server/src/core/doc/storage/doc.ts b/packages/backend/server/src/core/doc/storage/doc.ts index 1e5dd8cb02..8e439e7320 100644 --- a/packages/backend/server/src/core/doc/storage/doc.ts +++ b/packages/backend/server/src/core/doc/storage/doc.ts @@ -16,11 +16,13 @@ export interface DocRecord { docId: string; bin: Uint8Array; timestamp: number; + editor: string; } export interface DocUpdate { bin: Uint8Array; timestamp: number; + editor: string; } export interface HistoryFilter { @@ -61,7 +63,7 @@ export abstract class DocStorageAdapter extends Connection { const updates = await this.getDocUpdates(spaceId, docId); if (updates.length) { - const { timestamp, bin } = await this.squash( + const { timestamp, bin, editor } = await this.squash( snapshot ? [snapshot, ...updates] : updates ); @@ -70,6 +72,7 @@ export abstract class DocStorageAdapter extends Connection { docId, bin, timestamp, + editor, }; const success = await this.setDocSnapshot(newSnapshot); @@ -89,6 +92,7 @@ export abstract class DocStorageAdapter extends Connection { } abstract pushDocUpdates( + editorId: string, spaceId: string, docId: string, updates: Uint8Array[] @@ -97,6 +101,7 @@ export abstract class DocStorageAdapter extends Connection { abstract deleteDoc(spaceId: string, docId: string): Promise; abstract deleteSpace(spaceId: string): Promise; async rollbackDoc( + editorId: string, spaceId: string, docId: string, timestamp: number @@ -114,7 +119,7 @@ export abstract class DocStorageAdapter extends Connection { } const change = this.generateChangeUpdate(fromSnapshot.bin, toSnapshot.bin); - await this.pushDocUpdates(spaceId, docId, [change]); + await this.pushDocUpdates(editorId, spaceId, docId, [change]); // force create a new history record after rollback await this.createDocHistory(fromSnapshot, true); } @@ -173,6 +178,7 @@ export abstract class DocStorageAdapter extends Connection { return { bin: finalUpdate, timestamp: lastUpdate.timestamp, + editor: lastUpdate.editor, }; } diff --git a/packages/backend/server/src/core/sync/gateway.ts b/packages/backend/server/src/core/sync/gateway.ts index b026c430ef..b4279bb083 100644 --- a/packages/backend/server/src/core/sync/gateway.ts +++ b/packages/backend/server/src/core/sync/gateway.ts @@ -264,9 +264,11 @@ export class SpaceSyncGateway }; } + @Auth() @SubscribeMessage('space:push-doc-updates') async onReceiveDocUpdates( @ConnectedSocket() client: Socket, + @CurrentUser() user: CurrentUser, @MessageBody() message: PushDocUpdatesMessage ): Promise> { @@ -275,6 +277,7 @@ export class SpaceSyncGateway // TODO(@forehalo): we might need to check write permission before push updates const timestamp = await adapter.push( + user.id, spaceId, docId, updates.map(update => Buffer.from(update, 'base64')) @@ -448,8 +451,10 @@ export class SpaceSyncGateway }); } + @Auth() @SubscribeMessage('client-update-v2') async handleClientUpdateV2( + @CurrentUser() user: CurrentUser, @MessageBody() { workspaceId, @@ -462,7 +467,7 @@ export class SpaceSyncGateway }, @ConnectedSocket() client: Socket ): Promise> { - return this.onReceiveDocUpdates(client, { + return this.onReceiveDocUpdates(client, user, { spaceType: SpaceType.Workspace, spaceId: workspaceId, docId: guid, @@ -596,9 +601,9 @@ abstract class SyncSocketAdapter { permission?: Permission ): Promise; - push(spaceId: string, docId: string, updates: Buffer[]) { + push(editorId: string, spaceId: string, docId: string, updates: Buffer[]) { this.assertIn(spaceId); - return this.storage.pushDocUpdates(spaceId, docId, updates); + return this.storage.pushDocUpdates(editorId, spaceId, docId, updates); } get(spaceId: string, docId: string) { @@ -621,9 +626,14 @@ class WorkspaceSyncAdapter extends SyncSocketAdapter { super(SpaceType.Workspace, client, storage); } - override push(spaceId: string, docId: string, updates: Buffer[]) { + override push( + editorId: string, + spaceId: string, + docId: string, + updates: Buffer[] + ) { const id = new DocID(docId, spaceId); - return super.push(spaceId, id.guid, updates); + return super.push(editorId, spaceId, id.guid, updates); } override get(spaceId: string, docId: string) {