1+ /* This Source Code Form is subject to the terms of the Mozilla Public
2+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+ export const runtime = "nodejs" ;
6+
17/* This Source Code Form is subject to the terms of the Mozilla Public
28 * License, v. 2.0. If a copy of the MPL was not distributed with this
39 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
410
511import { NextRequest , NextResponse } from "next/server" ;
6- import { captureMessage } from "@sentry/node" ;
712
813import { bearerToken } from "../../../utils/auth" ;
914import { logger } from "../../../../functions/server/logging" ;
1015
1116import { PubSub } from "@google-cloud/pubsub" ;
1217import { isValidBearer } from "../../../../../utils/hibp" ;
1318import { config } from "../../../../../config" ;
14-
15- const projectId = process . env . GCP_PUBSUB_PROJECT_ID ;
16- const topicName = process . env . GCP_PUBSUB_TOPIC_NAME ;
17- const subscriptionName = process . env . GCP_PUBSUB_SUBSCRIPTION_NAME ;
19+ import {
20+ hibpNotifyRequestsTotal ,
21+ incHibpNotifyFailure ,
22+ } from "../../../../../instrumentation.node" ;
1823
1924export type PostHibpNotificationRequestBody = {
2025 breachName : string ;
@@ -29,23 +34,18 @@ export type PostHibpNotificationRequestBody = {
2934 * @param req
3035 */
3136export async function POST ( req : NextRequest ) {
37+ hibpNotifyRequestsTotal . inc ( ) ;
38+
3239 let pubsub : PubSub ;
3340 let json : PostHibpNotificationRequestBody ;
34- const hibpNotifyToken = process . env . HIBP_NOTIFY_TOKEN ;
41+ const hibpNotifyToken = config . hibpNotifyToken ;
42+ const projectId = config . gcp . projectId ;
43+ const topicName = config . gcp . pubsub . hibpTopic ;
3544 try {
36- if ( ! projectId ) {
37- throw new Error ( "GCP_PUBSUB_PROJECT_ID env var not set" ) ;
38- }
39- if ( ! topicName ) {
40- throw new Error ( "GCP_PUBSUB_TOPIC_NAME env var not set" ) ;
41- }
42- if ( ! hibpNotifyToken ) {
43- throw new Error ( "HIBP_NOTIFY_TOKEN env var not set" ) ;
44- }
45-
4645 const headerToken = bearerToken ( req ) ;
4746 if ( ! isValidBearer ( headerToken , hibpNotifyToken ) ) {
4847 logger . error ( `Received invalid header token: [${ headerToken } ]` ) ;
48+ incHibpNotifyFailure ( "unauthorized" ) ;
4949 return NextResponse . json ( { success : false } , { status : 401 } ) ;
5050 }
5151
@@ -55,44 +55,44 @@ export async function POST(req: NextRequest) {
5555 logger . error (
5656 "HIBP breach notification: requires breachName, hashPrefix, and hashSuffixes." ,
5757 ) ;
58+ incHibpNotifyFailure ( "bad-request" ) ;
5859 return NextResponse . json ( { success : false } , { status : 400 } ) ;
5960 }
6061 } catch ( ex ) {
6162 logger . error ( "error_processing_breach_alert_request:" , {
6263 exception : ex as string ,
6364 } ) ;
65+ incHibpNotifyFailure ( "server-error" ) ;
6466 return NextResponse . json ( { success : false } , { status : 500 } ) ;
6567 }
6668
6769 try {
6870 pubsub = new PubSub ( { projectId } ) ;
6971 } catch ( ex ) {
7072 logger . error ( "error_connecting_to_pubsub:" , { exception : ex as string } ) ;
71- captureMessage ( `error_connecting_to_pubsub: ${ ex as string } ` ) ;
73+ incHibpNotifyFailure ( "pubsub-error" ) ;
7274 return NextResponse . json ( { success : false } , { status : 429 } ) ;
7375 }
7476
7577 try {
7678 const topic = pubsub . topic ( topicName ) ;
79+ const [ exists ] = await topic . exists ( ) ;
80+ if ( ! exists ) {
81+ logger . error ( "error_connecting_to_pubsub: topic does not exist" , {
82+ topic : topicName ,
83+ } ) ;
84+ incHibpNotifyFailure ( "pubsub-error" ) ;
85+ return NextResponse . json ( { success : false } , { status : 500 } ) ;
86+ }
7787 await topic . publishMessage ( { json } ) ;
7888 logger . info ( "queued_breach_notification_success" , {
7989 json,
8090 topic : topicName ,
8191 } ) ;
8292 return NextResponse . json ( { success : true } , { status : 200 } ) ;
8393 } catch {
84- if ( config . nodeEnv === "development" ) {
85- if ( ! subscriptionName ) {
86- throw new Error ( "GCP_PUBSUB_SUBSCRIPTION_NAME env var not set" ) ;
87- }
88- await pubsub . createTopic ( topicName ) ;
89- await pubsub . topic ( topicName ) . createSubscription ( subscriptionName ) ;
90- } else {
91- logger . error ( "pubsub_topic_not_found:" , { topicName } ) ;
92- captureMessage ( `pubsub_topic_not_found: ${ topicName } ` ) ;
93- return NextResponse . json ( { success : false } , { status : 429 } ) ;
94- }
9594 logger . error ( "error_queuing_hibp_breach:" , { topicName } ) ;
95+ incHibpNotifyFailure ( "pubsub-error" ) ;
9696 return NextResponse . json ( { success : false } , { status : 429 } ) ;
9797 }
9898}
0 commit comments