/** * Dev/admin: set a user's password without sending email (bypasses 429 rate limits). * * Requires in .env.local: * NEXT_PUBLIC_SUPABASE_URL * SUPABASE_SERVICE_ROLE_KEY (Dashboard → Project Settings → API → service_role) * * Usage: * npm run auth:reset-password -- you@example.com YourNewPassword */ import { createClient } from "@supabase/supabase-js"; import { readFileSync, existsSync } from "fs"; import { dirname, join } from "path"; import { fileURLToPath } from "url"; const root = join(dirname(fileURLToPath(import.meta.url)), ".."); function loadEnvLocal() { const path = join(root, ".env.local"); if (!existsSync(path)) return {}; const env = {}; for (const line of readFileSync(path, "utf8").split(/\r?\n/)) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; const eq = trimmed.indexOf("="); if (eq === -1) continue; const key = trimmed.slice(0, eq).trim(); let val = trimmed.slice(eq + 1).trim(); if ( (val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'")) ) { val = val.slice(1, -1); } env[key] = val; } return env; } const [, , emailArg, passwordArg] = process.argv; const email = emailArg?.trim().toLowerCase(); const password = passwordArg; if (!email || !password) { console.error( "Usage: npm run auth:reset-password -- \n" ); process.exit(1); } if (password.length < 6) { console.error("Password must be at least 6 characters."); process.exit(1); } const env = loadEnvLocal(); const url = env.NEXT_PUBLIC_SUPABASE_URL; const serviceKey = env.SUPABASE_SERVICE_ROLE_KEY; if (!url || !serviceKey) { console.error( "Missing NEXT_PUBLIC_SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY in .env.local" ); process.exit(1); } const admin = createClient(url, serviceKey, { auth: { autoRefreshToken: false, persistSession: false }, }); const { data: list, error: listError } = await admin.auth.admin.listUsers({ page: 1, perPage: 1000, }); if (listError) { console.error("listUsers failed:", listError.message); process.exit(1); } const user = list.users.find((u) => u.email?.toLowerCase() === email); if (!user) { console.error(`No user found with email: ${email}`); process.exit(1); } const { error: updateError } = await admin.auth.admin.updateUserById(user.id, { password, }); if (updateError) { console.error("updateUserById failed:", updateError.message); process.exit(1); } console.log(`Password updated for ${email} (${user.id})`); console.log("Sign in at /login/manager or /login/master with the new password.");