otp actions

This commit is contained in:
2025-12-18 11:03:32 +00:00
parent a81d1de1e5
commit 40d6c7f248
4 changed files with 107 additions and 0 deletions

View 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;
};