import { prisma } from '@/db'; import { User } from '@/generated/prisma/client'; import { SessionModel } from '@/generated/prisma/models'; import { acOrg, adminOrg, member, owner, } from '@/lib/auth/organization-permissions'; import { ac, admin, user } from '@/lib/auth/permissions'; import { createAuditLog } from '@/service/audit.api'; import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import { admin as adminPlugin, organization } from 'better-auth/plugins'; export interface Session { session: SessionModel | null | undefined; user?: User; } export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', }), experimental: { joins: true }, emailAndPassword: { enabled: true, requireEmailVerification: false, }, trustedOrigins: ['http://localhost:3001'], advanced: { database: { generateId: false, }, }, plugins: [ adminPlugin({ ac, roles: { admin, user }, defaultRole: 'user', }), organization({ ac: acOrg, roles: { owner, admin: adminOrg, member }, schema: { organization: { additionalFields: { color: { type: 'string', defaultValue: '#000000', }, }, }, }, }), ], databaseHooks: { user: { create: { after: async (user) => { await auth.api.createOrganization({ body: { name: `${user.name || 'User'}'s Organization`, slug: `${user.name?.toLowerCase().replace(/\s+/g, '-')}-${Date.now()}`, userId: user.id, color: '#000000', }, }); }, }, update: { before: async (user, ctx) => { if (ctx?.context.session && ctx?.path === '/update-user') { const newUser = JSON.parse(JSON.stringify(user)); const keys = Object.keys(newUser); const oldUser = Object.fromEntries( Object.entries(ctx?.context.session?.user).filter(([key]) => keys.includes(key), ), ); await createAuditLog({ action: 'update', tableName: 'user', recordId: ctx?.context.session?.user.id, oldValue: JSON.stringify(oldUser), newValue: JSON.stringify(newUser), userId: ctx?.context.session?.user.id, }); } }, }, }, account: { update: { after: async (account, context) => { if (context?.path === '/change-password') { await createAuditLog({ action: 'change_password', tableName: 'account', recordId: account.id, oldValue: 'Change Password', newValue: 'Change Password', userId: account.userId, }); } }, }, }, session: { create: { after: async (session, context) => { if (context?.path.includes('/sign-in')) { await createAuditLog({ action: 'sign_in', tableName: 'session', recordId: session.id, oldValue: '', newValue: JSON.stringify(session), userId: session.userId, }); } }, }, delete: { after: async (session, context) => { if (context?.path === '/sign-out') { await createAuditLog({ action: 'sign_out', tableName: 'session', recordId: session.id, oldValue: JSON.stringify(session), newValue: '', userId: session.userId, }); } }, }, }, }, });