mirror of
https://github.com/stonith404/pingvin-share.git
synced 2025-02-19 01:55:48 -05:00
fix: store only 10 share tokens in the cookies and clear the expired ones
This commit is contained in:
parent
414bcecbb5
commit
e5a0c649e3
2 changed files with 53 additions and 11 deletions
|
@ -10,9 +10,11 @@ import {
|
|||
Res,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { JwtService } from "@nestjs/jwt";
|
||||
import { Throttle } from "@nestjs/throttler";
|
||||
import { User } from "@prisma/client";
|
||||
import { Request, Response } from "express";
|
||||
import * as moment from "moment";
|
||||
import { GetUser } from "src/auth/decorator/getUser.decorator";
|
||||
import { AdministratorGuard } from "src/auth/guard/isAdmin.guard";
|
||||
import { JwtGuard } from "src/auth/guard/jwt.guard";
|
||||
|
@ -29,7 +31,10 @@ import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
|
|||
import { ShareService } from "./share.service";
|
||||
@Controller("shares")
|
||||
export class ShareController {
|
||||
constructor(private shareService: ShareService) {}
|
||||
constructor(
|
||||
private shareService: ShareService,
|
||||
private jwtService: JwtService,
|
||||
) {}
|
||||
|
||||
@Get("all")
|
||||
@UseGuards(JwtGuard, AdministratorGuard)
|
||||
|
@ -121,10 +126,13 @@ export class ShareController {
|
|||
@Post(":id/token")
|
||||
async getShareToken(
|
||||
@Param("id") id: string,
|
||||
@Req() request: Request,
|
||||
@Res({ passthrough: true }) response: Response,
|
||||
@Body() body: SharePasswordDto,
|
||||
) {
|
||||
const token = await this.shareService.getShareToken(id, body.password);
|
||||
|
||||
this.clearShareTokenCookies(request, response);
|
||||
response.cookie(`share_${id}_token`, token, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
|
@ -132,4 +140,32 @@ export class ShareController {
|
|||
|
||||
return { token };
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the 10 most recent share token cookies and deletes the rest and all expired ones
|
||||
*/
|
||||
private clearShareTokenCookies(request: Request, response: Response) {
|
||||
const shareTokenCookies = Object.entries(request.cookies)
|
||||
.filter(([key]) => key.startsWith("share_") && key.endsWith("_token"))
|
||||
.map(([key, value]) => ({
|
||||
key,
|
||||
payload: this.jwtService.decode(value),
|
||||
}));
|
||||
|
||||
const expiredTokens = shareTokenCookies.filter(
|
||||
(cookie) => cookie.payload.exp < moment().unix(),
|
||||
);
|
||||
const validTokens = shareTokenCookies.filter(
|
||||
(cookie) => cookie.payload.exp >= moment().unix(),
|
||||
);
|
||||
|
||||
expiredTokens.forEach((cookie) => response.clearCookie(cookie.key));
|
||||
|
||||
if (validTokens.length > 10) {
|
||||
validTokens
|
||||
.sort((a, b) => a.payload.exp - b.payload.exp)
|
||||
.slice(0, -10)
|
||||
.forEach((cookie) => response.clearCookie(cookie.key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
Injectable,
|
||||
NotFoundException,
|
||||
} from "@nestjs/common";
|
||||
import { JwtService } from "@nestjs/jwt";
|
||||
import { JwtService, JwtSignOptions } from "@nestjs/jwt";
|
||||
import { Share, User } from "@prisma/client";
|
||||
import * as archiver from "archiver";
|
||||
import * as argon from "argon2";
|
||||
|
@ -328,15 +328,21 @@ export class ShareService {
|
|||
const { expiration } = await this.prisma.share.findUnique({
|
||||
where: { id: shareId },
|
||||
});
|
||||
return this.jwtService.sign(
|
||||
{
|
||||
shareId,
|
||||
},
|
||||
{
|
||||
expiresIn: moment(expiration).diff(new Date(), "seconds") + "s",
|
||||
secret: this.config.get("internal.jwtSecret"),
|
||||
},
|
||||
);
|
||||
|
||||
const tokenPayload = {
|
||||
shareId,
|
||||
iat: moment().unix(),
|
||||
};
|
||||
|
||||
const tokenOptions: JwtSignOptions = {
|
||||
secret: this.config.get("internal.jwtSecret"),
|
||||
};
|
||||
|
||||
if (!moment(expiration).isSame(0)) {
|
||||
tokenOptions.expiresIn = moment(expiration).diff(new Date(), "seconds");
|
||||
}
|
||||
|
||||
return this.jwtService.sign(tokenPayload, tokenOptions);
|
||||
}
|
||||
|
||||
async verifyShareToken(shareId: string, token: string) {
|
||||
|
|
Loading…
Add table
Reference in a new issue