1
0
mirror of https://github.com/stonith404/pingvin-share.git synced 2024-10-02 09:30:10 +02:00

Merge branch 'development' into main

This commit is contained in:
Elias Schneider 2022-10-10 23:40:10 +02:00
commit 1553801c32
7 changed files with 59 additions and 23 deletions

View File

@ -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";

View File

@ -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/",
@ -43,7 +41,7 @@ export class FileController {
file: Express.Multer.File, file: Express.Multer.File,
@Param("shareId") shareId: string @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") @Get(":fileId/download")

View 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;
}
}

View File

@ -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));
} }

View File

@ -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 } });
} }

View File

@ -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>

View File

@ -16,7 +16,7 @@ import { Check } from "tabler-icons-react";
import Meta from "../components/Meta"; import Meta from "../components/Meta";
import useUser from "../hooks/user.hook"; import useUser from "../hooks/user.hook";
const { publicRuntimeConfig } = getConfig() const { publicRuntimeConfig } = getConfig();
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
inner: { inner: {
@ -106,15 +106,21 @@ export default function Home() {
} }
> >
<List.Item> <List.Item>
<div>
<b>Self-Hosted</b> - Host Pingvin Share on your own machine. <b>Self-Hosted</b> - Host Pingvin Share on your own machine.
</div>
</List.Item> </List.Item>
<List.Item> <List.Item>
<div>
<b>Privacy</b> - Your files are your files and should never <b>Privacy</b> - Your files are your files and should never
get into the hands of third parties. get into the hands of third parties.
</div>
</List.Item> </List.Item>
<List.Item> <List.Item>
<div>
<b>No annoying file size limit</b> - Upload as big files as <b>No annoying file size limit</b> - Upload as big files as
you want. Only your hard drive will be your limit. you want. Only your hard drive will be your limit.
</div>
</List.Item> </List.Item>
</List> </List>