Files
Zero/lib/auth.ts
2025-02-13 11:22:48 -05:00

103 lines
3.2 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { betterAuth, BetterAuthOptions } from "better-auth";
import { connection, user as _user } from "@/db/schema";
import { customSession } from "better-auth/plugins";
import { eq } from "drizzle-orm";
import { Resend } from "resend";
import { env } from "./env";
import { db } from "@/db";
// If there is no resend key, it might be a local dev environment
// In that case, we don't want to send emails and just log them
const resend = env.RESEND_API_KEY
? new Resend(env.RESEND_API_KEY)
: { emails: { send: async (...args: any[]) => console.log(args) } };
const options = {
database: drizzleAdapter(db, {
provider: "pg",
}),
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24, // 1 day (every 1 day the session expiration is updated)
},
socialProviders: {
google: {
// Remove this before going to prod, it's to force to get `refresh_token` from google, some users don't have it yet.
prompt: "consent",
accessType: "offline",
scope: ["https://mail.google.com/"],
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
},
},
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) => {
await resend.emails.send({
from: "Mail0 <onboarding@mail0.io>",
to: user.email,
subject: "Reset your password",
html: `
<h2>Reset Your Password</h2>
<p>Click the link below to reset your password:</p>
<a href="${url}">${url}</a>
<p>If you didn't request this, you can safely ignore this email.</p>
`,
});
},
},
emailVerification: {
sendOnSignUp: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, token }) => {
const verificationUrl = `${env.NEXT_PUBLIC_APP_URL}/api/auth/verify-email?token=${token}&callbackURL=/connect-emails`;
await resend.emails.send({
from: "Mail0 <onboarding@mail0.io>",
to: user.email,
subject: "Verify your Mail0 account",
html: `
<h2>Verify Your Mail0 Account</h2>
<p>Click the link below to verify your email:</p>
<a href="${verificationUrl}">${verificationUrl}</a>
`,
});
},
},
plugins: [
customSession(async ({ user, session }) => {
const [foundUser] = await db
.select({
activeConnectionId: _user.defaultConnectionId,
})
.from(_user)
.where(eq(_user.id, user.id))
.limit(1);
if (!foundUser.activeConnectionId) {
const [defaultConnection] = await db
.select()
.from(connection)
.where(eq(connection.userId, user.id))
.limit(1);
return {
connectionId: defaultConnection ? defaultConnection.id : null,
user,
session,
};
}
return {
connectionId: foundUser.activeConnectionId,
user,
session,
};
}),
],
} satisfies BetterAuthOptions;
export const auth = betterAuth({
...options,
});