@@ -14,8 +14,8 @@ import { ConfigService } from '@nestjs/config';
1414import { createSha256 , hashPassword } from '../../src/auth/security.utils' ;
1515import * as jwt from 'jsonwebtoken' ;
1616
17- const ACCESS_SECRET = 'test-access-secret' ;
18- const REFRESH_SECRET = 'test-refresh-secret' ;
17+ const ACCESS_SECRET = 'test-access-secret-at-least-32-characters-long ' ;
18+ const REFRESH_SECRET = 'test-refresh-secret-at-least-32-characters-long ' ;
1919
2020describe ( 'Fraud alert auto-block e2e' , ( ) => {
2121 let app : INestApplication ;
@@ -66,12 +66,14 @@ describe('Fraud alert auto-block e2e', () => {
6666 } ,
6767 findFirst : async ( { where } : any ) => {
6868 if ( ! where ) return null ;
69- return Array . from ( users . values ( ) ) . find ( ( u ) => {
70- for ( const k of Object . keys ( where ) ) {
71- if ( u [ k ] !== where [ k ] ) return false ;
72- }
73- return true ;
74- } ) ?? null ;
69+ return (
70+ Array . from ( users . values ( ) ) . find ( ( u ) => {
71+ for ( const k of Object . keys ( where ) ) {
72+ if ( u [ k ] !== where [ k ] ) return false ;
73+ }
74+ return true ;
75+ } ) ?? null
76+ ) ;
7577 } ,
7678 update : async ( { where, data } : any ) => {
7779 const user = users . get ( where . id ) ;
@@ -112,7 +114,10 @@ describe('Fraud alert auto-block e2e', () => {
112114 } ,
113115 update : async ( { where, data } : any ) => {
114116 const existing = blacklistedTokens . get ( where . jti ) ;
115- if ( existing ) { Object . assign ( existing , data ) ; return existing ; }
117+ if ( existing ) {
118+ Object . assign ( existing , data ) ;
119+ return existing ;
120+ }
116121 return data ;
117122 } ,
118123 count : async ( ) => blacklistedTokens . size ,
@@ -132,13 +137,25 @@ describe('Fraud alert auto-block e2e', () => {
132137 findUnique : async ( { where } : any ) => fraudAlerts . get ( where . id ) ?? null ,
133138 create : async ( { data } : any ) => {
134139 const id = nid ( ) ;
135- const record = { id, ...data , occurrenceCount : 1 , lastDetectedAt : new Date ( ) , status : 'OPEN' , autoBlocked : data . autoBlocked ?? false , createdAt : new Date ( ) , updatedAt : new Date ( ) } ;
140+ const record = {
141+ id,
142+ ...data ,
143+ occurrenceCount : 1 ,
144+ lastDetectedAt : new Date ( ) ,
145+ status : 'OPEN' ,
146+ autoBlocked : data . autoBlocked ?? false ,
147+ createdAt : new Date ( ) ,
148+ updatedAt : new Date ( ) ,
149+ } ;
136150 fraudAlerts . set ( id , record ) ;
137151 return record ;
138152 } ,
139153 update : async ( { where, data } : any ) => {
140154 const existing = fraudAlerts . get ( where . id ) ;
141- if ( existing ) { Object . assign ( existing , data ) ; return existing ; }
155+ if ( existing ) {
156+ Object . assign ( existing , data ) ;
157+ return existing ;
158+ }
142159 return data ;
143160 } ,
144161 findMany : async ( ) => Array . from ( fraudAlerts . values ( ) ) ,
@@ -212,7 +229,8 @@ describe('Fraud alert auto-block e2e', () => {
212229 if ( where ?. OR ) {
213230 match = false ;
214231 for ( const cond of where . OR ) {
215- if ( cond . refreshTokenJti && s . refreshTokenJti === cond . refreshTokenJti ) match = true ;
232+ if ( cond . refreshTokenJti && s . refreshTokenJti === cond . refreshTokenJti )
233+ match = true ;
216234 if ( cond . accessTokenJti && s . accessTokenJti === cond . accessTokenJti ) match = true ;
217235 }
218236 }
@@ -221,12 +239,17 @@ describe('Fraud alert auto-block e2e', () => {
221239 return null ;
222240 } ,
223241 findMany : async ( { where } : any ) => {
224- return Array . from ( sessions . values ( ) ) . filter ( ( s ) => ! where ?. userId || s . userId === where . userId ) ;
242+ return Array . from ( sessions . values ( ) ) . filter (
243+ ( s ) => ! where ?. userId || s . userId === where . userId ,
244+ ) ;
225245 } ,
226246 updateMany : async ( { where, data } : any ) => {
227247 let count = 0 ;
228248 for ( const s of sessions . values ( ) ) {
229- if ( where ?. userId && s . userId === where . userId ) { Object . assign ( s , data ) ; count ++ ; }
249+ if ( where ?. userId && s . userId === where . userId ) {
250+ Object . assign ( s , data ) ;
251+ count ++ ;
252+ }
230253 }
231254 return { count } ;
232255 } ,
@@ -312,21 +335,23 @@ describe('Fraud alert auto-block e2e', () => {
312335 {
313336 provide : FraudService ,
314337 useValue : {
315- handleTokenReuse : jest . fn ( ) . mockImplementation ( async ( userId : string , jti : string , ip : string ) => {
316- await prisma . user . update ( { where : { id : userId } , data : { isBlocked : true } } ) ;
317- await prisma . fraudAlert . create ( {
318- data : {
319- userId,
320- pattern : 'TOKEN_REUSE' ,
321- severity : 'CRITICAL' ,
322- status : 'OPEN' ,
323- description : `Token reuse detected for user ${ userId } ` ,
324- ipAddress : ip ,
325- evidence : { jti } ,
326- autoBlocked : true ,
327- } ,
328- } ) ;
329- } ) ,
338+ handleTokenReuse : jest
339+ . fn ( )
340+ . mockImplementation ( async ( userId : string , jti : string , ip : string ) => {
341+ await prisma . user . update ( { where : { id : userId } , data : { isBlocked : true } } ) ;
342+ await prisma . fraudAlert . create ( {
343+ data : {
344+ userId,
345+ pattern : 'TOKEN_REUSE' ,
346+ severity : 'CRITICAL' ,
347+ status : 'OPEN' ,
348+ description : `Token reuse detected for user ${ userId } ` ,
349+ ipAddress : ip ,
350+ evidence : { jti } ,
351+ autoBlocked : true ,
352+ } ,
353+ } ) ;
354+ } ) ,
330355 evaluateFailedLogin : jest . fn ( ) . mockResolvedValue ( null ) ,
331356 evaluateSuccessfulLogin : jest . fn ( ) . mockResolvedValue ( [ ] ) ,
332357 } ,
0 commit comments