From 2c47b2a28468dd6beaf88892aaa867ca579905ca Mon Sep 17 00:00:00 2001 From: Elias Schneider Date: Mon, 10 Oct 2022 23:34:03 +0200 Subject: [PATCH] fix: add rule to check if user is owner of share --- backend/src/auth/auth.controller.ts | 1 - backend/src/file/file.controller.ts | 12 ++++---- backend/src/share/guard/shareOwner.guard.ts | 33 +++++++++++++++++++++ backend/src/share/share.controller.ts | 9 +++--- backend/src/share/share.service.ts | 4 +-- frontend/src/pages/account/shares.tsx | 5 ++-- 6 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 backend/src/share/guard/shareOwner.guard.ts diff --git a/backend/src/auth/auth.controller.ts b/backend/src/auth/auth.controller.ts index 0cf41437..3809ed66 100644 --- a/backend/src/auth/auth.controller.ts +++ b/backend/src/auth/auth.controller.ts @@ -6,7 +6,6 @@ import { Post, } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; -import { UserDTO } from "src/user/dto/user.dto"; import { AuthService } from "./auth.service"; import { AuthRegisterDTO } from "./dto/authRegister.dto"; diff --git a/backend/src/file/file.controller.ts b/backend/src/file/file.controller.ts index 3e6044c1..b5e2d4b2 100644 --- a/backend/src/file/file.controller.ts +++ b/backend/src/file/file.controller.ts @@ -10,23 +10,21 @@ import { UseGuards, UseInterceptors, } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; import { FileInterceptor } from "@nestjs/platform-express"; import { Response } from "express"; import { JwtGuard } from "src/auth/guard/jwt.guard"; import { FileDownloadGuard } from "src/file/guard/fileDownload.guard"; import { ShareDTO } from "src/share/dto/share.dto"; +import { ShareOwnerGuard } from "src/share/guard/shareOwner.guard"; import { ShareSecurityGuard } from "src/share/guard/shareSecurity.guard"; import { FileService } from "./file.service"; @Controller("shares/:shareId/files") export class FileController { - constructor( - private fileService: FileService, - private config: ConfigService - ) {} + constructor(private fileService: FileService) {} + @Post() - @UseGuards(JwtGuard) + @UseGuards(JwtGuard, ShareOwnerGuard) @UseInterceptors( FileInterceptor("file", { dest: "./uploads/_temp/", @@ -43,7 +41,7 @@ export class FileController { file: Express.Multer.File, @Param("shareId") shareId: string ) { - return new ShareDTO().from( await this.fileService.create(file, shareId)); + return new ShareDTO().from(await this.fileService.create(file, shareId)); } @Get(":fileId/download") diff --git a/backend/src/share/guard/shareOwner.guard.ts b/backend/src/share/guard/shareOwner.guard.ts new file mode 100644 index 00000000..ee7b65ef --- /dev/null +++ b/backend/src/share/guard/shareOwner.guard.ts @@ -0,0 +1,33 @@ +import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { User } from "@prisma/client"; +import { Request } from "express"; +import { ExtractJwt } from "passport-jwt"; +import { PrismaService } from "src/prisma/prisma.service"; +import { ShareService } from "src/share/share.service"; + +@Injectable() +export class ShareOwnerGuard implements CanActivate { + constructor( + private prisma: PrismaService + ) {} + + async canActivate(context: ExecutionContext) { + const request: Request = context.switchToHttp().getRequest(); + const shareId = Object.prototype.hasOwnProperty.call( + request.params, + "shareId" + ) + ? request.params.shareId + : request.params.id; + + const share = await this.prisma.share.findUnique({ + where: { id: shareId }, + include: { security: true }, + }); + + + + return share.creatorId == (request.user as User).id; + } +} diff --git a/backend/src/share/share.controller.ts b/backend/src/share/share.controller.ts index b0004170..0556b2f2 100644 --- a/backend/src/share/share.controller.ts +++ b/backend/src/share/share.controller.ts @@ -16,6 +16,7 @@ import { MyShareDTO } from "./dto/myShare.dto"; import { ShareDTO } from "./dto/share.dto"; import { ShareMetaDataDTO } from "./dto/shareMetaData.dto"; import { SharePasswordDto } from "./dto/sharePassword.dto"; +import { ShareOwnerGuard } from "./guard/shareOwner.guard"; import { ShareSecurityGuard } from "./guard/shareSecurity.guard"; import { ShareService } from "./share.service"; @@ -50,14 +51,14 @@ export class ShareController { } @Delete(":id") - @UseGuards(JwtGuard) - async remove(@Param("id") id: string, @GetUser() user: User) { - await this.shareService.remove(id, user.id); + @UseGuards(JwtGuard, ShareOwnerGuard) + async remove(@Param("id") id: string) { + await this.shareService.remove(id); } @Post(":id/complete") @HttpCode(202) - @UseGuards(JwtGuard) + @UseGuards(JwtGuard, ShareOwnerGuard) async complete(@Param("id") id: string) { return new ShareDTO().from(await this.shareService.complete(id)); } diff --git a/backend/src/share/share.service.ts b/backend/src/share/share.service.ts index f363fda8..a6fa6fc6 100644 --- a/backend/src/share/share.service.ts +++ b/backend/src/share/share.service.ts @@ -132,15 +132,13 @@ export class ShareService { return share; } - async remove(shareId: string, userId: string) { + async remove(shareId: string) { const share = await this.prisma.share.findUnique({ where: { id: shareId }, }); if (!share) throw new NotFoundException("Share not found"); - if (share.creatorId != userId) throw new ForbiddenException(); - await this.prisma.share.delete({ where: { id: shareId } }); } diff --git a/frontend/src/pages/account/shares.tsx b/frontend/src/pages/account/shares.tsx index 67b9d58f..f3da20b3 100644 --- a/frontend/src/pages/account/shares.tsx +++ b/frontend/src/pages/account/shares.tsx @@ -5,6 +5,7 @@ import { Group, LoadingOverlay, Space, + Stack, Table, Text, Title, @@ -39,14 +40,14 @@ const MyShares = () => { {shares.length == 0 ? (
- + It's empty here 👀 You don't have any shares. - +
) : (