From 1657ad375b988b453f9a36218e73af0f39ae233e Mon Sep 17 00:00:00 2001 From: David Ernst Date: Mon, 5 Jan 2026 23:13:56 -0800 Subject: [PATCH] /api/malware-check: Alert admin on edge-case endpoint errors --- pages/api/malware-check/confirm.ts | 11 ++++----- pages/api/malware-check/decrypt-success.ts | 13 +++++------ pages/api/malware-check/download.ts | 27 ++++++++++++++-------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/pages/api/malware-check/confirm.ts b/pages/api/malware-check/confirm.ts index 84919f65..486c4e34 100644 --- a/pages/api/malware-check/confirm.ts +++ b/pages/api/malware-check/confirm.ts @@ -1,6 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next' import { firebase, pushover } from '../_services' +import { malwareCheckErrorGenerator } from './download' export default async (req: NextApiRequest, res: NextApiResponse) => { const { auth_token, confirmed, election_id, issue_description, otp } = req.body @@ -14,17 +15,15 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { const checkDoc = electionDoc.collection('malware-checks').doc(auth_token) const check = await checkDoc.get() - if (!check.exists) return res.status(404).json({ error: 'No malware check found' }) + const malwareCheckError = malwareCheckErrorGenerator('confirm', election_id, auth_token, otp, res) + if (!check.exists) return malwareCheckError('No malware check found') const data = check.data() - if (!data || !data.checks || !Array.isArray(data.checks)) return res.status(404).json({ error: 'Invalid check data' }) + if (!data || !data.checks || !Array.isArray(data.checks)) return malwareCheckError('Invalid check data') // Find matching check entry by OTP const checkEntry = data.checks.find((entry: { otp?: string }) => entry.otp === otp) - if (!checkEntry) { - await pushover('Malware check, confirm: Invalid OTP', `${election_id}: ${auth_token}\nOTP: ${otp}`) - return res.status(404).json({ error: 'Invalid OTP' }) - } + if (!checkEntry) return malwareCheckError('Invalid OTP', 401) // Update the specific check entry - add confirmation const updatedChecks = data.checks.map((entry: { confirmations?: unknown[]; otp?: string }) => { diff --git a/pages/api/malware-check/decrypt-success.ts b/pages/api/malware-check/decrypt-success.ts index 6c830130..a59616ad 100644 --- a/pages/api/malware-check/decrypt-success.ts +++ b/pages/api/malware-check/decrypt-success.ts @@ -1,6 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next' -import { firebase, pushover } from '../_services' +import { firebase } from '../_services' +import { malwareCheckErrorGenerator } from './download' export default async (req: NextApiRequest, res: NextApiResponse) => { const { auth_token, election_id, otp } = req.body @@ -12,18 +13,16 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { const electionDoc = firebase.firestore().collection('elections').doc(election_id) const checkDoc = electionDoc.collection('malware-checks').doc(auth_token) + const malwareCheckError = malwareCheckErrorGenerator('decrypt-success', election_id, auth_token, otp, res) const check = await checkDoc.get() - if (!check.exists) return res.status(404).json({ error: 'No malware check found' }) + if (!check.exists) return malwareCheckError('No malware check found') const data = check.data() - if (!data || !data.checks || !Array.isArray(data.checks)) return res.status(404).json({ error: 'Invalid check data' }) + if (!data || !data.checks || !Array.isArray(data.checks)) return malwareCheckError('Invalid check data') // Find matching check entry by OTP const checkEntry = data.checks.find((entry: { otp?: string }) => entry.otp === otp) - if (!checkEntry) { - await pushover('Malware check, decrypt success: Invalid OTP', `${election_id}: ${auth_token}\nOTP: ${otp}`) - return res.status(404).json({ error: 'Invalid OTP' }) - } + if (!checkEntry) return malwareCheckError('Invalid OTP', 401) // Update the specific check entry const updatedChecks = data.checks.map((entry: { otp?: string }) => { diff --git a/pages/api/malware-check/download.ts b/pages/api/malware-check/download.ts index b5598f88..58fdf96a 100644 --- a/pages/api/malware-check/download.ts +++ b/pages/api/malware-check/download.ts @@ -14,20 +14,16 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { const checkDoc = electionDoc.collection('malware-checks').doc(auth_token) const check = await checkDoc.get() - if (!check.exists) { - await pushover('Malware check not found', `${election_id}: ${auth_token}\nOTP: ${otp}`) - return res.status(404).json({ error: 'No malware check found' }) - } + + const malwareCheckError = malwareCheckErrorGenerator('download', election_id, auth_token, otp, res) + if (!check.exists) return malwareCheckError('No malware check found') const data = check.data() - if (!data || !data.checks || !Array.isArray(data.checks)) return res.status(404).json({ error: 'Invalid check data' }) + if (!data || !data.checks || !Array.isArray(data.checks)) return malwareCheckError('Invalid check data') // Find matching check entry by OTP const checkEntry = data.checks.find((entry: { otp?: string }) => entry.otp === otp) - if (!checkEntry) { - await pushover('Malware check, download: Invalid OTP', `${election_id}: ${auth_token}\nOTP: ${otp}`) - return res.status(401).json({ error: 'Invalid OTP' }) - } + if (!checkEntry) return malwareCheckError('Invalid OTP', 401) // Check if already downloaded if (checkEntry.downloaded_at) { @@ -63,3 +59,16 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { encrypted_vote: storedEncryptedVote, }) } + +export function malwareCheckErrorGenerator( + type: 'confirm' | 'decrypt-success' | 'download', + election_id: string, + auth_token: string, + otp: string, + res: NextApiResponse, +) { + return async function (error: string, errorCode = 404) { + await pushover(`Malware check, ${type}: ${error}`, `${election_id}: ${auth_token}\nOTP: ${otp}`) + return res.status(errorCode).json({ error }) + } +}