From 9ba0f259f435f38093ef2bd923e609453c395b5c Mon Sep 17 00:00:00 2001 From: Max Bischof Date: Mon, 13 May 2024 16:03:18 +0200 Subject: [PATCH] Add delete sessions endpoint --- .../etherpad-client/etherpad-client.adapter.ts | 12 ++++++++++-- .../api/collaborative-text-editor.controller.ts | 15 +++++++++++++-- .../api/collaborative-text-editor.uc.ts | 6 ++++++ .../domain/do/collaborative-text-editor.ts | 5 ++++- .../service/collaborative-text-editor.service.ts | 14 ++++++++------ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/apps/server/src/infra/etherpad-client/etherpad-client.adapter.ts b/apps/server/src/infra/etherpad-client/etherpad-client.adapter.ts index 58d02502cfe..9559bf3cfab 100644 --- a/apps/server/src/infra/etherpad-client/etherpad-client.adapter.ts +++ b/apps/server/src/infra/etherpad-client/etherpad-client.adapter.ts @@ -31,7 +31,7 @@ export class EtherpadClientAdapter { private readonly authorApi: AuthorApi ) {} - public async getOrCreateAuthorId(userId: EntityId, username: string): Promise { + public async getOrCreateAuthorId(userId: EntityId, username?: string): Promise { const response = await this.tryCreateAuthor(userId, username); const user = this.handleEtherpadResponse(response, { userId }); @@ -40,7 +40,7 @@ export class EtherpadClientAdapter { return authorId; } - private async tryCreateAuthor(userId: string, username: string): Promise> { + private async tryCreateAuthor(userId: string, username?: string): Promise> { try { const response = await this.authorApi.createAuthorIfNotExistsForUsingGET(userId, username); @@ -71,6 +71,14 @@ export class EtherpadClientAdapter { return sessionId; } + public async deleteSession(sessionId: SessionId) { + try { + await this.sessionApi.deleteSessionUsingPOST(sessionId); + } catch (error) { + throw EtherpadResponseMapper.mapResponseToException(EtherpadErrorType.CONNECTION_ERROR, { sessionId }, error); + } + } + private async tryCreateSession( groupId: string, authorId: string, diff --git a/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.controller.ts b/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.controller.ts index febd0c555d4..4532bed4f95 100644 --- a/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.controller.ts +++ b/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.controller.ts @@ -1,5 +1,5 @@ import { Authenticate, CurrentUser, ICurrentUser } from '@modules/authentication'; -import { Controller, ForbiddenException, Get, NotFoundException, Param, Res } from '@nestjs/common'; +import { Controller, Delete, ForbiddenException, Get, NotFoundException, Param, Res } from '@nestjs/common'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { ApiValidationError } from '@shared/common'; import { Response } from 'express'; @@ -30,13 +30,24 @@ export class CollaborativeTextEditorController { getCollaborativeTextEditorForParentParams ); - res.cookie('sessionID', textEditor.sessions.toString(), { + res.cookie('sessionID', textEditor.sessionId, { expires: textEditor.sessionExpiryDate, secure: true, + path: textEditor.path, }); const dto = CollaborativeTextEditorMapper.mapCollaborativeTextEditorToResponse(textEditor); return dto; } + + @ApiOperation({ summary: 'Delete all etherpad sessions for user' }) + @ApiResponse({ status: 200, type: CollaborativeTextEditorResponse }) + @ApiResponse({ status: 400, type: ApiValidationError }) + @ApiResponse({ status: 403, type: ForbiddenException }) + @ApiResponse({ status: 404, type: NotFoundException }) + @Delete('/delete-sessions') + async deleteSessionsByUser(@CurrentUser() currentUser: ICurrentUser): Promise { + await this.collaborativeTextEditorUc.deleteSessionsByUser(currentUser.userId); + } } diff --git a/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.uc.ts b/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.uc.ts index 2f45c89c2f6..cb0ac2e87ea 100644 --- a/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.uc.ts +++ b/apps/server/src/modules/collaborative-text-editor/api/collaborative-text-editor.uc.ts @@ -36,6 +36,12 @@ export class CollaborativeTextEditorUc { return textEditor; } + async deleteSessionsByUser(userId: string): Promise { + const user = await this.authorizationService.getUserWithPermissions(userId); + + await this.collaborativeTextEditorService.deleteSessionsByUser(user.id); + } + private async authorizeByParentType(params: GetCollaborativeTextEditorForParentParams, user: User) { if (params.parentType === CollaborativeTextEditorParentType.BOARD_CONTENT_ELEMENT) { await this.authorizeForContentElement(params, user); diff --git a/apps/server/src/modules/collaborative-text-editor/domain/do/collaborative-text-editor.ts b/apps/server/src/modules/collaborative-text-editor/domain/do/collaborative-text-editor.ts index c1b58baa071..e907192140b 100644 --- a/apps/server/src/modules/collaborative-text-editor/domain/do/collaborative-text-editor.ts +++ b/apps/server/src/modules/collaborative-text-editor/domain/do/collaborative-text-editor.ts @@ -1,5 +1,8 @@ +import { SessionId } from '@src/infra/etherpad-client/interface'; + export interface CollaborativeTextEditor { url: string; - sessions: string[]; + path: string; + sessionId: SessionId; sessionExpiryDate: Date; } diff --git a/apps/server/src/modules/collaborative-text-editor/service/collaborative-text-editor.service.ts b/apps/server/src/modules/collaborative-text-editor/service/collaborative-text-editor.service.ts index 38aae97cff5..2b289672863 100644 --- a/apps/server/src/modules/collaborative-text-editor/service/collaborative-text-editor.service.ts +++ b/apps/server/src/modules/collaborative-text-editor/service/collaborative-text-editor.service.ts @@ -33,14 +33,13 @@ export class CollaborativeTextEditorService { parentId, sessionExpiryDate ); - const authorsSessionIds = await this.collaborativeTextEditorAdapter.listSessionIdsOfAuthor(authorId); const url = this.buildPath(padId); - const uniqueSessionIds = this.removeDuplicateSessions([...authorsSessionIds, sessionId]); return { - sessions: uniqueSessionIds, + sessionId, url, + path: `/p/${padId}`, sessionExpiryDate, }; } @@ -51,10 +50,13 @@ export class CollaborativeTextEditorService { await this.collaborativeTextEditorAdapter.deleteGroup(groupId); } - private removeDuplicateSessions(sessions: string[]): string[] { - const uniqueSessions = [...new Set(sessions)]; + async deleteSessionsByUser(userId: string) { + const authorId = await this.collaborativeTextEditorAdapter.getOrCreateAuthorId(userId); + const sessionIds = await this.collaborativeTextEditorAdapter.listSessionIdsOfAuthor(authorId); - return uniqueSessions; + const promises = sessionIds.map((sessionId) => this.collaborativeTextEditorAdapter.deleteSession(sessionId)); + + await Promise.all(promises); } private buildSessionExpiryDate(): Date {