@@ -10,9 +10,11 @@ import {
1010 Res ,
1111 UseGuards ,
1212} from "@nestjs/common" ;
13+ import { JwtService } from "@nestjs/jwt" ;
1314import { Throttle } from "@nestjs/throttler" ;
1415import { User } from "@prisma/client" ;
1516import { Request , Response } from "express" ;
17+ import * as moment from "moment" ;
1618import { GetUser } from "src/auth/decorator/getUser.decorator" ;
1719import { AdministratorGuard } from "src/auth/guard/isAdmin.guard" ;
1820import { JwtGuard } from "src/auth/guard/jwt.guard" ;
@@ -29,7 +31,10 @@ import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
2931import { ShareService } from "./share.service" ;
3032@Controller ( "shares" )
3133export class ShareController {
32- constructor ( private shareService : ShareService ) { }
34+ constructor (
35+ private shareService : ShareService ,
36+ private jwtService : JwtService ,
37+ ) { }
3338
3439 @Get ( "all" )
3540 @UseGuards ( JwtGuard , AdministratorGuard )
@@ -121,15 +126,46 @@ export class ShareController {
121126 @Post ( ":id/token" )
122127 async getShareToken (
123128 @Param ( "id" ) id : string ,
129+ @Req ( ) request : Request ,
124130 @Res ( { passthrough : true } ) response : Response ,
125131 @Body ( ) body : SharePasswordDto ,
126132 ) {
127133 const token = await this . shareService . getShareToken ( id , body . password ) ;
134+
135+ this . clearShareTokenCookies ( request , response ) ;
128136 response . cookie ( `share_${ id } _token` , token , {
129137 path : "/" ,
130138 httpOnly : true ,
131139 } ) ;
132140
133141 return { token } ;
134142 }
143+
144+ /**
145+ * Keeps the 10 most recent share token cookies and deletes the rest and all expired ones
146+ */
147+ private clearShareTokenCookies ( request : Request , response : Response ) {
148+ const shareTokenCookies = Object . entries ( request . cookies )
149+ . filter ( ( [ key ] ) => key . startsWith ( "share_" ) && key . endsWith ( "_token" ) )
150+ . map ( ( [ key , value ] ) => ( {
151+ key,
152+ payload : this . jwtService . decode ( value ) ,
153+ } ) ) ;
154+
155+ const expiredTokens = shareTokenCookies . filter (
156+ ( cookie ) => cookie . payload . exp < moment ( ) . unix ( ) ,
157+ ) ;
158+ const validTokens = shareTokenCookies . filter (
159+ ( cookie ) => cookie . payload . exp >= moment ( ) . unix ( ) ,
160+ ) ;
161+
162+ expiredTokens . forEach ( ( cookie ) => response . clearCookie ( cookie . key ) ) ;
163+
164+ if ( validTokens . length > 10 ) {
165+ validTokens
166+ . sort ( ( a , b ) => a . payload . exp - b . payload . exp )
167+ . slice ( 0 , - 10 )
168+ . forEach ( ( cookie ) => response . clearCookie ( cookie . key ) ) ;
169+ }
170+ }
135171}
0 commit comments