( kind: DeploymentKind, deploymentId: string, email: string )
| 109 | } |
| 110 | |
| 111 | export async function getOTP( |
| 112 | kind: DeploymentKind, |
| 113 | deploymentId: string, |
| 114 | email: string |
| 115 | ): Promise<string | null> { |
| 116 | const keys = OTP_KEYS[kind] |
| 117 | const storageMethod = getStorageMethod() |
| 118 | |
| 119 | if (storageMethod === 'redis') { |
| 120 | const redis = getRedisClient() |
| 121 | if (!redis) throw new Error('Redis configured but client unavailable') |
| 122 | return redis.get(keys.redisKey(email, deploymentId)) |
| 123 | } |
| 124 | |
| 125 | const now = new Date() |
| 126 | const [record] = await db |
| 127 | .select({ value: verification.value }) |
| 128 | .from(verification) |
| 129 | .where( |
| 130 | and( |
| 131 | eq(verification.identifier, keys.dbIdentifier(email, deploymentId)), |
| 132 | gt(verification.expiresAt, now) |
| 133 | ) |
| 134 | ) |
| 135 | .limit(1) |
| 136 | |
| 137 | return record?.value ?? null |
| 138 | } |
| 139 | |
| 140 | /** |
| 141 | * Lua script for atomic OTP attempt increment in Redis. |
no test coverage detected