122 lines
3.2 KiB
TypeScript
122 lines
3.2 KiB
TypeScript
import { prisma } from '@/db';
|
|
import { User } from '@/generated/prisma/client';
|
|
import { SessionModel } from '@/generated/prisma/models';
|
|
import { DB_TABLE, LOG_ACTION } from '@/types/enum';
|
|
import {
|
|
acOrg,
|
|
adminOrg,
|
|
member,
|
|
owner,
|
|
} from '@lib/auth/organization-permissions';
|
|
import { ac, admin, user } from '@lib/auth/permissions';
|
|
import { createAuditLog, getInitialOrganization } from '@service/repository';
|
|
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 House`,
|
|
slug: `${user.name?.toLowerCase().replace(/\s+/g, '-')}-house-${Date.now()}`,
|
|
userId: user.id,
|
|
color: '#000000',
|
|
},
|
|
});
|
|
await prisma.setting.create({
|
|
data: {
|
|
key: user.id,
|
|
value: '{"language": "en"}',
|
|
description: '',
|
|
relation: 'user',
|
|
},
|
|
});
|
|
},
|
|
},
|
|
},
|
|
session: {
|
|
create: {
|
|
before: async (session) => {
|
|
const organization = await getInitialOrganization(session.userId);
|
|
return {
|
|
data: {
|
|
...session,
|
|
activeOrganizationId: organization?.id,
|
|
},
|
|
};
|
|
},
|
|
after: async (session, context) => {
|
|
if (context?.path.includes('/sign-in')) {
|
|
await createAuditLog({
|
|
action: LOG_ACTION.SIGN_IN,
|
|
tableName: DB_TABLE.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: LOG_ACTION.SIGN_OUT,
|
|
tableName: DB_TABLE.SESSION,
|
|
recordId: session.id,
|
|
oldValue: JSON.stringify(session),
|
|
newValue: '',
|
|
userId: session.userId,
|
|
});
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|