66 lines
2.5 KiB
TypeScript
66 lines
2.5 KiB
TypeScript
|
|
import { API_BASE } from "./env";
|
||
|
|
import { solveCaptcha } from "./captcha";
|
||
|
|
import { getOtpFromRedis } from "./otp";
|
||
|
|
|
||
|
|
export interface RegisterInput {
|
||
|
|
email: string;
|
||
|
|
password: string;
|
||
|
|
first_name?: string;
|
||
|
|
last_name?: string;
|
||
|
|
phone?: string;
|
||
|
|
intent?: string;
|
||
|
|
profession?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** POST /api/auth/register (captcha-solved automatically). */
|
||
|
|
export async function apiRegister(input: RegisterInput): Promise<{ user_id: string; [k: string]: any }> {
|
||
|
|
const { captcha_id, captcha_answer } = await solveCaptcha();
|
||
|
|
const res = await fetch(`${API_BASE}/auth/register`, {
|
||
|
|
method: "POST",
|
||
|
|
headers: { "Content-Type": "application/json" },
|
||
|
|
body: JSON.stringify({ ...input, captcha_id, captcha_answer }),
|
||
|
|
});
|
||
|
|
const data = await res.json();
|
||
|
|
if (!res.ok) {
|
||
|
|
throw new Error(`Register failed (${res.status}): ${JSON.stringify(data)}`);
|
||
|
|
}
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** POST /api/auth/verify-email, sourcing the OTP straight from Redis. */
|
||
|
|
export async function apiVerifyEmail(email: string, userId: string): Promise<boolean> {
|
||
|
|
const otp = await getOtpFromRedis(userId);
|
||
|
|
if (!otp) {
|
||
|
|
console.log(`⚠️ Could not retrieve OTP from Redis for user ${userId}`);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
const res = await fetch(`${API_BASE}/auth/verify-email`, {
|
||
|
|
method: "POST",
|
||
|
|
headers: { "Content-Type": "application/json" },
|
||
|
|
body: JSON.stringify({ otp, email }),
|
||
|
|
});
|
||
|
|
return res.ok;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** POST /api/auth/login (captcha-solved automatically). Returns null on non-2xx. */
|
||
|
|
export async function apiLogin(email: string, password: string): Promise<{ access_token: string; [k: string]: any } | null> {
|
||
|
|
const { captcha_id, captcha_answer } = await solveCaptcha();
|
||
|
|
const res = await fetch(`${API_BASE}/auth/login`, {
|
||
|
|
method: "POST",
|
||
|
|
headers: { "Content-Type": "application/json" },
|
||
|
|
body: JSON.stringify({ email, password, captcha_id, captcha_answer }),
|
||
|
|
});
|
||
|
|
if (!res.ok) return null;
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Full register → verify → login convenience flow, returning the access token. */
|
||
|
|
export async function registerVerifyLogin(input: RegisterInput): Promise<{ user_id: string; access_token: string }> {
|
||
|
|
const regData = await apiRegister(input);
|
||
|
|
const verified = await apiVerifyEmail(input.email, regData.user_id);
|
||
|
|
if (!verified) throw new Error(`Email verification failed for ${input.email}`);
|
||
|
|
const loginData = await apiLogin(input.email, input.password);
|
||
|
|
if (!loginData) throw new Error(`Login failed for ${input.email} after verification`);
|
||
|
|
return { user_id: regData.user_id, access_token: loginData.access_token };
|
||
|
|
}
|