add crm auth, email, status update and search
All checks were successful
Auto Deploy / deploy (push) Successful in 1m7s

This commit is contained in:
deonisii
2026-04-17 21:29:14 +03:00
parent 246fb6d52d
commit 4f67bca4be
16 changed files with 502 additions and 35 deletions

71
lib/auth.ts Normal file
View File

@@ -0,0 +1,71 @@
const SESSION_COOKIE = "wp_admin_session";
const SESSION_TTL_SECONDS = 60 * 60 * 24 * 7;
function getSecret() {
const secret = process.env.ADMIN_SESSION_SECRET;
if (!secret) {
throw new Error("ADMIN_SESSION_SECRET is not set");
}
return secret;
}
function toHex(buffer: ArrayBuffer) {
return Array.from(new Uint8Array(buffer))
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
async function sign(value: string) {
const key = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(getSecret()),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signature = await crypto.subtle.sign(
"HMAC",
key,
new TextEncoder().encode(value)
);
return toHex(signature);
}
export async function createSessionToken(email: string) {
const expiresAt = Math.floor(Date.now() / 1000) + SESSION_TTL_SECONDS;
const payload = `${email}.${expiresAt}`;
const signature = await sign(payload);
return `${payload}.${signature}`;
}
export async function verifySessionToken(token?: string | null) {
if (!token) return false;
const parts = token.split(".");
if (parts.length < 3) return false;
const signature = parts.pop()!;
const expiresAt = Number(parts.pop());
const email = parts.join(".");
if (!email || !expiresAt || Number.isNaN(expiresAt)) return false;
if (expiresAt < Math.floor(Date.now() / 1000)) return false;
const payload = `${email}.${expiresAt}`;
const expectedSignature = await sign(payload);
return signature === expectedSignature;
}
export function getSessionCookieName() {
return SESSION_COOKIE;
}
export function getAdminCredentials() {
return {
email: process.env.ADMIN_EMAIL || "",
password: process.env.ADMIN_PASSWORD || "",
};
}