@@ -378,25 +378,26 @@ export const checkVerificationOTP = (opts: RequiredEmailOTPOptions) =>
378378 if ( ! verificationValue ) {
379379 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . INVALID_OTP ) ;
380380 }
381+ const otpIdentifier = `${ ctx . body . type } -otp-${ email } ` ;
381382 if ( verificationValue . expiresAt < new Date ( ) ) {
382- await ctx . context . internalAdapter . deleteVerificationValue (
383- verificationValue . id ,
383+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
384+ otpIdentifier ,
384385 ) ;
385386 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . OTP_EXPIRED ) ;
386387 }
387388
388389 const [ otpValue , attempts ] = splitAtLastColon ( verificationValue . value ) ;
389390 const allowedAttempts = opts ?. allowedAttempts || 3 ;
390391 if ( attempts && parseInt ( attempts ) >= allowedAttempts ) {
391- await ctx . context . internalAdapter . deleteVerificationValue (
392- verificationValue . id ,
392+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
393+ otpIdentifier ,
393394 ) ;
394395 throw APIError . from ( "FORBIDDEN" , ERROR_CODES . TOO_MANY_ATTEMPTS ) ;
395396 }
396397 const verified = await verifyStoredOTP ( ctx , opts , otpValue , ctx . body . otp ) ;
397398 if ( ! verified ) {
398- await ctx . context . internalAdapter . updateVerificationValue (
399- verificationValue . id ,
399+ await ctx . context . internalAdapter . updateVerificationByIdentifier (
400+ otpIdentifier ,
400401 {
401402 value : `${ otpValue } :${ parseInt ( attempts || "0" ) + 1 } ` ,
402403 } ,
@@ -1097,9 +1098,10 @@ export const requestEmailChangeEmailOTP = (opts: RequiredEmailOTPOptions) =>
10971098 if ( ! currentEmailVerificationValue ) {
10981099 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . INVALID_OTP ) ;
10991100 }
1101+ const currentEmailIdentifier = `email-verification-otp-${ email } ` ;
11001102 if ( currentEmailVerificationValue . expiresAt < new Date ( ) ) {
1101- await ctx . context . internalAdapter . deleteVerificationValue (
1102- currentEmailVerificationValue . id ,
1103+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1104+ currentEmailIdentifier ,
11031105 ) ;
11041106 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . OTP_EXPIRED ) ;
11051107 }
@@ -1109,8 +1111,8 @@ export const requestEmailChangeEmailOTP = (opts: RequiredEmailOTPOptions) =>
11091111 ) ;
11101112 const allowedAttempts = opts ?. allowedAttempts || 3 ;
11111113 if ( attempts && parseInt ( attempts ) >= allowedAttempts ) {
1112- await ctx . context . internalAdapter . deleteVerificationValue (
1113- currentEmailVerificationValue . id ,
1114+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1115+ currentEmailIdentifier ,
11141116 ) ;
11151117 throw APIError . from ( "FORBIDDEN" , ERROR_CODES . TOO_MANY_ATTEMPTS ) ;
11161118 }
@@ -1122,16 +1124,16 @@ export const requestEmailChangeEmailOTP = (opts: RequiredEmailOTPOptions) =>
11221124 ctx . body . otp ,
11231125 ) ;
11241126 if ( ! verified ) {
1125- await ctx . context . internalAdapter . updateVerificationValue (
1126- currentEmailVerificationValue . id ,
1127+ await ctx . context . internalAdapter . updateVerificationByIdentifier (
1128+ currentEmailIdentifier ,
11271129 {
11281130 value : `${ otpValue } :${ parseInt ( attempts || "0" ) + 1 } ` ,
11291131 } ,
11301132 ) ;
11311133 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . INVALID_OTP ) ;
11321134 }
1133- await ctx . context . internalAdapter . deleteVerificationValue (
1134- currentEmailVerificationValue . id ,
1135+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1136+ currentEmailIdentifier ,
11351137 ) ;
11361138 } else {
11371139 if ( ctx . body . otp ) {
@@ -1265,34 +1267,35 @@ export const changeEmailEmailOTP = (opts: RequiredEmailOTPOptions) =>
12651267 if ( ! verificationValue ) {
12661268 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . INVALID_OTP ) ;
12671269 }
1270+ const changeEmailIdentifier = `change-email-otp-${ email } -${ newEmail } ` ;
12681271 if ( verificationValue . expiresAt < new Date ( ) ) {
1269- await ctx . context . internalAdapter . deleteVerificationValue (
1270- verificationValue . id ,
1272+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1273+ changeEmailIdentifier ,
12711274 ) ;
12721275 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . OTP_EXPIRED ) ;
12731276 }
12741277
12751278 const [ otpValue , attempts ] = splitAtLastColon ( verificationValue . value ) ;
12761279 const allowedAttempts = opts ?. allowedAttempts || 3 ;
12771280 if ( attempts && parseInt ( attempts ) >= allowedAttempts ) {
1278- await ctx . context . internalAdapter . deleteVerificationValue (
1279- verificationValue . id ,
1281+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1282+ changeEmailIdentifier ,
12801283 ) ;
12811284 throw APIError . from ( "FORBIDDEN" , ERROR_CODES . TOO_MANY_ATTEMPTS ) ;
12821285 }
12831286
12841287 const verified = await verifyStoredOTP ( ctx , opts , otpValue , ctx . body . otp ) ;
12851288 if ( ! verified ) {
1286- await ctx . context . internalAdapter . updateVerificationValue (
1287- verificationValue . id ,
1289+ await ctx . context . internalAdapter . updateVerificationByIdentifier (
1290+ changeEmailIdentifier ,
12881291 {
12891292 value : `${ otpValue } :${ parseInt ( attempts || "0" ) + 1 } ` ,
12901293 } ,
12911294 ) ;
12921295 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . INVALID_OTP ) ;
12931296 }
1294- await ctx . context . internalAdapter . deleteVerificationValue (
1295- verificationValue . id ,
1297+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1298+ changeEmailIdentifier ,
12961299 ) ;
12971300
12981301 const currentUser =
@@ -1371,8 +1374,8 @@ async function atomicVerifyOTP(
13711374 }
13721375
13731376 if ( verificationValue . expiresAt < new Date ( ) ) {
1374- await ctx . context . internalAdapter . deleteVerificationValue (
1375- verificationValue . id ,
1377+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1378+ identifier ,
13761379 ) ;
13771380 throw APIError . from ( "BAD_REQUEST" , ERROR_CODES . OTP_EXPIRED ) ;
13781381 }
@@ -1381,16 +1384,14 @@ async function atomicVerifyOTP(
13811384 const allowedAttempts = opts ?. allowedAttempts || 3 ;
13821385
13831386 if ( attempts && parseInt ( attempts ) >= allowedAttempts ) {
1384- await ctx . context . internalAdapter . deleteVerificationValue (
1385- verificationValue . id ,
1387+ await ctx . context . internalAdapter . deleteVerificationByIdentifier (
1388+ identifier ,
13861389 ) ;
13871390 throw APIError . from ( "FORBIDDEN" , ERROR_CODES . TOO_MANY_ATTEMPTS ) ;
13881391 }
13891392
13901393 // Atomically delete token before verification to prevent race condition
1391- await ctx . context . internalAdapter . deleteVerificationValue (
1392- verificationValue . id ,
1393- ) ;
1394+ await ctx . context . internalAdapter . deleteVerificationByIdentifier ( identifier ) ;
13941395
13951396 const verified = await verifyStoredOTP ( ctx , opts , otpValue , providedOTP ) ;
13961397
0 commit comments