wulf-pulse/lib/auth.ts
lorentz ff9e34cafe feat: add Autotask tags sync (tag groups, tags, ticket tag associations)
- Migration 057: autotask_tag_groups, autotask_tags, and junction tables
  (ticket_tags, company_tags, configuration_item_tags, contact_tags)
- Add TAG_GROUPS and TAGS to EntityType enum and dependency map
- Add mapTagGroup() and mapTag() entity mapper functions
- Add syncTagGroups(), syncTags(), syncTicketTagAssociations() methods
- Wire TicketTagAssociations bulk sync into full/incremental sync flow
- Add 'exist' operator to QueryFilter type
- No FK on ticket_id (tagged tickets may be outside 2yr sync window)

Synced: 26 tag groups, 7299 tags, 10141 ticket-tag associations
2026-03-20 09:22:40 -04:00

100 lines
2.3 KiB
TypeScript

import { betterAuth } from "better-auth";
import { magicLink, twoFactor, admin } from "better-auth/plugins";
import { nextCookies } from "better-auth/next-js";
import { Pool } from "pg";
import { sendMagicLinkEmail } from "./services/email";
import { ac, adminRole, userRole, superAdminRole } from "./permissions";
// Create a PostgreSQL pool for Better Auth
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
export const auth = betterAuth({
database: pool,
appName: "Pulse",
baseURL: process.env.BETTER_AUTH_URL,
secret: process.env.BETTER_AUTH_SECRET,
trustedOrigins: [
"http://localhost:3100",
"https://pulse.wulfconsulting.cloud"
],
// Email & Password disabled - using magic link and Microsoft OAuth only
emailAndPassword: {
enabled: false,
},
// Session configuration
session: {
expiresIn: parseInt(process.env.SESSION_TIMEOUT_SECONDS || "86400"),
updateAge: 60 * 60, // Update session every hour
cookieCache: {
enabled: true,
maxAge: 5 * 60, // 5 minutes
},
},
// Social providers
socialProviders: {
microsoft: {
clientId: process.env.MICROSOFT_CLIENT_ID || "",
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
tenantId: process.env.MICROSOFT_TENANT_ID || "common",
},
},
// Plugins
plugins: [
// Magic link authentication
magicLink({
sendMagicLink: async ({ email, url, token }) => {
await sendMagicLinkEmail({ email, url, token });
},
expiresIn: 300, // 5 minutes
}),
// Two-factor authentication
twoFactor({
issuer: "Pulse",
}),
// Admin plugin with RBAC
admin({
ac,
roles: {
"super-admin": superAdminRole,
admin: adminRole,
user: userRole,
},
}),
// Next.js cookie handling - must be last
nextCookies(),
],
// Allow Microsoft OAuth to link to existing accounts created by admins
account: {
accountLinking: {
enabled: true,
trustedProviders: ["microsoft"],
},
},
// User configuration
user: {
additionalFields: {
role: {
type: "string",
defaultValue: "user",
},
requires_setup: {
type: "boolean",
defaultValue: false,
},
},
},
});
export type Session = typeof auth.$Infer.Session;
export type User = typeof auth.$Infer.Session.user;