Compare commits

..

4 Commits

Author SHA1 Message Date
Elias Schneider
fccc4cbc02 release: 0.6.1 2023-01-11 13:08:09 +01:00
Elias Schneider
f1b44f87fa fix: shareUrl uses wrong origin 2023-01-11 13:06:38 +01:00
Elias Schneider
02e41e2437 feat: delete all sessions if password was changed 2023-01-10 13:32:37 +01:00
Elias Schneider
74e8956106 fix: update password doesn't work 2023-01-10 12:29:38 +01:00
14 changed files with 104 additions and 37 deletions

View File

@@ -1,3 +1,16 @@
### [0.6.1](https://github.com/stonith404/pingvin-share/compare/v0.6.0...v0.6.1) (2023-01-11)
### Features
* delete all sessions if password was changed ([02e41e2](https://github.com/stonith404/pingvin-share/commit/02e41e243768de34de1bdc8833e83f60db530e55))
### Bug Fixes
* shareUrl uses wrong origin ([f1b44f8](https://github.com/stonith404/pingvin-share/commit/f1b44f87fa64d3b21ca92c9068cb352d0ad51bc0))
* update password doesn't work ([74e8956](https://github.com/stonith404/pingvin-share/commit/74e895610642552c98c0015d0f8347735aaed457))
## [0.6.0](https://github.com/stonith404/pingvin-share/compare/v0.5.1...v0.6.0) (2023-01-09)

View File

@@ -1,12 +1,12 @@
{
"name": "pingvin-share-backend",
"version": "0.6.0",
"version": "0.6.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "pingvin-share-backend",
"version": "0.6.0",
"version": "0.6.1",
"dependencies": {
"@nestjs/common": "^9.2.1",
"@nestjs/config": "^2.2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share-backend",
"version": "0.6.0",
"version": "0.6.1",
"scripts": {
"build": "nest build",
"dev": "nest start --watch",

View File

@@ -21,6 +21,7 @@ import { AuthRegisterDTO } from "./dto/authRegister.dto";
import { AuthSignInDTO } from "./dto/authSignIn.dto";
import { AuthSignInTotpDTO } from "./dto/authSignInTotp.dto";
import { EnableTotpDTO } from "./dto/enableTotp.dto";
import { TokenDTO } from "./dto/token.dto";
import { UpdatePasswordDTO } from "./dto/updatePassword.dto";
import { VerifyTotpDTO } from "./dto/verifyTotp.dto";
import { JwtGuard } from "./guard/jwt.guard";
@@ -45,8 +46,8 @@ export class AuthController {
response = this.addTokensToResponse(
response,
result.accessToken,
result.refreshToken
result.refreshToken,
result.accessToken
);
return result;
@@ -64,8 +65,8 @@ export class AuthController {
if (result.accessToken && result.refreshToken) {
response = this.addTokensToResponse(
response,
result.accessToken,
result.refreshToken
result.refreshToken,
result.accessToken
);
}
@@ -83,17 +84,28 @@ export class AuthController {
response = this.addTokensToResponse(
response,
result.accessToken,
result.refreshToken
result.refreshToken,
result.accessToken
);
return result;
return new TokenDTO().from(result);
}
@Patch("password")
@UseGuards(JwtGuard)
async updatePassword(@GetUser() user: User, @Body() dto: UpdatePasswordDTO) {
await this.authService.updatePassword(user, dto.oldPassword, dto.password);
async updatePassword(
@GetUser() user: User,
@Res({ passthrough: true }) response: Response,
@Body() dto: UpdatePasswordDTO
) {
const result = await this.authService.updatePassword(
user,
dto.oldPassword,
dto.password
);
response = this.addTokensToResponse(response, result.refreshToken);
return new TokenDTO().from(result);
}
@Post("token")
@@ -108,7 +120,7 @@ export class AuthController {
request.cookies.refresh_token
);
response.cookie("access_token", accessToken);
return { accessToken };
return new TokenDTO().from({ accessToken });
}
@Post("signOut")
@@ -146,15 +158,16 @@ export class AuthController {
private addTokensToResponse(
response: Response,
accessToken: string,
refreshToken: string
refreshToken?: string,
accessToken?: string
) {
response.cookie("access_token", accessToken);
response.cookie("refresh_token", refreshToken, {
path: "/api/auth/token",
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 30 * 3,
});
if (accessToken) response.cookie("access_token", accessToken);
if (refreshToken)
response.cookie("refresh_token", refreshToken, {
path: "/api/auth/token",
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 30 * 3,
});
return response;
}

View File

@@ -87,10 +87,16 @@ export class AuthService {
const hash = await argon.hash(newPassword);
this.prisma.user.update({
await this.prisma.refreshToken.deleteMany({
where: { userId: user.id },
});
await this.prisma.user.update({
where: { id: user.id },
data: { password: hash },
});
return this.createRefreshToken(user.id);
}
async createAccessToken(user: User, refreshTokenId: string) {
@@ -112,7 +118,12 @@ export class AuthService {
refreshTokenId: string;
};
await this.prisma.refreshToken.delete({ where: { id: refreshTokenId } });
await this.prisma.refreshToken
.delete({ where: { id: refreshTokenId } })
.catch((e) => {
// Ignore error if refresh token doesn't exist
if (e.code != "P2025") throw e;
});
}
async refreshAccessToken(refreshToken: string) {

View File

@@ -0,0 +1,15 @@
import { Expose, plainToClass } from "class-transformer";
export class TokenDTO {
@Expose()
accessToken: string;
@Expose()
refreshToken: string;
from(partial: Partial<TokenDTO>) {
return plainToClass(TokenDTO, partial, {
excludeExtraneousValues: true,
});
}
}

View File

@@ -1,12 +1,12 @@
{
"name": "pingvin-share-frontend",
"version": "0.6.0",
"version": "0.6.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "pingvin-share-frontend",
"version": "0.6.0",
"version": "0.6.1",
"dependencies": {
"@emotion/react": "^11.10.5",
"@emotion/server": "^11.10.0",

View File

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

View File

@@ -1,8 +1,8 @@
import { Stack, TextInput } from "@mantine/core";
import { ModalsContextProps } from "@mantine/modals/lib/context";
const showShareLinkModal = (modals: ModalsContextProps, shareId: string) => {
const link = `${window.location.origin}/share/${shareId}`;
const showShareLinkModal = (modals: ModalsContextProps, shareId: string, appUrl : string) => {
const link = `${appUrl}/share/${shareId}`;
return modals.openModal({
title: "Share link",
children: (

View File

@@ -15,7 +15,11 @@ import { TbCopy } from "react-icons/tb";
import { Share } from "../../../types/share.type";
import toast from "../../../utils/toast.util";
const showCompletedUploadModal = (modals: ModalsContextProps, share: Share) => {
const showCompletedUploadModal = (
modals: ModalsContextProps,
share: Share,
appUrl: string
) => {
return modals.openModal({
closeOnClickOutside: false,
withCloseButton: false,
@@ -25,15 +29,16 @@ const showCompletedUploadModal = (modals: ModalsContextProps, share: Share) => {
<Title order={4}>Share ready</Title>
</Stack>
),
children: <Body share={share} />,
children: <Body share={share} appUrl={appUrl} />,
});
};
const Body = ({ share }: { share: Share }) => {
const Body = ({ share, appUrl }: { share: Share; appUrl: string }) => {
const clipboard = useClipboard({ timeout: 500 });
const modals = useModals();
const router = useRouter();
const link = `${window.location.origin}/share/${share.id}`;
const link = `${appUrl}/share/${share.id}`;
return (
<Stack align="stretch">
<TextInput

View File

@@ -30,6 +30,7 @@ const showCreateUploadModal = (
modals: ModalsContextProps,
options: {
isUserSignedIn: boolean;
appUrl: string;
allowUnauthenticatedShares: boolean;
enableEmailRecepients: boolean;
},
@@ -53,6 +54,7 @@ const CreateUploadModalBody = ({
uploadCallback: (createShare: CreateShare) => void;
options: {
isUserSignedIn: boolean;
appUrl: string;
allowUnauthenticatedShares: boolean;
enableEmailRecepients: boolean;
};
@@ -156,7 +158,7 @@ const CreateUploadModalBody = ({
color: theme.colors.gray[6],
})}
>
{window.location.origin}/share/
{options.appUrl}/share/
{form.values.link == "" ? "myAwesomeShare" : form.values.link}
</Text>
<Grid align={form.errors.link ? "center" : "flex-end"}>

View File

@@ -19,6 +19,7 @@ import { useEffect, useState } from "react";
import { TbLink, TbTrash } from "react-icons/tb";
import showShareLinkModal from "../../components/account/showShareLinkModal";
import Meta from "../../components/Meta";
import useConfig from "../../hooks/config.hook";
import useUser from "../../hooks/user.hook";
import shareService from "../../services/share.service";
import { MyShare } from "../../types/share.type";
@@ -28,6 +29,8 @@ const MyShares = () => {
const modals = useModals();
const clipboard = useClipboard();
const router = useRouter();
const config = useConfig();
const { user } = useUser();
const [shares, setShares] = useState<MyShare[]>();
@@ -86,13 +89,17 @@ const MyShares = () => {
onClick={() => {
if (window.isSecureContext) {
clipboard.copy(
`${window.location.origin}/share/${share.id}`
`${config.get("APP_URL")}/share/${share.id}`
);
toast.success(
"Your link was copied to the keyboard."
);
} else {
showShareLinkModal(modals, share.id);
showShareLinkModal(
modals,
share.id,
config.get("APP_URL")
);
}
}}
>

View File

@@ -140,7 +140,7 @@ const Upload = () => {
.completeShare(createdShare.id)
.then(() => {
setisUploading(false);
showCompletedUploadModal(modals, createdShare);
showCompletedUploadModal(modals, createdShare, config.get("APP_URL"));
setFiles([]);
})
.catch(() =>
@@ -164,6 +164,7 @@ const Upload = () => {
modals,
{
isUserSignedIn: user ? true : false,
appUrl: config.get("APP_URL"),
allowUnauthenticatedShares: config.get(
"ALLOW_UNAUTHENTICATED_SHARES"
),

View File

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