11import httpMocks from 'node-mocks-http'
22import {
33 createRequestWithEmail ,
4- createRequestWithEmailAndOtp ,
4+ createRequestWithEmailAndIpAndOtp ,
55 createRequestWithUser ,
66 userModelMock ,
77} from '../../../../../test/server/api/util'
@@ -116,6 +116,7 @@ describe('LoginController', () => {
116116 const mailJobFailure = jest . fn ( )
117117 const mailJobSuccess = jest . fn ( )
118118
119+ const getRedisKey = jest . fn ( )
119120 const deleteOtpByEmail = jest . fn ( )
120121 const setOtpForEmail = jest . fn ( )
121122 const getOtpForEmail = jest . fn ( )
@@ -124,7 +125,7 @@ describe('LoginController', () => {
124125 const authService = new AuthService (
125126 { hash, compare } ,
126127 { mailOTP, initMailer, mailJobFailure, mailJobSuccess } ,
127- { deleteOtpByEmail, setOtpForEmail, getOtpForEmail } ,
128+ { getRedisKey , deleteOtpByEmail, setOtpForEmail, getOtpForEmail } ,
128129 new UserRepository ( new UserMapper ( urlMapper ) , urlMapper ) ,
129130 )
130131 const controller = new LoginController ( authService )
@@ -152,6 +153,7 @@ describe('LoginController', () => {
152153 expect ( res . ok ) . toHaveBeenCalled ( )
153154 expect ( setOtpForEmail ) . toHaveBeenCalledWith (
154155 email ,
156+ ip ,
155157 expect . objectContaining ( {
156158 hashedOtp : otp ,
157159 retries : expect . any ( Number ) ,
@@ -190,6 +192,7 @@ describe('LoginController', () => {
190192 describe ( 'verifyOtp tests' , ( ) => {
191193192194 const otp = '1'
195+ const ip = '1.1.1.1' // This should match the IP set in createRequestWithEmailAndIpAndOtp
193196
194197 const hash = jest . fn ( )
195198 const compare = jest . fn ( )
@@ -199,6 +202,7 @@ describe('LoginController', () => {
199202 const mailJobFailure = jest . fn ( )
200203 const mailJobSuccess = jest . fn ( )
201204
205+ const getRedisKey = jest . fn ( )
202206 const deleteOtpByEmail = jest . fn ( )
203207 const setOtpForEmail = jest . fn ( )
204208 const getOtpForEmail = jest . fn ( )
@@ -217,7 +221,7 @@ describe('LoginController', () => {
217221 const authService = new AuthService (
218222 { hash, compare } ,
219223 { mailOTP, initMailer, mailJobFailure, mailJobSuccess } ,
220- { deleteOtpByEmail, setOtpForEmail, getOtpForEmail } ,
224+ { getRedisKey , deleteOtpByEmail, setOtpForEmail, getOtpForEmail } ,
221225 userRepository ,
222226 )
223227
@@ -243,54 +247,54 @@ describe('LoginController', () => {
243247 test ( 'valid email and otp' , async ( ) => {
244248 const user = { id : 1 , email }
245249
246- getOtpForEmail . mockImplementation ( ( e ) =>
250+ getOtpForEmail . mockImplementation ( ( e , i ) =>
247251 Promise . resolve (
248- e === email
252+ e === email && i === ip
249253 ? {
250254 hashedOtp : otp ,
251255 retries : 100 ,
252256 }
253257 : null ,
254258 ) ,
255259 )
256- const req = createRequestWithEmailAndOtp ( email , otp )
260+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , otp )
257261 const res = getMockResponse ( )
258262 findOrCreateWithEmail . mockResolvedValue ( user )
259263
260264 await controller . verifyOtp ( req , res )
261265
262- expect ( deleteOtpByEmail ) . toHaveBeenCalledWith ( email )
266+ expect ( deleteOtpByEmail ) . toHaveBeenCalledWith ( email , ip )
263267 expect ( req . session ! . user ) . toStrictEqual ( user )
264268 expect ( res . ok ) . toHaveBeenCalled ( )
265269 } )
266270
267271 test ( 'valid email, wrong otp and expiring' , async ( ) => {
268272 const badOtp = '0'
269273
270- getOtpForEmail . mockImplementation ( ( e ) =>
274+ getOtpForEmail . mockImplementation ( ( e , i ) =>
271275 Promise . resolve (
272- e === email
276+ e === email && i === ip
273277 ? {
274278 hashedOtp : otp ,
275279 retries : 1 ,
276280 }
277281 : null ,
278282 ) ,
279283 )
280- const req = createRequestWithEmailAndOtp ( email , badOtp )
284+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , badOtp )
281285 const res = getMockResponse ( )
282286
283287 await controller . verifyOtp ( req , res )
284288
285- expect ( deleteOtpByEmail ) . toHaveBeenCalledWith ( email )
289+ expect ( deleteOtpByEmail ) . toHaveBeenCalledWith ( email , ip )
286290 expect ( req . session ! . user ) . toBeUndefined ( )
287291 expect ( res . unauthorized ) . toHaveBeenCalled ( )
288292 } )
289293
290294 test ( 'valid email and no otp in cache' , async ( ) => {
291295 getOtpForEmail . mockResolvedValue ( null )
292296
293- const req = createRequestWithEmailAndOtp ( email , otp )
297+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , otp )
294298 const res = getMockResponse ( )
295299
296300 await controller . verifyOtp ( req , res )
@@ -302,9 +306,9 @@ describe('LoginController', () => {
302306
303307 test ( 'valid email and wrong otp with retries left' , async ( ) => {
304308 const badOtp = '0'
305- getOtpForEmail . mockImplementation ( ( e ) =>
309+ getOtpForEmail . mockImplementation ( ( e , i ) =>
306310 Promise . resolve (
307- e === email
311+ e === email && i === ip
308312 ? {
309313 hashedOtp : otp ,
310314 retries : 100 ,
@@ -313,12 +317,12 @@ describe('LoginController', () => {
313317 ) ,
314318 )
315319
316- const req = createRequestWithEmailAndOtp ( email , badOtp )
320+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , badOtp )
317321 const res = getMockResponse ( )
318322
319323 await controller . verifyOtp ( req , res )
320324
321- expect ( setOtpForEmail ) . toHaveBeenCalledWith ( email , {
325+ expect ( setOtpForEmail ) . toHaveBeenCalledWith ( email , ip , {
322326 hashedOtp : otp ,
323327 retries : 99 ,
324328 } )
@@ -327,17 +331,17 @@ describe('LoginController', () => {
327331 } )
328332
329333 test ( 'no email and has valid otp in request' , async ( ) => {
330- getOtpForEmail . mockImplementation ( ( e ) =>
334+ getOtpForEmail . mockImplementation ( ( e , i ) =>
331335 Promise . resolve (
332- e === email
336+ e === email && i === ip
333337 ? {
334338 hashedOtp : otp ,
335339 retries : 100 ,
336340 }
337341 : null ,
338342 ) ,
339343 )
340- const req = createRequestWithEmailAndOtp ( undefined , '1' )
344+ const req = createRequestWithEmailAndIpAndOtp ( undefined , ip , otp )
341345 const res = getMockResponse ( )
342346
343347 await controller . verifyOtp ( req , res )
@@ -351,7 +355,7 @@ describe('LoginController', () => {
351355
352356 test ( 'cache down' , async ( ) => {
353357 getOtpForEmail . mockRejectedValue ( new Error ( ) )
354- const req = createRequestWithEmailAndOtp ( email , otp )
358+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , otp )
355359 const res = getMockResponse ( )
356360
357361 await controller . verifyOtp ( req , res )
@@ -363,9 +367,9 @@ describe('LoginController', () => {
363367 } )
364368
365369 test ( 'db down' , async ( ) => {
366- getOtpForEmail . mockImplementation ( ( e ) =>
370+ getOtpForEmail . mockImplementation ( ( e , i ) =>
367371 Promise . resolve (
368- e === email
372+ e === email && i === ip
369373 ? {
370374 hashedOtp : otp ,
371375 retries : 100 ,
@@ -375,7 +379,7 @@ describe('LoginController', () => {
375379 )
376380 findOrCreateWithEmail . mockRejectedValue ( new Error ( ) )
377381
378- const req = createRequestWithEmailAndOtp ( email , otp )
382+ const req = createRequestWithEmailAndIpAndOtp ( email , ip , otp )
379383 const res = getMockResponse ( )
380384
381385 await controller . verifyOtp ( req , res )
0 commit comments