37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import { NextResponse } from "next/server"
|
|||
|
|
import { headers } from "next/headers"
|
||
|
|
import { db } from "@/lib/db"
|
||
|
|
import { consent_log } from "@/lib/db/schema"
|
||
|
|
import { getSessionUser } from "@/lib/session"
|
||
|
|
import { LEGAL } from "@/lib/legal"
|
||
|
|
|
||
|
|
// Records a cookie-consent choice from the banner. Only signed-in users are
|
||
|
|
// logged — anonymous visitors keep their choice in localStorage only, so this
|
||
|
|
// endpoint can't be used to spam the consent table.
|
||
|
|
export async function POST(request: Request) {
|
||
|
|
const user = await getSessionUser()
|
||
|
|
if (!user) return new NextResponse(null, { status: 204 })
|
||
|
|
|
||
|
|
let analytics = false
|
||
|
|
try {
|
||
|
|
const body = await request.json()
|
||
|
|
analytics = body?.analytics === true
|
||
|
|
} catch {
|
||
|
|
return NextResponse.json({ error: "Invalid body" }, { status: 400 })
|
||
|
|
}
|
||
|
|
|
||
|
|
const h = await headers()
|
||
|
|
await db.insert(consent_log).values({
|
||
|
|
user_id: user.id,
|
||
|
|
email: user.email,
|
||
|
|
kind: "cookies",
|
||
|
|
granted: analytics,
|
||
|
|
policy_version: LEGAL.lastUpdated,
|
||
|
|
source: "cookie-banner",
|
||
|
|
ip_address: h.get("x-forwarded-for")?.split(",")[0]?.trim() ?? h.get("x-real-ip"),
|
||
|
|
user_agent: h.get("user-agent"),
|
||
|
|
})
|
||
|
|
|
||
|
|
return NextResponse.json({ ok: true })
|
||
|
|
}
|