Initial commit

This commit is contained in:
Developer
2026-02-06 21:44:04 -06:00
commit f85e93c7a6
151 changed files with 22916 additions and 0 deletions

128
lib/auth.ts Normal file
View File

@@ -0,0 +1,128 @@
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { getPrisma } from "./db";
import { loadSystemConfig } from "./system-config";
import { setCached, getCached, deleteCached, cacheKeys } from "./redis";
let authInstance: ReturnType<typeof betterAuth> | null = null;
export async function getAuth() {
if (authInstance) {
return authInstance;
}
const prisma = await getPrisma();
const cfg = await loadSystemConfig();
if (!prisma) {
throw new Error("Database not configured");
}
const isDevelopment = process.env.NODE_ENV === "development";
const baseURL = process.env.APP_BASE_URL ||
(isDevelopment ? "http://localhost:3001" : "https://estate-platform.com");
authInstance = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
secret: cfg.auth?.jwtSecret || process.env.BETTER_AUTH_SECRET || "default-secret-change-me",
baseURL: baseURL,
trustHost: true,
// Disable origin validation in development
...(isDevelopment && {
skipOriginValidation: true,
}),
csrfProtection: false, // Disable CSRF protection completely
advanced: {
useSecureCookies: !isDevelopment, // Allow non-secure cookies in development
disableMultipleTabsWarning: isDevelopment,
sessionTimeout: 86400 * 7, // 7 days
defaultCookieMaxAge: 86400 * 7, // 7 days
},
emailAndPassword: {
enabled: true,
autoSignUpDisabled: false,
minPasswordLength: 8,
maxPasswordLength: 20,
requireEmailVerification: cfg.email?.enabled || false,
},
socialProviders: {
google: {
clientId: cfg.oauth?.google?.clientId || process.env.GOOGLE_CLIENT_ID || "",
clientSecret: cfg.oauth?.google?.clientSecret || process.env.GOOGLE_CLIENT_SECRET || "",
},
github: {
clientId: cfg.oauth?.github?.clientId || process.env.GITHUB_CLIENT_ID || "",
clientSecret: cfg.oauth?.github?.clientSecret || process.env.GITHUB_CLIENT_SECRET || "",
},
facebook: {
clientId: cfg.oauth?.facebook?.clientId || process.env.FACEBOOK_CLIENT_ID || "",
clientSecret: cfg.oauth?.facebook?.clientSecret || process.env.FACEBOOK_CLIENT_SECRET || "",
},
discord: {
clientId: cfg.oauth?.discord?.clientId || process.env.DISCORD_CLIENT_ID || "",
clientSecret: cfg.oauth?.discord?.clientSecret || process.env.DISCORD_CLIENT_SECRET || "",
},
},
});
return authInstance;
}
// Session caching helper
export async function cacheSession(sessionId: string, sessionData: any) {
try {
await setCached(cacheKeys.session(sessionId), sessionData, 604800); // 7 days
} catch (error) {
console.error("[Auth] Error caching session:", error);
}
}
export async function getCachedSession(sessionId: string) {
try {
return await getCached(cacheKeys.session(sessionId));
} catch (error) {
console.error("[Auth] Error getting cached session:", error);
return null;
}
}
export async function invalidateSessionCache(sessionId: string) {
try {
await deleteCached(cacheKeys.session(sessionId));
} catch (error) {
console.error("[Auth] Error invalidating session cache:", error);
}
}
// User caching helper
export async function cacheUser(userId: string, userData: any) {
try {
await setCached(cacheKeys.user(userId), userData, 3600); // 1 hour
} catch (error) {
console.error("[Auth] Error caching user:", error);
}
}
export async function getCachedUser(userId: string) {
try {
return await getCached(cacheKeys.user(userId));
} catch (error) {
console.error("[Auth] Error getting cached user:", error);
return null;
}
}
export async function invalidateUserCache(userId: string) {
try {
await deleteCached(cacheKeys.user(userId));
} catch (error) {
console.error("[Auth] Error invalidating user cache:", error);
}
}
// Re-export BetterAuth session types
export type { Session } from "better-auth";
export type { User } from "better-auth";