Skip to content

Commit

Permalink
Merge pull request #13 from Excali-Studio/EXD-67-remove-access-per-tag
Browse files Browse the repository at this point in the history
[EXD-67] Added ability to cancel access to canvases by tags
  • Loading branch information
marcin-piela-ssh authored May 17, 2024
2 parents 3754dd0 + 3437f25 commit 117d007
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 23 deletions.
51 changes: 39 additions & 12 deletions src/canvas/canvas.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import {
} from '@nestjs/common';
import { CanvasService } from './canvas.service';
import {
CanvasAccessByTagDTO,
GiveCanvasAccessByTagDTO,
CanvasAccessDTO,
CanvasContentUpdateDto,
CanvasCreateDTO,
CanvasDTO,
CanvasMetadataUpdateDTO,
CanvasModifyTagDTO,
CanvasStateFilter,
CancelCanvasAccessByTagDTO,
} from './canvas.interface';
import { Uuid } from '../common/common.interface';
import { ListFilter, PagedResult } from '../common/pageable.utils';
Expand Down Expand Up @@ -251,37 +252,46 @@ 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)
public async giveAccess(
@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,
});
}

/**
* 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
*/
@Post('/access')
@UseGuards(AuthenticatedGuard)
public async giveAccessByTag(
@Body() dto: CanvasAccessByTagDTO,
@Body() dto: GiveCanvasAccessByTagDTO,
@Req() req: Request,
) {
await this.canvasService.giveAccessByTag({
Expand All @@ -291,9 +301,26 @@ export class CanvasController {
}

/**
* Adds a single tag to a canvas
* Removes access to canvases with tags from the given list
* @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 tags to a canvas
* @param canvasId
* @param dto - an object containing 'tagId'
* @param dto - an object containing 'tagIds'
*/
@Post('/:id/tags')
@UseGuards(AuthenticatedGuard, CanvasGuard)
Expand All @@ -306,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)
Expand Down
21 changes: 17 additions & 4 deletions src/canvas/canvas.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -45,6 +46,11 @@ export interface GiveAccessByTagCommand {
personIds: Uuid[];
}

export interface CancelAccessByTagCommand {
userId: Uuid;
tagIds: Uuid[];
}

export interface CanvasAddTagCommand {
canvasId: Uuid;
tagIds: Uuid[];
Expand Down Expand Up @@ -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()
Expand All @@ -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;
Expand Down
55 changes: 48 additions & 7 deletions src/canvas/canvas.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Repository } from 'typeorm';
import { CanvasEntity } from './entity/canvas.entity';
import { InjectRepository } from '@nestjs/typeorm';
import {
CancelAccessByTagCommand,
CancelAccessCommand,
CanvasAddTagCommand,
CanvasContentUpdateCommand,
Expand Down Expand Up @@ -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 },
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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 },
Expand Down

0 comments on commit 117d007

Please sign in to comment.