From 69826cd9a0360a48f5e62abd083706afabc369ac Mon Sep 17 00:00:00 2001 From: Marcin Piela Date: Fri, 17 May 2024 11:54:31 +0200 Subject: [PATCH 1/2] [EXD-67] Added ability to cancel access to canvases by tags --- src/canvas/canvas.controller.ts | 43 +++++++++++++++++++++----- src/canvas/canvas.interface.ts | 21 ++++++++++--- src/canvas/canvas.service.ts | 55 ++++++++++++++++++++++++++++----- 3 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/canvas/canvas.controller.ts b/src/canvas/canvas.controller.ts index ea5fc7a..9ed86aa 100644 --- a/src/canvas/canvas.controller.ts +++ b/src/canvas/canvas.controller.ts @@ -12,7 +12,7 @@ import { } from '@nestjs/common'; import { CanvasService } from './canvas.service'; import { - CanvasAccessByTagDTO, + GiveCanvasAccessByTagDTO, CanvasAccessDTO, CanvasContentUpdateDto, CanvasCreateDTO, @@ -20,6 +20,7 @@ import { CanvasMetadataUpdateDTO, CanvasModifyTagDTO, CanvasStateFilter, + CancelCanvasAccessByTagDTO, } from './canvas.interface'; import { Uuid } from '../common/common.interface'; import { ListFilter, PagedResult } from '../common/pageable.utils'; @@ -251,7 +252,7 @@ export class CanvasController { /** * Gives access to a single canvas for a single user * @param canvasId - * @param dto - an object containing 'userId' + * @param dto - an object containing 'personId' */ @Post('/:id/access') @UseGuards(AuthenticatedGuard, CanvasGuard) @@ -259,29 +260,38 @@ export class CanvasController { @Param('id') canvasId: Uuid, @Body() dto: CanvasAccessDTO, ) { - const userId = dto.userId; - await this.canvasService.giveAccess({ canvasId, userId }); + await this.canvasService.giveAccess({ canvasId, ...dto }); } /** * Removes access to a single canvas for a single user * @param canvasId - * @param dto - an object containing 'userId' + * @param dto - an object containing 'personId' + * @param req - HTTP request object */ @Delete('/:id/access') @UseGuards(AuthenticatedGuard, CanvasGuard) public async cancelAccess( @Param('id') canvasId: Uuid, @Body() dto: CanvasAccessDTO, + @Req() req: Request, ) { - const userId = dto.userId; - await this.canvasService.cancelAccess({ canvasId, userId }); + await this.canvasService.cancelAccess({ + userId: req.user.toString(), + canvasId, + ...dto, + }); } + /** + * Give access to canvases with a given tag for selected users + * @param dto - an object containing 'tagIds' & 'personIds' + * @param req - HTTP request object + */ @Post('/access') @UseGuards(AuthenticatedGuard) public async giveAccessByTag( - @Body() dto: CanvasAccessByTagDTO, + @Body() dto: GiveCanvasAccessByTagDTO, @Req() req: Request, ) { await this.canvasService.giveAccessByTag({ @@ -290,6 +300,23 @@ export class CanvasController { }); } + /** + * Cancel access to canvases with a given tag for selected users + * @param dto - an object containing 'tagIds' + * @param req - HTTP request object + */ + @Delete('/access') + @UseGuards(AuthenticatedGuard) + public async cancelAccessByTag( + @Body() dto: CancelCanvasAccessByTagDTO, + @Req() req: Request, + ) { + await this.canvasService.cancelAccessByTag({ + userId: req.user.toString(), + ...dto, + }); + } + /** * Adds a single tag to a canvas * @param canvasId diff --git a/src/canvas/canvas.interface.ts b/src/canvas/canvas.interface.ts index 2585b74..7f36809 100644 --- a/src/canvas/canvas.interface.ts +++ b/src/canvas/canvas.interface.ts @@ -31,12 +31,13 @@ export interface CanvasMetadataUpdateCommand { export interface GiveAccessCommand { canvasId: Uuid; - userId: Uuid; + personId: Uuid; } export interface CancelAccessCommand { - canvasId: Uuid; userId: Uuid; + canvasId: Uuid; + personId: Uuid; } export interface GiveAccessByTagCommand { @@ -45,6 +46,11 @@ export interface GiveAccessByTagCommand { personIds: Uuid[]; } +export interface CancelAccessByTagCommand { + userId: Uuid; + tagIds: Uuid[]; +} + export interface CanvasAddTagCommand { canvasId: Uuid; tagIds: Uuid[]; @@ -90,10 +96,10 @@ export interface CanvasTagDTO { export class CanvasAccessDTO { @IsUUID() @IsNotEmpty() - userId: Uuid; + personId: Uuid; } -export class CanvasAccessByTagDTO { +export class GiveCanvasAccessByTagDTO { @IsUUID('all', { each: true }) @IsNotEmpty({ each: true }) @IsNotEmpty() @@ -104,6 +110,13 @@ export class CanvasAccessByTagDTO { personIds: Uuid[]; } +export class CancelCanvasAccessByTagDTO { + @IsUUID('all', { each: true }) + @IsNotEmpty({ each: true }) + @IsNotEmpty() + tagIds: Uuid[]; +} + export class CanvasStateFilter { @IsOptional() versionTimestamp?: string; diff --git a/src/canvas/canvas.service.ts b/src/canvas/canvas.service.ts index 75350fe..5711ff6 100644 --- a/src/canvas/canvas.service.ts +++ b/src/canvas/canvas.service.ts @@ -3,6 +3,7 @@ import { Repository } from 'typeorm'; import { CanvasEntity } from './entity/canvas.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { + CancelAccessByTagCommand, CancelAccessCommand, CanvasAddTagCommand, CanvasContentUpdateCommand, @@ -168,7 +169,7 @@ export class CanvasService { public async giveAccess(command: GiveAccessCommand) { const user = await this.userRepository.findOne({ - where: { id: command.userId }, + where: { id: command.personId }, }); const canvas = await this.canvasRepository.findOne({ where: { id: command.canvasId }, @@ -177,7 +178,10 @@ export class CanvasService { throw new NotFoundException(); } let canvasAccess = await this.canvasAccessRepository.findOne({ - where: { user: { id: command.userId }, canvas: { id: command.canvasId } }, + where: { + user: { id: command.personId }, + canvas: { id: command.canvasId }, + }, }); if (canvasAccess) { return; @@ -190,10 +194,20 @@ export class CanvasService { } public async cancelAccess(command: CancelAccessCommand) { - await this.canvasAccessRepository.delete({ - user: { id: command.userId }, - canvas: { id: command.canvasId }, - }); + let criteria: any; + if (command.userId == command.personId) { + criteria = { + user: { id: command.personId }, + canvas: { id: command.canvasId }, + }; + } else { + criteria = { + user: { id: command.personId }, + canvas: { id: command.canvasId }, + isOwner: false, + }; + } + await this.canvasAccessRepository.delete(criteria); } public async giveAccessByTag(command: GiveAccessByTagCommand) { @@ -208,12 +222,39 @@ export class CanvasService { command.personIds.forEach((personId) => this.giveAccess({ canvasId: canvas.id, - userId: personId, + personId: personId, }), ), ); } + public async cancelAccessByTag(command: CancelAccessByTagCommand) { + const user = await this.userRepository.findOne({ + where: { id: command.userId }, + }); + if (!user) { + throw new NotFoundException(); + } + const accessibleWithTags = await this.readByTags(command.tagIds, user.id); + for (const canvas of accessibleWithTags) { + const accessList = await this.canvasAccessRepository.find({ + where: { + canvas: { id: canvas.id }, + }, + relations: { user: true }, + }); + accessList.forEach((access) => { + if (access.user.id != user.id) { + this.cancelAccess({ + userId: user.id, + canvasId: canvas.id, + personId: access.user.id, + }); + } + }); + } + } + public async addTags(command: CanvasAddTagCommand) { const canvas = await this.canvasRepository.findOne({ where: { id: command.canvasId }, From 3437f2540c8c5a3cf8aab65b369afaf64a0f5fb2 Mon Sep 17 00:00:00 2001 From: Marcin Piela Date: Fri, 17 May 2024 13:44:26 +0200 Subject: [PATCH 2/2] [EXD-67] Fixed / updated method descriptions --- src/canvas/canvas.controller.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/canvas/canvas.controller.ts b/src/canvas/canvas.controller.ts index 9ed86aa..56ba7b9 100644 --- a/src/canvas/canvas.controller.ts +++ b/src/canvas/canvas.controller.ts @@ -284,7 +284,7 @@ export class CanvasController { } /** - * Give access to canvases with a given tag for selected users + * Gives access to canvases with tags from the given list for selected users * @param dto - an object containing 'tagIds' & 'personIds' * @param req - HTTP request object */ @@ -301,7 +301,7 @@ export class CanvasController { } /** - * Cancel access to canvases with a given tag for selected users + * Removes access to canvases with tags from the given list * @param dto - an object containing 'tagIds' * @param req - HTTP request object */ @@ -318,9 +318,9 @@ export class CanvasController { } /** - * Adds a single tag to a canvas + * Adds tags to a canvas * @param canvasId - * @param dto - an object containing 'tagId' + * @param dto - an object containing 'tagIds' */ @Post('/:id/tags') @UseGuards(AuthenticatedGuard, CanvasGuard) @@ -333,9 +333,9 @@ export class CanvasController { } /** - * Removes a single tag from a canvas + * Removes tags from a canvas * @param canvasId - * @param dto - an object containing 'tagId' + * @param dto - an object containing 'tagIds' */ @Delete('/:id/tags') @UseGuards(AuthenticatedGuard, CanvasGuard)