import { betterAuth } from "better-auth"; import { nextCookies } from "better-auth/next-js"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { admin as adminPlugin, organization, phoneNumber, magicLink, openAPI, customSession, jwt, username, } from "better-auth/plugins"; import { ac, owner, admin, moderator, member } from "@/lib/auth/permissions"; import { db } from "@/drizzle/db"; import * as schema from "@/drizzle/schema"; import { client } from "./client"; import { sendSignInEmail } from "@/utils/actions/users/sendSignInEmail"; import { sendSignInOTP } from "@/utils/actions/users/sendSignInOTP"; import { getOrganizationRole } from "./getOrganizationRole"; import { getActiveOrganization } from "./getActiveOrganization"; export const auth = betterAuth({ trustedOrigins: ["https://www.dotsvote.com", "https://dotsvote.com"], session: { cookieCache: { enabled: false, // maxAge: 5 * 60, // Cache duration in seconds }, }, emailAndPassword: { enabled: true, requireEmailVerification: true, password: { hash: async (password: string) => { const bcrypt = await import("bcryptjs"); const salt = await bcrypt.genSalt(10); return bcrypt.hash(password, salt); }, verify: async (data: { hash: string; password: string }) => { const bcrypt = await import("bcryptjs"); return bcrypt.compare(data.password, data.hash); }, }, }, emailVerification: { autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url, token }, request) => { await sendSignInEmail({ email: user.email, magicLink: url, }); }, }, database: drizzleAdapter(db, { provider: "pg", schema: { ...schema, }, usePlural: true, }), databaseHooks: { session: { create: { before: async (session) => { const organization = await getActiveOrganization(session.userId); return { data: { ...session, activeOrganizationId: organization?.id, }, }; }, }, }, }, advanced: { generateId: false, }, plugins: [ // customSession(async ({ user, session}) => { // const role = "test" // return { // role, // } // }), jwt({ jwks: { keyPairConfig: { alg: "EdDSA", crv: "Ed25519", }, }, jwt: { definePayload: async (user) => { const [member] = await getOrganizationRole( user.user.id, user.session.activeOrganizationId ); return { id: user.user.id, email: user.user.email, role: member?.role || "member", device: user.session.device, requestId: crypto.randomUUID(), }; }, }, }), nextCookies(), openAPI(), magicLink({ sendMagicLink: async ({ email, token, url }, request) => { await sendSignInEmail({ email, magicLink: url, }); }, disableSignUp: true, expiresIn: 600, // 10 minutes }), phoneNumber({ sendOTP: async ({ phoneNumber, code }, request) => { await sendSignInOTP({ phoneNumber, code, }); }, }), adminPlugin({ defaultRole: "member", }), organization({ ac: ac, roles: { owner, admin, moderator, member, }, creatorRole: "admin", organizationLimit: async (user) => { // const subscription = await getSubscription(user.id); // return subscription.plan === "pro"; return false; }, allowUserToCreateOrganization: async (user) => { // const subscription = await getSubscription(user.id); // return subscription.plan === "pro"; return true; }, membershipLimit: 100000, async sendInvitationEmail(data) { // const inviteLink = `https://example.com/accept-invitation/${data.id}`; // sendOrganizationInvitation({ // email: data.email, // invitedByUsername: data.inviter.user.name, // invitedByEmail: data.inviter.user.email, // teamName: data.organization.name, // inviteLink, // }); // const invite = await client.organization.inviteMember({ // email: data.email, // role: data.role, // }); // console.log(invite); // await client.organization.acceptInvitation({ // invitationId: invite.id, // }); // console.log(data); }, }), username(), ], // make sure this is the last plugin in the array });