@@ -6,7 +6,7 @@ import { z } from 'zod'
66import { renderOTPEmail } from '@/components/emails/render-email'
77import { sendEmail } from '@/lib/email/mailer'
88import { createLogger } from '@/lib/logs/console/logger'
9- import { getRedisClient , markMessageAsProcessed , releaseLock } from '@/lib/redis'
9+ import { getRedisClient } from '@/lib/redis'
1010import { generateRequestId } from '@/lib/utils'
1111import { addCorsHeaders , setChatAuthCookie } from '@/app/api/chat/utils'
1212import { createErrorResponse , createSuccessResponse } from '@/app/api/workflows/utils'
@@ -21,83 +21,52 @@ function generateOTP() {
2121// We use 15 minutes (900 seconds) expiry for OTPs
2222const OTP_EXPIRY = 15 * 60
2323
24- // Store OTP in Redis
25- async function storeOTP ( email : string , chatId : string , otp : string ) : Promise < void > {
24+ async function storeOTP ( email : string , chatId : string , otp : string ) : Promise < boolean > {
2625 const key = `otp:${ email } :${ chatId } `
2726 const redis = getRedisClient ( )
2827
29- if ( redis ) {
30- // Use Redis if available
31- await redis . set ( key , otp , 'EX' , OTP_EXPIRY )
32- } else {
33- // Use the existing function as fallback to mark that an OTP exists
34- await markMessageAsProcessed ( key , OTP_EXPIRY )
28+ if ( ! redis ) {
29+ logger . warn ( 'Redis not available, OTP functionality requires Redis' )
30+ return false
31+ }
3532
36- // For the fallback case, we need to handle storing the OTP value separately
37- // since markMessageAsProcessed only stores "1"
38- const valueKey = `${ key } :value`
39- try {
40- // Access the in-memory cache directly - hacky but works for fallback
41- const inMemoryCache = ( global as any ) . inMemoryCache
42- if ( inMemoryCache ) {
43- const fullKey = `processed:${ valueKey } `
44- const expiry = OTP_EXPIRY ? Date . now ( ) + OTP_EXPIRY * 1000 : null
45- inMemoryCache . set ( fullKey , { value : otp , expiry } )
46- }
47- } catch ( error ) {
48- logger . error ( 'Error storing OTP in fallback cache:' , error )
49- }
33+ try {
34+ await redis . set ( key , otp , 'EX' , OTP_EXPIRY )
35+ return true
36+ } catch ( error ) {
37+ logger . error ( 'Error storing OTP in Redis:' , error )
38+ return false
5039 }
5140}
5241
53- // Get OTP from Redis
5442async function getOTP ( email : string , chatId : string ) : Promise < string | null > {
5543 const key = `otp:${ email } :${ chatId } `
5644 const redis = getRedisClient ( )
5745
58- if ( redis ) {
59- // Use Redis if available
60- return await redis . get ( key )
46+ if ( ! redis ) {
47+ return null
6148 }
62- // Use the existing function as fallback - check if it exists
63- const exists = await new Promise ( ( resolve ) => {
64- try {
65- // Check the in-memory cache directly - hacky but works for fallback
66- const inMemoryCache = ( global as any ) . inMemoryCache
67- const fullKey = `processed:${ key } `
68- const cacheEntry = inMemoryCache ?. get ( fullKey )
69- resolve ( ! ! cacheEntry )
70- } catch {
71- resolve ( false )
72- }
73- } )
74-
75- if ( ! exists ) return null
7649
77- // Try to get the value key
78- const valueKey = `${ key } :value`
7950 try {
80- const inMemoryCache = ( global as any ) . inMemoryCache
81- const fullKey = `processed:${ valueKey } `
82- const cacheEntry = inMemoryCache ?. get ( fullKey )
83- return cacheEntry ?. value || null
84- } catch {
51+ return await redis . get ( key )
52+ } catch ( error ) {
53+ logger . error ( 'Error getting OTP from Redis:' , error )
8554 return null
8655 }
8756}
8857
89- // Delete OTP from Redis
9058async function deleteOTP ( email : string , chatId : string ) : Promise < void > {
9159 const key = `otp:${ email } :${ chatId } `
9260 const redis = getRedisClient ( )
9361
94- if ( redis ) {
95- // Use Redis if available
62+ if ( ! redis ) {
63+ return
64+ }
65+
66+ try {
9667 await redis . del ( key )
97- } else {
98- // Use the existing function as fallback
99- await releaseLock ( `processed:${ key } ` )
100- await releaseLock ( `processed:${ key } :value` )
68+ } catch ( error ) {
69+ logger . error ( 'Error deleting OTP from Redis:' , error )
10170 }
10271}
10372
@@ -177,7 +146,17 @@ export async function POST(
177146
178147 const otp = generateOTP ( )
179148
180- await storeOTP ( email , deployment . id , otp )
149+ const stored = await storeOTP ( email , deployment . id , otp )
150+ if ( ! stored ) {
151+ logger . error ( `[${ requestId } ] Failed to store OTP - Redis unavailable` )
152+ return addCorsHeaders (
153+ createErrorResponse (
154+ 'Email verification temporarily unavailable, please try again later' ,
155+ 503
156+ ) ,
157+ request
158+ )
159+ }
181160
182161 const emailHtml = await renderOTPEmail (
183162 otp ,
0 commit comments