UNPKG

@proofkit/cli

Version:

Create web application with the ProofKit stack

137 lines (122 loc) 4.11 kB
import { generateRandomOTP } from "./index"; import { encodeBase32 } from "@oslojs/encoding"; import { cookies } from "next/headers"; import { getCurrentSession } from "./session"; import { emailVerificationLayout } from "../db/client"; import { TemailVerification } from "../db/emailVerification"; import { sendEmail } from "../email"; /** * An Email Verification Request is a record in the email verification table that is created when a user requests to change their email address. It's like a temporary session which can expire if the user doesn't verify the new email address within a certain amount of time. */ /** * Get a user's email verification request. * @param userId - The ID of the user. * @param id - The ID of the email verification request. * @returns The email verification request, or null if it doesn't exist. */ export async function getUserEmailVerificationRequest( userId: string, id: string, ): Promise<TemailVerification | null> { const result = await emailVerificationLayout.maybeFindFirst({ query: { id_user: `==${userId}`, id: `==${id}` }, }); return result?.data.fieldData ?? null; } /** * Create a new email verification request for a user. * @param id_user - The ID of the user. * @param email - The email address to verify. * @returns The email verification request. */ export async function createEmailVerificationRequest( id_user: string, email: string, ): Promise<TemailVerification> { deleteUserEmailVerificationRequest(id_user); const idBytes = new Uint8Array(20); crypto.getRandomValues(idBytes); const id = encodeBase32(idBytes).toLowerCase(); const code = generateRandomOTP(); const expiresAt = new Date(Date.now() + 1000 * 60 * 10); const request: TemailVerification = { id, code, expires_at: Math.floor(expiresAt.getTime() / 1000), email, id_user, }; await emailVerificationLayout.create({ fieldData: request, }); return request; } /** * Delete a user's email verification request. * @param id_user - The ID of the user. */ export async function deleteUserEmailVerificationRequest( id_user: string, ): Promise<void> { const result = await emailVerificationLayout.maybeFindFirst({ query: { id_user: `==${id_user}` }, }); if (result === null) return; await emailVerificationLayout.delete({ recordId: result.data.recordId }); } /** * Send a verification email to a user. * @param email - The email address to send the verification email to. * @param code - The verification code to send to the user. */ export async function sendVerificationEmail( email: string, code: string, ): Promise<void> { await sendEmail({ to: email, code, type: "verification" }); } /** * Set a cookie for a user's email verification request. * @param request - The email verification request. */ export async function setEmailVerificationRequestCookie( request: TemailVerification, ): Promise<void> { (await cookies()).set("email_verification", request.id, { httpOnly: true, path: "/", secure: process.env.NODE_ENV === "production", sameSite: "lax", expires: request.expires_at ? new Date(request.expires_at * 1000) : new Date(Date.now() + 1000 * 60 * 60), }); } /** * Delete the cookie for a user's email verification request. */ export async function deleteEmailVerificationRequestCookie(): Promise<void> { (await cookies()).set("email_verification", "", { httpOnly: true, path: "/", secure: process.env.NODE_ENV === "production", sameSite: "lax", maxAge: 0, }); } /** * Get a user's email verification request from the cookie. * @returns The email verification request, or null if it doesn't exist. */ export async function getUserEmailVerificationRequestFromRequest(): Promise<TemailVerification | null> { const { user } = await getCurrentSession(); if (user === null) { return null; } const id = (await cookies()).get("email_verification")?.value ?? null; if (id === null) { return null; } const request = await getUserEmailVerificationRequest(user.id, id); return request; }