otp actions
This commit is contained in:
48
website/src/actions/otp/verify-otp.ts
Normal file
48
website/src/actions/otp/verify-otp.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { z } from "astro/zod";
|
||||
import { defineAction } from "astro:actions";
|
||||
import { and, db, eq, gte, Otp, SendmailToken } from "astro:db";
|
||||
|
||||
export default defineAction({
|
||||
input: z.object({
|
||||
guess: z.string().length(6),
|
||||
lenient: z.boolean().default(false),
|
||||
userId: z.string().nonempty(),
|
||||
}),
|
||||
handler: verifyOtp,
|
||||
});
|
||||
|
||||
async function verifyOtp({ guess, lenient, userId }: VerifyOtpParams) {
|
||||
const leniency = lenient ? 1000 * 60 : 0;
|
||||
const isOtpCorrect =
|
||||
(await db.$count(
|
||||
Otp,
|
||||
and(
|
||||
eq(Otp.userId, userId),
|
||||
eq(Otp.value, guess),
|
||||
gte(Otp.validUntil, Date.now() - leniency),
|
||||
),
|
||||
)) > 0;
|
||||
|
||||
if (!isOtpCorrect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await db.delete(Otp).where(and(eq(Otp.userId, userId), eq(Otp.value, guess)));
|
||||
|
||||
const token = randomBytes(256).toString("hex");
|
||||
await db.insert(SendmailToken).values({
|
||||
userId,
|
||||
value: token,
|
||||
createdAt: Date.now(),
|
||||
validUntil: Date.now() + 60_000,
|
||||
});
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
type VerifyOtpParams = {
|
||||
guess: string;
|
||||
lenient: boolean;
|
||||
userId: string;
|
||||
};
|
||||
Reference in New Issue
Block a user