68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import { z } from "zod";
|
|
import { notifications } from "@/features/notifications/server";
|
|
import { apiError, apiJson, apiUnavailable } from "@/lib/api";
|
|
import { auth } from "@/lib/auth";
|
|
import { sessionUserId } from "@/lib/auth/session-user";
|
|
import { rateLimit } from "@/lib/rate-limit";
|
|
|
|
const mutation = z.discriminatedUnion("action", [
|
|
z
|
|
.object({ action: z.literal("read"), key: z.string().min(1).max(128) })
|
|
.strict(),
|
|
z
|
|
.object({
|
|
action: z.literal("preferences"),
|
|
preferences: z
|
|
.object({
|
|
support: z.boolean(),
|
|
friends: z.boolean(),
|
|
events: z.boolean(),
|
|
})
|
|
.strict(),
|
|
})
|
|
.strict(),
|
|
]);
|
|
export async function GET(req: Request) {
|
|
const uid = sessionUserId((await auth())?.user?.id);
|
|
if (!uid) return apiError("Unauthorized", 401);
|
|
try {
|
|
return apiJson(
|
|
await notifications.feed(
|
|
uid,
|
|
Number(new URL(req.url).searchParams.get("page") ?? 1),
|
|
),
|
|
);
|
|
} catch {
|
|
return apiUnavailable();
|
|
}
|
|
}
|
|
export async function POST(req: Request) {
|
|
const uid = sessionUserId((await auth())?.user?.id);
|
|
if (!uid) return apiError("Unauthorized", 401);
|
|
if (req.headers.get("origin") !== new URL(req.url).origin)
|
|
return apiError("Invalid origin", 403);
|
|
if (!req.headers.get("content-type")?.startsWith("application/json"))
|
|
return apiError("Invalid content type", 415);
|
|
if (!(await rateLimit(`notifications:${uid}`, 60, 60_000)).ok)
|
|
return apiError("Too many requests", 429);
|
|
const body = await req.text();
|
|
if (body.length > 2048) return apiError("Request too large", 413);
|
|
let value: unknown;
|
|
try {
|
|
value = JSON.parse(body);
|
|
} catch {
|
|
return apiError("Invalid request");
|
|
}
|
|
const parsed = mutation.safeParse(value);
|
|
if (!parsed.success) return apiError("Invalid request");
|
|
try {
|
|
if (parsed.data.action === "read") {
|
|
if (!(await notifications.mark(uid, parsed.data.key)))
|
|
return apiError("Notification not found", 404);
|
|
} else await notifications.preferences(uid, parsed.data.preferences);
|
|
return apiJson({ ok: true });
|
|
} catch {
|
|
return apiUnavailable();
|
|
}
|
|
}
|