Les comptes déjà créés ne sont pas inscrits. Le choix est facultatif à l’inscription et dans les paramètres. Un lien public demande confirmation avant d’arrêter les actualités, sans toucher aux messages de compte.
54 lines
1.9 KiB
TypeScript
54 lines
1.9 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { unsubscribeByUserId } from '@/lib/marketing/preference'
|
|
import { publicAppOrigin, verifyUnsubscribeToken } from '@/lib/marketing/unsubscribe-token'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
function tokenFromRequest(request: NextRequest, bodyToken?: string | null): string | null {
|
|
return (
|
|
request.nextUrl.searchParams.get('token') ||
|
|
bodyToken ||
|
|
null
|
|
)
|
|
}
|
|
|
|
async function applyUnsubscribe(request: NextRequest, token: string | null) {
|
|
const payload = token ? verifyUnsubscribeToken(token) : null
|
|
if (!payload) {
|
|
return NextResponse.json({ ok: false }, { status: 400 })
|
|
}
|
|
const forwarded = request.headers.get('x-forwarded-for')
|
|
const ip = forwarded?.split(',')[0]?.trim() || request.headers.get('x-real-ip')
|
|
await unsubscribeByUserId({
|
|
userId: payload.userId,
|
|
source: 'unsubscribe-one-click',
|
|
meta: { ip, userAgent: request.headers.get('user-agent') },
|
|
})
|
|
return new NextResponse('OK', { status: 200 })
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
let bodyToken: string | null = null
|
|
const contentType = request.headers.get('content-type') || ''
|
|
try {
|
|
if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
const form = await request.formData()
|
|
bodyToken = String(form.get('token') || '')
|
|
} else if (contentType.includes('application/json')) {
|
|
const json = await request.json().catch(() => null)
|
|
bodyToken = json?.token ? String(json.token) : null
|
|
}
|
|
} catch {
|
|
bodyToken = null
|
|
}
|
|
return applyUnsubscribe(request, tokenFromRequest(request, bodyToken))
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const token = request.nextUrl.searchParams.get('token') || ''
|
|
const origin = publicAppOrigin() || request.nextUrl.origin
|
|
const url = new URL('/unsubscribe', origin)
|
|
if (token) url.searchParams.set('token', token)
|
|
return NextResponse.redirect(url, 303)
|
|
}
|