import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { admin, apiKey, createAuthMiddleware, customSession, jwt, lastLoginMethod, username, } from "better-auth/plugins"; import { eq } from "drizzle-orm"; import { db } from "../db/db.controller.js"; import * as rawSchema from "../db/schema/auth.schema.js"; import { allowedOrigins } from "./cors.utils.js"; import { sendEmail } from "./sendEmail.utils.js"; export const schema = { user: rawSchema.user, session: rawSchema.session, account: rawSchema.account, verification: rawSchema.verification, jwks: rawSchema.jwks, apiKey: rawSchema.apikey, // 🔑 rename to apiKey }; export const auth = betterAuth({ appName: "lst", baseURL: process.env.URL, database: drizzleAdapter(db, { provider: "pg", schema, }), user: { additionalFields: { role: { type: "string", required: false, input: false, }, lastLogin: { type: "date", required: true, input: false, }, }, }, plugins: [ jwt({ jwt: { expirationTime: "1h" } }), apiKey(), admin(), lastLoginMethod(), username({ minUsernameLength: 5, usernameValidator: (username) => { if (username === "admin") { return false; } return true; }, }), customSession(async ({ user, session }) => { const roles = await db .select({ roles: rawSchema.user.role }) .from(rawSchema.user) .where(eq(rawSchema.user.id, session.id)); return { roles, user: { ...user, //newField: "newField", }, session, }; }), ], trustedOrigins: allowedOrigins, emailAndPassword: { enabled: true, minPasswordLength: 8, // optional config resetPasswordTokenExpirySeconds: process.env.RESET_EXPIRY_SECONDS, // time in seconds sendResetPassword: async ({ user, token }) => { const frontendUrl = `${process.env.BETTER_AUTH_URL}/lst/app/user/resetpassword?token=${token}`; const expiryMinutes = Math.floor( parseInt(process.env.RESET_EXPIRY_SECONDS ?? "3600", 10) / 60, ); const expiryText = expiryMinutes >= 60 ? `${expiryMinutes / 60} hour${expiryMinutes === 60 ? "" : "s"}` : `${expiryMinutes} minutes`; const emailData = { email: user.email, subject: "LST- Forgot password request", template: "forgotPassword", context: { username: user.name, email: user.email, url: frontendUrl, expiry: expiryText, }, }; await sendEmail(emailData); }, // onPasswordReset: async ({ user }, request) => { // // your logic here // console.log(`Password for user ${user.email} has been reset.`); // }, }, session: { expiresIn: 60 * 60, updateAge: 60 * 5, freshAge: 60 * 2, cookieCache: { enabled: true, maxAge: 5 * 60, }, }, cookie: { path: "/lst/app", sameSite: "lax", secure: false, httpOnly: true, }, hooks: { after: createAuthMiddleware(async (ctx) => { if (ctx.path.startsWith("/login")) { const newSession = ctx.context.newSession; if (newSession) { // something here later } } }), }, events: { // async onSignInSuccess({ user }: { user: User }) { // await db // .update(rawSchema.user) // .set({ lastLogin: new Date() }) // .where(eq(schema.user.id, user.id)); // }, }, });