Add user management
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
import { createAuthClient } from "better-auth/client";
|
||||
import type { auth } from "@/lib/auth";
|
||||
import { inferAdditionalFields } from "better-auth/client/plugins";
|
||||
import { createAuthClient } from "better-auth/react";
|
||||
|
||||
export const authClient = createAuthClient();
|
||||
export const authClient = createAuthClient({
|
||||
plugins: [inferAdditionalFields<typeof auth>()],
|
||||
});
|
||||
@ -1,12 +1,53 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||
import { nextCookies } from "better-auth/next-js";
|
||||
import { admin } from "better-auth/plugins";
|
||||
import { sendEmail } from "./email";
|
||||
import { prisma } from "./prisma";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: prismaAdapter(prisma, {
|
||||
provider: "postgresql",
|
||||
}),
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
user: {
|
||||
additionalFields: {
|
||||
role: {
|
||||
type: ["user", "admin"],
|
||||
required: false,
|
||||
defaultValue: "user",
|
||||
input: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
emailVerification: {
|
||||
sendOnSignUp: true,
|
||||
sendOnSignIn: true,
|
||||
autoSignInAfterVerification: true,
|
||||
sendVerificationEmail: async ({ user, url }) => {
|
||||
await sendEmail({
|
||||
to: user.email,
|
||||
subject: "Verify your email",
|
||||
text: `Please verify your email by opening this link:\n\n${url}\n`,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
requireEmailVerification: true,
|
||||
sendResetPassword: async ({ user, url }) => {
|
||||
await sendEmail({
|
||||
to: user.email,
|
||||
subject: "Reset your password",
|
||||
text: `Reset your password using this link:\n\n${url}\n`,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
admin(),
|
||||
nextCookies(),
|
||||
],
|
||||
});
|
||||
48
src/lib/email.ts
Normal file
48
src/lib/email.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
type SendEmailArgs = {
|
||||
to: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html?: string;
|
||||
};
|
||||
|
||||
let cached: nodemailer.Transporter | null = null;
|
||||
|
||||
function getTransporter() {
|
||||
if (cached) return cached;
|
||||
|
||||
const host = process.env.SMTP_HOST;
|
||||
const port = Number(process.env.SMTP_PORT ?? "587");
|
||||
const secure = String(process.env.SMTP_SECURE ?? "false") === "true";
|
||||
const user = process.env.SMTP_USER;
|
||||
const pass = process.env.SMTP_PASS;
|
||||
|
||||
if (!host || !user || !pass) {
|
||||
throw new Error("SMTP env vars missing (SMTP_HOST/SMTP_USER/SMTP_PASS).");
|
||||
}
|
||||
|
||||
cached = nodemailer.createTransport({
|
||||
host,
|
||||
port,
|
||||
secure, // false for STARTTLS (587), true for 465
|
||||
auth: { user, pass },
|
||||
});
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
export async function sendEmail(args: SendEmailArgs) {
|
||||
const from = process.env.SMTP_FROM || process.env.SMTP_USER;
|
||||
if (!from) throw new Error("SMTP_FROM (or SMTP_USER) must be set.");
|
||||
|
||||
const transporter = getTransporter();
|
||||
|
||||
await transporter.sendMail({
|
||||
from,
|
||||
to: args.to,
|
||||
subject: args.subject,
|
||||
text: args.text,
|
||||
html: args.html,
|
||||
});
|
||||
}
|
||||
6
src/lib/registration.ts
Normal file
6
src/lib/registration.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function isPublicRegistrationOpen() {
|
||||
const count = await prisma.user.count();
|
||||
return count === 0;
|
||||
}
|
||||
Reference in New Issue
Block a user