Initial import: property management SaaS + security hardening + admin dashboard
Property Management Network — Next.js 16 (App Router), Better Auth, Drizzle ORM over PostgreSQL, Stripe, OpenAI, Resend. Includes: - Security hardening: access-control/IDOR fixes, TLS-by-default DB layer, constant-time cron auth, strict security headers, atomic AI quota gating, HTML/email output encoding, demo-backdoor disabled in production. - Superadmin dashboard at /admin (overview/MRR, server-paginated users with ban/impersonate/plan/delete, billing, platform activity + admin audit log, AI usage, system health) via the Better Auth admin plugin. - Seed/migration utility scripts under scripts/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { NextResponse, type NextRequest } from "next/server"
|
||||
import { getSessionCookie } from "better-auth/cookies"
|
||||
|
||||
const PROTECTED_PATHS = [
|
||||
"/admin",
|
||||
"/dashboard",
|
||||
"/properties",
|
||||
"/tenants",
|
||||
"/rent",
|
||||
"/maintenance",
|
||||
"/leases",
|
||||
"/expenses",
|
||||
"/settings",
|
||||
"/onboarding",
|
||||
"/calendar",
|
||||
"/inspections",
|
||||
"/vendors",
|
||||
"/reports",
|
||||
"/activity",
|
||||
"/ai",
|
||||
"/ai-dashboard",
|
||||
"/predictions",
|
||||
"/recommendations",
|
||||
"/impact",
|
||||
"/follow-ups",
|
||||
]
|
||||
|
||||
const AUTH_PATHS = ["/login", "/signup", "/forgot-password"]
|
||||
|
||||
export async function proxy(request: NextRequest) {
|
||||
const pathname = request.nextUrl.pathname
|
||||
|
||||
// Optimistic check based on the presence of the session cookie. Real
|
||||
// enforcement happens in routes / server components via getSessionUser().
|
||||
const sessionCookie = getSessionCookie(request)
|
||||
|
||||
const isProtected = PROTECTED_PATHS.some((p) => pathname.startsWith(p))
|
||||
if (isProtected && !sessionCookie) {
|
||||
const url = request.nextUrl.clone()
|
||||
url.pathname = "/login"
|
||||
return NextResponse.redirect(url)
|
||||
}
|
||||
|
||||
const isAuthPage = AUTH_PATHS.some((p) => pathname.startsWith(p))
|
||||
if (isAuthPage && sessionCookie) {
|
||||
const url = request.nextUrl.clone()
|
||||
url.pathname = "/dashboard"
|
||||
return NextResponse.redirect(url)
|
||||
}
|
||||
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user