Comprehensive admin + user dashboards (production-ready)

This commit is contained in:
Leon Serfaty
2026-06-07 17:54:30 -04:00
parent 155507f21a
commit f033f00379
122 changed files with 7878 additions and 805 deletions
+19 -3
View File
@@ -9,15 +9,28 @@ const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";
const googleConfigured = !!(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET);
// Fail fast in production if the signing secret is missing — sessions/cookies are
// only secure when BETTER_AUTH_SECRET is set. Stay frictionless in dev/test.
if (!process.env.BETTER_AUTH_SECRET && process.env.NODE_ENV === "production") {
throw new Error("BETTER_AUTH_SECRET must be set in production.");
}
export const auth = betterAuth({
appName: "PodcastYes",
secret: process.env.BETTER_AUTH_SECRET,
baseURL: process.env.BETTER_AUTH_URL ?? appUrl,
database: prismaAdapter(prisma, { provider: "postgresql" }),
// Built-in brute-force protection for auth endpoints (login, password reset, etc).
// 30 requests per 60s window per IP.
rateLimit: { enabled: true, window: 60, max: 30 },
emailAndPassword: {
enabled: true,
// Flip on once email delivery is verified in prod.
// SECURITY GATE (currently OPEN): unverified emails can sign in. Flip this to
// `true` once email delivery is confirmed working in prod. Left `false` for now
// so existing dev accounts aren't locked out. Verification emails ARE sent on
// signup (see emailVerification.sendOnSignUp below), so users can verify already.
requireEmailVerification: false,
minPasswordLength: 8,
async sendResetPassword({ user, url }) {
@@ -35,7 +48,7 @@ export const auth = betterAuth({
},
emailVerification: {
sendOnSignUp: false,
sendOnSignUp: true,
async sendVerificationEmail({ user, url }) {
await sendEmail({
to: user.email,
@@ -62,7 +75,10 @@ export const auth = betterAuth({
session: {
expiresIn: 60 * 60 * 24 * 30, // 30 days
updateAge: 60 * 60 * 24, // refresh daily
cookieCache: { enabled: true, maxAge: 5 * 60 },
// Cache the session in a signed cookie to avoid a DB hit on every request.
// Tradeoff: a banned/demoted user keeps cached access until the cache expires,
// so we keep the window short (60s). Shorter = faster revocation but more DB hits.
cookieCache: { enabled: true, maxAge: 60 },
},
account: {