Compare commits

...

7 Commits

Author SHA1 Message Date
Elias Schneider
c303454db3 release: 0.23.1 2024-04-05 13:54:55 +02:00
Elias Schneider
3972589f76 fix: normal shares were added to the previous reverse share 2024-04-05 13:54:36 +02:00
Elias Schneider
3c5e0ad513 fix: incorrect layout on 404 page 2024-04-05 12:03:38 +02:00
Elias Schneider
384fd19203 fix: redirect vulnerability on error, sign in and totp page 2024-04-05 12:00:41 +02:00
Elias Schneider
9d1a12b0d1 fix: disable js execution on raw file view 2024-04-05 11:37:47 +02:00
Elias Schneider
24e100bd7b fix: changing the chunk size needed an app restart 2024-04-05 11:31:43 +02:00
Elias Schneider
1da4feeb89 fix(backend): crash on unhandled promise rejections 2024-04-04 23:18:00 +02:00
15 changed files with 72 additions and 47 deletions

View File

@@ -1,3 +1,15 @@
## [0.23.1](https://github.com/stonith404/pingvin-share/compare/v0.23.0...v0.23.1) (2024-04-05)
### Bug Fixes
* **backend:** crash on unhandled promise rejections ([1da4fee](https://github.com/stonith404/pingvin-share/commit/1da4feeb895a13d0a0ae754bd716a84e8186d081))
* changing the chunk size needed an app restart ([24e100b](https://github.com/stonith404/pingvin-share/commit/24e100bd7be8bf20778bdf2767aa35cae8d7e502))
* disable js execution on raw file view ([9d1a12b](https://github.com/stonith404/pingvin-share/commit/9d1a12b0d1812214f1fe6fa56e3848091ce4945c))
* incorrect layout on 404 page ([3c5e0ad](https://github.com/stonith404/pingvin-share/commit/3c5e0ad5134ee2d405ac420152b5825102f65bfc))
* normal shares were added to the previous reverse share ([3972589](https://github.com/stonith404/pingvin-share/commit/3972589f76519b03074d916fb2460c795b1f0737))
* redirect vulnerability on error, sign in and totp page ([384fd19](https://github.com/stonith404/pingvin-share/commit/384fd19203b63eeb4b952f83a9e1eaab1b19b90d))
## [0.23.0](https://github.com/stonith404/pingvin-share/compare/v0.22.2...v0.23.0) (2024-04-04)

View File

@@ -1,12 +1,12 @@
{
"name": "pingvin-share-backend",
"version": "0.23.0",
"version": "0.23.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "pingvin-share-backend",
"version": "0.23.0",
"version": "0.23.1",
"dependencies": {
"@nestjs/cache-manager": "^2.1.0",
"@nestjs/common": "^10.1.2",

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share-backend",
"version": "0.23.0",
"version": "0.23.1",
"scripts": {
"build": "nest build",
"dev": "cross-env NODE_ENV=development nest start --watch",

View File

@@ -99,7 +99,7 @@ export class AuthService {
include: { resetPasswordToken: true },
});
if (!user) throw new BadRequestException("User not found");
if (!user) return;
// Delete old reset password token
if (user.resetPasswordToken) {

View File

@@ -26,7 +26,13 @@ export class FileController {
@SkipThrottle()
@UseGuards(CreateShareGuard, ShareOwnerGuard)
async create(
@Query() query: any,
@Query()
query: {
id: string;
name: string;
chunkIndex: string;
totalChunks: string;
},
@Body() body: string,
@Param("shareId") shareId: string,
) {
@@ -69,6 +75,7 @@ export class FileController {
const headers = {
"Content-Type": file.metaData.mimeType,
"Content-Length": file.metaData.size,
"Content-Security-Policy": "script-src 'none'",
};
if (download === "true") {

View File

@@ -1,13 +1,18 @@
import { ClassSerializerInterceptor, ValidationPipe } from "@nestjs/common";
import {
ClassSerializerInterceptor,
Logger,
ValidationPipe,
} from "@nestjs/common";
import { NestFactory, Reflector } from "@nestjs/core";
import { NestExpressApplication } from "@nestjs/platform-express";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import * as bodyParser from "body-parser";
import * as cookieParser from "cookie-parser";
import { NextFunction, Request, Response } from "express";
import * as fs from "fs";
import { AppModule } from "./app.module";
import { DATA_DIRECTORY } from "./constants";
import { ConfigService } from "./config/config.service";
import { DATA_DIRECTORY } from "./constants";
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
@@ -15,12 +20,14 @@ async function bootstrap() {
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
const config = app.get<ConfigService>(ConfigService);
app.use(
app.use((req: Request, res: Response, next: NextFunction) => {
const chunkSize = config.get("share.chunkSize");
bodyParser.raw({
type: "application/octet-stream",
limit: `${config.get("share.chunkSize")}B`,
}),
);
limit: `${chunkSize}B`,
})(req, res, next);
});
app.use(cookieParser());
app.set("trust proxy", true);
@@ -42,5 +49,8 @@ async function bootstrap() {
}
await app.listen(parseInt(process.env.PORT) || 8080);
const logger = new Logger("UnhandledAsyncError");
process.on("unhandledRejection", (e) => logger.error(e));
}
bootstrap();

View File

@@ -1,12 +1,12 @@
{
"name": "pingvin-share-frontend",
"version": "0.23.0",
"version": "0.23.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "pingvin-share-frontend",
"version": "0.23.0",
"version": "0.23.1",
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/server": "^11.11.0",

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share-frontend",
"version": "0.23.0",
"version": "0.23.1",
"scripts": {
"dev": "next dev",
"build": "next build",

View File

@@ -25,6 +25,7 @@ import useTranslate from "../../hooks/useTranslate.hook";
import authService from "../../services/auth.service";
import { getOAuthIcon, getOAuthUrl } from "../../utils/oauth.util";
import toast from "../../utils/toast.util";
import { safeRedirectPath } from "../../utils/router.util";
const useStyles = createStyles((theme) => ({
or: {
@@ -98,7 +99,7 @@ const SignInForm = ({ redirectPath }: { redirectPath: string }) => {
);
} else {
await refreshUser();
router.replace(redirectPath);
router.replace(safeRedirectPath(redirectPath));
}
})
.catch(toast.axiosError);

View File

@@ -6,15 +6,16 @@ import {
PinInput,
Title,
} from "@mantine/core";
import { useForm, yupResolver } from "@mantine/form";
import { useRouter } from "next/router";
import { useState } from "react";
import { FormattedMessage } from "react-intl";
import * as yup from "yup";
import useTranslate from "../../hooks/useTranslate.hook";
import { useForm, yupResolver } from "@mantine/form";
import { useState } from "react";
import authService from "../../services/auth.service";
import toast from "../../utils/toast.util";
import { useRouter } from "next/router";
import useUser from "../../hooks/user.hook";
import authService from "../../services/auth.service";
import { safeRedirectPath } from "../../utils/router.util";
import toast from "../../utils/toast.util";
function TotpForm({ redirectPath }: { redirectPath: string }) {
const t = useTranslate();
@@ -46,7 +47,7 @@ function TotpForm({ redirectPath }: { redirectPath: string }) {
router.query.loginToken as string,
);
await refreshUser();
await router.replace(redirectPath);
await router.replace(safeRedirectPath(redirectPath));
} catch (e) {
toast.axiosError(e);
form.setFieldError("code", "error");

View File

@@ -1,14 +1,7 @@
import {
Button,
Container,
createStyles,
Group,
Text,
Title,
} from "@mantine/core";
import { Button, Container, createStyles, Group, Title } from "@mantine/core";
import Link from "next/link";
import Meta from "../components/Meta";
import { FormattedMessage } from "react-intl";
import Meta from "../components/Meta";
const useStyles = createStyles((theme) => ({
root: {
@@ -21,19 +14,13 @@ const useStyles = createStyles((theme) => ({
fontWeight: 900,
fontSize: 220,
lineHeight: 1,
marginBottom: `calc(${theme.spacing.xl} * 100)`,
marginBottom: 20,
color: theme.colors.gray[2],
[theme.fn.smallerThan("sm")]: {
fontSize: 120,
},
},
description: {
maxWidth: 500,
margin: "auto",
marginBottom: `calc(${theme.spacing.xl} * 100)`,
},
}));
const ErrorNotFound = () => {
@@ -47,12 +34,7 @@ const ErrorNotFound = () => {
<Title align="center" order={3}>
<FormattedMessage id="404.description" />
</Title>
<Text
color="dimmed"
align="center"
className={classes.description}
></Text>
<Group position="center">
<Group position="center" mt={50}>
<Button component={Link} href="/" variant="light">
<FormattedMessage id="404.button.home" />
</Button>

View File

@@ -4,6 +4,7 @@ import Meta from "../components/Meta";
import useTranslate from "../hooks/useTranslate.hook";
import { useRouter } from "next/router";
import { FormattedMessage } from "react-intl";
import { safeRedirectPath } from "../utils/router.util";
const useStyle = createStyles({
title: {
@@ -39,7 +40,9 @@ export default function Error() {
</Text>
<Button
mt="xl"
onClick={() => router.push((router.query.redirect as string) || "/")}
onClick={() =>
router.push(safeRedirectPath(router.query.redirect as string))
}
>
{t("error.button.back")}
</Button>

View File

@@ -1,4 +1,4 @@
import { setCookie } from "cookies-next";
import { deleteCookie, setCookie } from "cookies-next";
import mime from "mime-types";
import { FileUploadResponse } from "../types/File.type";
@@ -16,7 +16,9 @@ const create = async (share: CreateShare) => {
};
const completeShare = async (id: string) => {
return (await api.post(`shares/${id}/complete`)).data;
const response = (await api.post(`shares/${id}/complete`)).data;
deleteCookie("reverse_share_token");
return response;
};
const revertComplete = async (id: string) => {

View File

@@ -0,0 +1,7 @@
export function safeRedirectPath(path: string | undefined) {
if (!path) return "/";
if (!path.startsWith("/")) return `/${path}`;
return path;
}

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share",
"version": "0.23.0",
"version": "0.23.1",
"scripts": {
"format": "cd frontend && npm run format && cd ../backend && npm run format",
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",