@@ -10,9 +10,11 @@ import {
10
10
Res ,
11
11
UseGuards ,
12
12
} from "@nestjs/common" ;
13
+ import { JwtService } from "@nestjs/jwt" ;
13
14
import { Throttle } from "@nestjs/throttler" ;
14
15
import { User } from "@prisma/client" ;
15
16
import { Request , Response } from "express" ;
17
+ import * as moment from "moment" ;
16
18
import { GetUser } from "src/auth/decorator/getUser.decorator" ;
17
19
import { AdministratorGuard } from "src/auth/guard/isAdmin.guard" ;
18
20
import { JwtGuard } from "src/auth/guard/jwt.guard" ;
@@ -29,7 +31,10 @@ import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
29
31
import { ShareService } from "./share.service" ;
30
32
@Controller ( "shares" )
31
33
export class ShareController {
32
- constructor ( private shareService : ShareService ) { }
34
+ constructor (
35
+ private shareService : ShareService ,
36
+ private jwtService : JwtService ,
37
+ ) { }
33
38
34
39
@Get ( "all" )
35
40
@UseGuards ( JwtGuard , AdministratorGuard )
@@ -121,15 +126,46 @@ export class ShareController {
121
126
@Post ( ":id/token" )
122
127
async getShareToken (
123
128
@Param ( "id" ) id : string ,
129
+ @Req ( ) request : Request ,
124
130
@Res ( { passthrough : true } ) response : Response ,
125
131
@Body ( ) body : SharePasswordDto ,
126
132
) {
127
133
const token = await this . shareService . getShareToken ( id , body . password ) ;
134
+
135
+ this . clearShareTokenCookies ( request , response ) ;
128
136
response . cookie ( `share_${ id } _token` , token , {
129
137
path : "/" ,
130
138
httpOnly : true ,
131
139
} ) ;
132
140
133
141
return { token } ;
134
142
}
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
+ }
135
171
}
0 commit comments