mirror of
https://github.com/hanzo-apps/dataroom.git
synced 2026-10-30 14:47:36 +00:00
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import { NextApiRequest, NextApiResponse } from "next";
|
|
|
|
import { getDataroomSessionByLinkIdInPagesRouter } from "@/lib/auth/dataroom-auth";
|
|
import prisma from "@/lib/prisma";
|
|
import { ratelimit } from "@/lib/redis";
|
|
import { getIpAddress } from "@/lib/utils/ip";
|
|
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse,
|
|
) {
|
|
if (req.method !== "POST") {
|
|
res.setHeader("Allow", ["POST"]);
|
|
return res.status(405).end(`Method ${req.method} Not Allowed`);
|
|
}
|
|
|
|
// 1. IP-based rate limiting (same pattern as OTP endpoints in verify.ts)
|
|
const ipAddress = getIpAddress(req.headers) ?? "unknown";
|
|
const { success } = await ratelimit(10, "1 m").limit(
|
|
`download-by-email-ip:${ipAddress}`,
|
|
);
|
|
if (!success) {
|
|
return res
|
|
.status(429)
|
|
.json({ error: "Too many requests. Try again later." });
|
|
}
|
|
|
|
const { linkId, email } = req.body as { linkId?: string; email?: string };
|
|
if (!linkId || !email) {
|
|
return res.status(400).json({ error: "linkId and email are required" });
|
|
}
|
|
|
|
// 2. Require a valid dataroom session
|
|
const session = await getDataroomSessionByLinkIdInPagesRouter(req, linkId);
|
|
if (!session) {
|
|
return res.status(401).json({ error: "Session required" });
|
|
}
|
|
|
|
// 3. Prevent email enumeration — always return 200 with uniform body
|
|
const view = await prisma.view.findFirst({
|
|
where: {
|
|
linkId,
|
|
viewType: "DATAROOM_VIEW",
|
|
viewerEmail: { equals: email, mode: "insensitive" },
|
|
},
|
|
select: { id: true },
|
|
orderBy: { viewedAt: "desc" },
|
|
});
|
|
|
|
return res.status(200).json({ viewId: view?.id ?? null });
|
|
}
|