92 lines
2.3 KiB
TypeScript
92 lines
2.3 KiB
TypeScript
import { cookies, headers } from "next/headers"
|
|
import { redirect } from "next/navigation"
|
|
|
|
import { getCookieCache } from "better-auth/cookies"
|
|
|
|
import { env } from "@/lib/env"
|
|
import { isAdmin, isStaff } from "@/lib/authz"
|
|
|
|
type ServerSession = Awaited<ReturnType<typeof getCookieCache>>
|
|
|
|
function serializeCookies() {
|
|
const store = cookies()
|
|
return store.getAll().map((cookie) => `${cookie.name}=${cookie.value}`).join("; ")
|
|
}
|
|
|
|
function buildRequest() {
|
|
const cookieHeader = serializeCookies()
|
|
const headerList = headers()
|
|
const userAgent = headerList.get("user-agent") ?? ""
|
|
const ip =
|
|
headerList.get("x-forwarded-for") ||
|
|
headerList.get("x-real-ip") ||
|
|
headerList.get("cf-connecting-ip") ||
|
|
headerList.get("x-client-ip") ||
|
|
undefined
|
|
|
|
return new Request(env.BETTER_AUTH_URL ?? "http://localhost:3000", {
|
|
headers: {
|
|
cookie: cookieHeader,
|
|
"user-agent": userAgent,
|
|
...(ip ? { "x-forwarded-for": ip } : {}),
|
|
},
|
|
})
|
|
}
|
|
|
|
export async function getServerSession(): Promise<ServerSession | null> {
|
|
try {
|
|
const request = buildRequest()
|
|
const session = await getCookieCache(request)
|
|
return session ?? null
|
|
} catch (error) {
|
|
console.error("Failed to read Better Auth session", error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
export async function assertAuthenticatedSession() {
|
|
const session = await getServerSession()
|
|
return session?.user ? session : null
|
|
}
|
|
|
|
export async function requireAuthenticatedSession() {
|
|
const session = await assertAuthenticatedSession()
|
|
if (!session) {
|
|
redirect("/login")
|
|
}
|
|
return session
|
|
}
|
|
|
|
export async function assertStaffSession() {
|
|
const session = await assertAuthenticatedSession()
|
|
if (!session) return null
|
|
if (!isStaff(session.user.role)) {
|
|
return null
|
|
}
|
|
return session
|
|
}
|
|
|
|
export async function requireStaffSession() {
|
|
const session = await assertStaffSession()
|
|
if (!session) {
|
|
redirect("/portal")
|
|
}
|
|
return session
|
|
}
|
|
|
|
export async function assertAdminSession() {
|
|
const session = await assertAuthenticatedSession()
|
|
if (!session) return null
|
|
if (!isAdmin(session.user.role)) {
|
|
return null
|
|
}
|
|
return session
|
|
}
|
|
|
|
export async function requireAdminSession() {
|
|
const session = await assertAdminSession()
|
|
if (!session) {
|
|
redirect("/dashboard")
|
|
}
|
|
return session
|
|
}
|