61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
/**
|
|
* Create (or promote) an admin user with a hashed email/password credential.
|
|
*
|
|
* Usage: npx tsx scripts/create-admin.ts <email> <password> [name]
|
|
*
|
|
* Passwords are hashed with Better Auth's own hasher and stored in the
|
|
* `account` table — never in plaintext. If the user already exists they are
|
|
* promoted to admin and their password is reset.
|
|
*/
|
|
import "dotenv/config";
|
|
import { prisma } from "@/lib/db";
|
|
import { auth } from "@/lib/auth/auth";
|
|
|
|
async function main() {
|
|
const [email, password, ...nameParts] = process.argv.slice(2);
|
|
if (!email || !password) {
|
|
console.error("Usage: npx tsx scripts/create-admin.ts <email> <password> [name]");
|
|
process.exit(1);
|
|
}
|
|
const name = nameParts.join(" ") || email.split("@")[0];
|
|
|
|
const ctx = await auth.$context;
|
|
const passwordHash = await ctx.password.hash(password);
|
|
|
|
const existing = await prisma.user.findUnique({ where: { email } });
|
|
|
|
const user = existing
|
|
? await prisma.user.update({
|
|
where: { id: existing.id },
|
|
data: { role: "admin", emailVerified: true, name: existing.name || name },
|
|
})
|
|
: await prisma.user.create({
|
|
data: { name, email, role: "admin", emailVerified: true },
|
|
});
|
|
|
|
// Upsert the credential account (no compound unique on account, so do it manually).
|
|
const cred = await prisma.account.findFirst({
|
|
where: { userId: user.id, providerId: "credential" },
|
|
select: { id: true },
|
|
});
|
|
if (cred) {
|
|
await prisma.account.update({ where: { id: cred.id }, data: { password: passwordHash } });
|
|
} else {
|
|
await prisma.account.create({
|
|
data: { accountId: user.id, providerId: "credential", userId: user.id, password: passwordHash },
|
|
});
|
|
}
|
|
|
|
console.log(`\n✅ Admin ${existing ? "updated" : "created"}: ${email}`);
|
|
console.log(` id: ${user.id}`);
|
|
console.log(` role: ${user.role}`);
|
|
console.log(` login: ${email} / (the password you provided)\n`);
|
|
}
|
|
|
|
main()
|
|
.catch((err) => {
|
|
console.error("create-admin failed:", err?.message ?? err);
|
|
process.exitCode = 1;
|
|
})
|
|
.finally(() => prisma.$disconnect());
|