Spaces:
Sleeping
Sleeping
| "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.", | |
| }; | |
| } | |