Files
buzz-sheet/app/api/notifications/route.ts
T
gunshiz 9bc710c94b
CI / Verify (push) Successful in 1m50s
CI / Build immutable images and deploy (push) Successful in 2m59s
feat : ask for noti
2026-10-08 02:23:59 +07:00

28 lines
1.5 KiB
TypeScript

import * as z from 'zod';
import { requireCommissionUser } from '@/lib/commission/server';
import { listNotifications, readNotifications } from '@/lib/notifications/repository';
import { errorResponse, HttpError, readJson, requireSameOrigin } from '@/lib/security/http';
import { limitRequest } from '@/lib/security/rate-limit';
export async function GET(request: Request) {
try {
const user = await requireCommissionUser();
const raw = new URL(request.url).searchParams.get('before');
const parts = raw?.split('|');
const parsed = parts ? z.object({ time: z.iso.datetime(), id: z.uuid() }).safeParse({ time: parts[0], id: parts[1] }) : undefined;
if (raw && (!parsed?.success || parts?.length !== 2)) throw new HttpError(400, 'invalid-cursor');
const before = parsed?.success ? parsed.data : undefined;
return Response.json(await listNotifications(user, before), { headers: { 'Cache-Control': 'private, no-store' } });
} catch (cause) { return errorResponse(cause); }
}
export async function POST(request: Request) {
try {
requireSameOrigin(request);
const user = await requireCommissionUser();
await limitRequest('notification-read', user.id, 120);
const parsed = z.object({ id: z.uuid().optional() }).safeParse(await readJson(request, 1024));
if (!parsed.success) throw new HttpError(400, 'invalid-notification');
await readNotifications(user.id, parsed.data.id);
return new Response(null, { status: 204 });
} catch (cause) { return errorResponse(cause); }
}