in src/app/api/v1/hibp/notify/route.ts [29:90]
export async function POST(req: NextRequest) {
let pubsub: PubSub;
let json: PostHibpNotificationRequestBody;
try {
if (!projectId) {
throw new Error("GCP_PUBSUB_PROJECT_ID env var not set");
}
if (!topicName) {
throw new Error("GCP_PUBSUB_TOPIC_NAME env var not set");
}
const headerToken = bearerToken(req);
if (headerToken !== process.env.HIBP_NOTIFY_TOKEN) {
logger.error(`Received invalid header token: [${headerToken}]`);
return NextResponse.json({ success: false }, { status: 401 });
}
json = (await req.json()) as PostHibpNotificationRequestBody;
if (!(json.breachName && json.hashPrefix && json.hashSuffixes)) {
logger.error(
"HIBP breach notification: requires breachName, hashPrefix, and hashSuffixes.",
);
return NextResponse.json({ success: false }, { status: 400 });
}
} catch (ex) {
logger.error("error_processing_breach_alert_request:", {
exception: ex as string,
});
return NextResponse.json({ success: false }, { status: 500 });
}
try {
pubsub = new PubSub({ projectId });
} catch (ex) {
logger.error("error_connecting_to_pubsub:", { exception: ex as string });
captureMessage(`error_connecting_to_pubsub: ${ex as string}`);
return NextResponse.json({ success: false }, { status: 429 });
}
try {
const topic = pubsub.topic(topicName);
await topic.publishMessage({ json });
logger.info("queued_breach_notification_success", { json });
return NextResponse.json({ success: true }, { status: 200 });
} catch {
if (process.env.NODE_ENV === "development") {
if (!subscriptionName) {
throw new Error("GCP_PUBSUB_SUBSCRIPTION_NAME env var not set");
}
await pubsub.createTopic(topicName);
await pubsub.topic(topicName).createSubscription(subscriptionName);
} else {
logger.error("pubsub_topic_not_found:", { topicName });
captureMessage(`pubsub_topic_not_found: ${topicName}`);
return NextResponse.json({ success: false }, { status: 429 });
}
logger.error("error_queuing_hibp_breach:", { topicName });
return NextResponse.json({ success: false }, { status: 429 });
}
}