pnp-chatbot-admin-v1 / utils /forgotPassword.ts
FauziIsyrinApridal
revisi 8
43be92e
"use server";
import { createClient } from "@/utils/supabase/server";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
export type ForgotResult =
| { ok: true; message: string }
| { ok: false; message: string };
export async function sendResetEmail(email: string): Promise<ForgotResult> {
const supabase = createClient();
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
return { ok: false, message: "Email tidak valid" };
}
// Admin-only: verify the email belongs to an admin user before sending reset link
try {
const adminClient = createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!,
);
// list users and find by email (no direct getUserByEmail in v2)
let page = 1;
const perPage = 200;
let foundRole: unknown = null;
while (true) {
const { data, error } = await adminClient.auth.admin.listUsers({ page, perPage });
if (error) throw error;
const users = data?.users || [];
const match = users.find((u) => u.email?.toLowerCase() === email.toLowerCase());
if (match) {
foundRole = match.user_metadata?.role;
break;
}
if (!data || users.length < perPage) break; // no more pages
page += 1;
// safety cap to avoid excessive loops
if (page > 50) break;
}
if (foundRole !== "admin") {
// Do not reveal whether the email exists; return a generic message
return {
ok: false,
message: "Akun tidak diizinkan melakukan reset di aplikasi admin.",
};
}
} catch {
// Fail closed: if role check fails, do not proceed
return {
ok: false,
message: "Gagal memverifikasi akun. Coba lagi.",
};
}
// Determine redirect URL for the password reset flow
const siteUrl =
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, "") ||
(process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000");
const redirectTo = `${siteUrl}/reset-password`;
const { error } = await supabase.auth.resetPasswordForEmail(email, {
redirectTo,
});
if (error) {
return { ok: false, message: "Gagal mengirim email reset. Coba lagi." };
}
return {
ok: true,
message: "Email reset telah dikirim. Periksa kotak masuk Anda.",
};
}