mirror of
https://github.com/stonith404/pingvin-share.git
synced 2025-02-05 01:38:56 -05:00
fix: add rule to check if user is owner of share
This commit is contained in:
parent
e818a29442
commit
2c47b2a284
6 changed files with 47 additions and 17 deletions
|
@ -6,7 +6,6 @@ import {
|
||||||
Post,
|
Post,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
import { UserDTO } from "src/user/dto/user.dto";
|
|
||||||
|
|
||||||
import { AuthService } from "./auth.service";
|
import { AuthService } from "./auth.service";
|
||||||
import { AuthRegisterDTO } from "./dto/authRegister.dto";
|
import { AuthRegisterDTO } from "./dto/authRegister.dto";
|
||||||
|
|
|
@ -10,23 +10,21 @@ import {
|
||||||
UseGuards,
|
UseGuards,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { ConfigService } from "@nestjs/config";
|
|
||||||
import { FileInterceptor } from "@nestjs/platform-express";
|
import { FileInterceptor } from "@nestjs/platform-express";
|
||||||
import { Response } from "express";
|
import { Response } from "express";
|
||||||
import { JwtGuard } from "src/auth/guard/jwt.guard";
|
import { JwtGuard } from "src/auth/guard/jwt.guard";
|
||||||
import { FileDownloadGuard } from "src/file/guard/fileDownload.guard";
|
import { FileDownloadGuard } from "src/file/guard/fileDownload.guard";
|
||||||
import { ShareDTO } from "src/share/dto/share.dto";
|
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 { ShareSecurityGuard } from "src/share/guard/shareSecurity.guard";
|
||||||
import { FileService } from "./file.service";
|
import { FileService } from "./file.service";
|
||||||
|
|
||||||
@Controller("shares/:shareId/files")
|
@Controller("shares/:shareId/files")
|
||||||
export class FileController {
|
export class FileController {
|
||||||
constructor(
|
constructor(private fileService: FileService) {}
|
||||||
private fileService: FileService,
|
|
||||||
private config: ConfigService
|
|
||||||
) {}
|
|
||||||
@Post()
|
@Post()
|
||||||
@UseGuards(JwtGuard)
|
@UseGuards(JwtGuard, ShareOwnerGuard)
|
||||||
@UseInterceptors(
|
@UseInterceptors(
|
||||||
FileInterceptor("file", {
|
FileInterceptor("file", {
|
||||||
dest: "./uploads/_temp/",
|
dest: "./uploads/_temp/",
|
||||||
|
|
33
backend/src/share/guard/shareOwner.guard.ts
Normal file
33
backend/src/share/guard/shareOwner.guard.ts
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import { MyShareDTO } from "./dto/myShare.dto";
|
||||||
import { ShareDTO } from "./dto/share.dto";
|
import { ShareDTO } from "./dto/share.dto";
|
||||||
import { ShareMetaDataDTO } from "./dto/shareMetaData.dto";
|
import { ShareMetaDataDTO } from "./dto/shareMetaData.dto";
|
||||||
import { SharePasswordDto } from "./dto/sharePassword.dto";
|
import { SharePasswordDto } from "./dto/sharePassword.dto";
|
||||||
|
import { ShareOwnerGuard } from "./guard/shareOwner.guard";
|
||||||
import { ShareSecurityGuard } from "./guard/shareSecurity.guard";
|
import { ShareSecurityGuard } from "./guard/shareSecurity.guard";
|
||||||
import { ShareService } from "./share.service";
|
import { ShareService } from "./share.service";
|
||||||
|
|
||||||
|
@ -50,14 +51,14 @@ export class ShareController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(":id")
|
@Delete(":id")
|
||||||
@UseGuards(JwtGuard)
|
@UseGuards(JwtGuard, ShareOwnerGuard)
|
||||||
async remove(@Param("id") id: string, @GetUser() user: User) {
|
async remove(@Param("id") id: string) {
|
||||||
await this.shareService.remove(id, user.id);
|
await this.shareService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post(":id/complete")
|
@Post(":id/complete")
|
||||||
@HttpCode(202)
|
@HttpCode(202)
|
||||||
@UseGuards(JwtGuard)
|
@UseGuards(JwtGuard, ShareOwnerGuard)
|
||||||
async complete(@Param("id") id: string) {
|
async complete(@Param("id") id: string) {
|
||||||
return new ShareDTO().from(await this.shareService.complete(id));
|
return new ShareDTO().from(await this.shareService.complete(id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,15 +132,13 @@ export class ShareService {
|
||||||
return share;
|
return share;
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove(shareId: string, userId: string) {
|
async remove(shareId: string) {
|
||||||
const share = await this.prisma.share.findUnique({
|
const share = await this.prisma.share.findUnique({
|
||||||
where: { id: shareId },
|
where: { id: shareId },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!share) throw new NotFoundException("Share not found");
|
if (!share) throw new NotFoundException("Share not found");
|
||||||
|
|
||||||
if (share.creatorId != userId) throw new ForbiddenException();
|
|
||||||
|
|
||||||
await this.prisma.share.delete({ where: { id: shareId } });
|
await this.prisma.share.delete({ where: { id: shareId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
Group,
|
Group,
|
||||||
LoadingOverlay,
|
LoadingOverlay,
|
||||||
Space,
|
Space,
|
||||||
|
Stack,
|
||||||
Table,
|
Table,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
|
@ -39,14 +40,14 @@ const MyShares = () => {
|
||||||
</Title>
|
</Title>
|
||||||
{shares.length == 0 ? (
|
{shares.length == 0 ? (
|
||||||
<Center style={{ height: "70vh" }}>
|
<Center style={{ height: "70vh" }}>
|
||||||
<Group direction="column" align="center" spacing={10}>
|
<Stack align="center" spacing={10}>
|
||||||
<Title order={3}>It's empty here 👀</Title>
|
<Title order={3}>It's empty here 👀</Title>
|
||||||
<Text>You don't have any shares.</Text>
|
<Text>You don't have any shares.</Text>
|
||||||
<Space h={5} />
|
<Space h={5} />
|
||||||
<Button component={NextLink} href="/upload" variant="light">
|
<Button component={NextLink} href="/upload" variant="light">
|
||||||
Create one
|
Create one
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
<Table>
|
<Table>
|
||||||
|
|
Loading…
Add table
Reference in a new issue