style: format code biome
This commit is contained in:
1 parent
8efd032cc6
commit
df38dccbf1
735 files changed
+128321
-120870
No files matched your search
+34
-21
@@ -16,28 +16,36 @@ import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
/** Secret mixed into the digest. Requires at least one of APP_KEY or AUTH_SECRET. */
|
||||
function verifySecret(): string {
|
||||
const secret = env.APP_KEY || env.AUTH_SECRET;
|
||||
if (!secret) throw new Error("APP_KEY or AUTH_SECRET must be set for email verification");
|
||||
return secret;
|
||||
const secret = env.APP_KEY || env.AUTH_SECRET;
|
||||
if (!secret)
|
||||
throw new Error(
|
||||
"APP_KEY or AUTH_SECRET must be set for email verification",
|
||||
);
|
||||
return secret;
|
||||
}
|
||||
|
||||
/** Compute the verification token for an email (lowercased + trimmed). */
|
||||
export async function verificationToken(email: string): Promise<string> {
|
||||
const normalised = email.trim().toLowerCase();
|
||||
return createHash("sha256").update(`${normalised}|${verifySecret()}`).digest("hex");
|
||||
const normalised = email.trim().toLowerCase();
|
||||
return createHash("sha256")
|
||||
.update(`${normalised}|${verifySecret()}`)
|
||||
.digest("hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant-time check that `token` matches the expected digest for `email`.
|
||||
* Returns false on any length/format mismatch rather than throwing.
|
||||
*/
|
||||
export async function isValidVerificationToken(email: string, token: string): Promise<boolean> {
|
||||
if (!email || !token || !/^[a-f0-9]{64}$/i.test(token)) return false;
|
||||
const expected = await verificationToken(email);
|
||||
const a = Buffer.from(expected, "utf8");
|
||||
const b = Buffer.from(token.toLowerCase(), "utf8");
|
||||
if (a.length !== b.length) return false;
|
||||
return timingSafeEqual(a, b);
|
||||
export async function isValidVerificationToken(
|
||||
email: string,
|
||||
token: string,
|
||||
): Promise<boolean> {
|
||||
if (!email || !token || !/^[a-f0-9]{64}$/i.test(token)) return false;
|
||||
const expected = await verificationToken(email);
|
||||
const a = Buffer.from(expected, "utf8");
|
||||
const b = Buffer.from(token.toLowerCase(), "utf8");
|
||||
if (a.length !== b.length) return false;
|
||||
return timingSafeEqual(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,16 +53,17 @@ export async function isValidVerificationToken(email: string, token: string): Pr
|
||||
* is unconfigured (sendMail returns false).
|
||||
*/
|
||||
export async function sendVerification(email: string): Promise<boolean> {
|
||||
const normalised = email.trim().toLowerCase();
|
||||
if (!normalised) return false;
|
||||
const normalised = email.trim().toLowerCase();
|
||||
if (!normalised) return false;
|
||||
|
||||
const token = await verificationToken(normalised);
|
||||
const base = env.APP_URL.replace(/\/+$/, "");
|
||||
const link = `${base}/verify?token=${encodeURIComponent(token)}&email=${encodeURIComponent(normalised)}`;
|
||||
const token = await verificationToken(normalised);
|
||||
const base = env.APP_URL.replace(/\/+$/, "");
|
||||
const link = `${base}/verify?token=${encodeURIComponent(token)}&email=${encodeURIComponent(normalised)}`;
|
||||
|
||||
const hotelName = (await siteSettings.get("hotel_name", env.HOTEL_NAME)) ?? env.HOTEL_NAME;
|
||||
const hotelName =
|
||||
(await siteSettings.get("hotel_name", env.HOTEL_NAME)) ?? env.HOTEL_NAME;
|
||||
|
||||
const html = `
|
||||
const html = `
|
||||
<div style="font-family:sans-serif;line-height:1.5;color:#0f172a">
|
||||
<h2 style="margin:0 0 0.5rem">Verify your email</h2>
|
||||
<p>Welcome to ${escapeHtml(hotelName)}! Confirm this email address to finish setting up your account.</p>
|
||||
@@ -69,9 +78,13 @@ export async function sendVerification(email: string): Promise<boolean> {
|
||||
</div>
|
||||
`.trim();
|
||||
|
||||
return sendMail(normalised, `Verify your email · ${hotelName}`, html);
|
||||
return sendMail(normalised, `Verify your email · ${hotelName}`, html);
|
||||
}
|
||||
|
||||
function escapeHtml(s: string): string {
|
||||
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
||||
return s
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
Reference in new issue
Block a user