diff --git a/pages/api/submit-vote.ts b/pages/api/submit-vote.ts index 92d4ca6f..467d8d1e 100644 --- a/pages/api/submit-vote.ts +++ b/pages/api/submit-vote.ts @@ -9,7 +9,10 @@ import { validateAuthToken } from './check-auth-token' import { pusher } from './pusher' export default async (req: NextApiRequest, res: NextApiResponse) => { - const { auth, election_id, encrypted_vote } = req.body + const payload = req.method === 'POST' ? req.body : req.query + const { auth, election_id, encrypted_vote } = payload + + // return res.status(200).json({ auth, election_id, encrypted_vote }) const electionDoc = firebase.firestore().collection('elections').doc(election_id) diff --git a/src/vote/AirGappedSubmission.tsx b/src/vote/AirGappedSubmission.tsx index bd74b02d..d5da0a35 100644 --- a/src/vote/AirGappedSubmission.tsx +++ b/src/vote/AirGappedSubmission.tsx @@ -1,3 +1,4 @@ +import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { DetailedEncryptionReceipt } from './submitted/DetailedEncryptionReceipt' @@ -13,7 +14,9 @@ export const AirGappedSubmission = ({ state: State }) => { const [isOffline, setIsOffline] = useState(false) + const path = useRouter().asPath + // Show when going offline useEffect(() => { const setOnline = () => setIsOffline(false) const setOffline = () => setIsOffline(true) @@ -27,7 +30,12 @@ export const AirGappedSubmission = ({ } }, []) - if (!isOffline) return null + // Or include "offline" in path (e.g /vote?auth=foo&offline) to show even if online + if (!(isOffline || path.includes('offline'))) return null + + const submission_url = `/api/submit-vote?auth=${auth}&election_id=${election_id}&encrypted_vote=${JSON.stringify( + sortedKeys(state.encrypted), + )}` return (
@@ -37,18 +45,18 @@ export const AirGappedSubmission = ({ You can submit your vote via an air-gapped submission. If you do this from a Private Incognito window, it ensures even this webapp cannot possibly extract your private vote selections.
-

When you{"'"}re done making your vote selections...

+

1. When you{"'"}re done making your vote selections...

- 1. Copy and Paste the following Detailed Encryption Receipt somewhere safe for your own private records: + Copy and Paste the following Detailed Encryption Receipt somewhere safe for your own private records:
-

Verifying your Vote

- 2. The easiest way to quickly verify your vote was counted correctly is your Verification #. +

2. Verifying your Vote

+ The easiest way to quickly verify your vote was counted correctly is your Verification #.
This unique secret number is generated randomly on your own device. No one else can know it.
@@ -64,6 +72,47 @@ export const AirGappedSubmission = ({ for quicker access.
+ +
+

3. Submitting your Vote

+ Lastly, now that your private verification information is backed up, you are ready to submit your encrypted + vote. +
Your full encrypted vote is:
+
+ {JSON.stringify(sortedKeys(state.encrypted), null, 2)} +
+
+ You can submit this encrypted payload by visiting this Submission URL, once + you turn your internet back on: +
+
+ + {window.location.origin} + {submission_url} + +
+
+
+ Once you{"'"}ve copied down your private data and Submission URL, you can close this window, turn your + internet back on, and visit your submission URL. +
+
) } + +function sortedKeys(obj: unknown): string { + const sortedObj = JSON.parse( + JSON.stringify(obj, (key, value) => + value instanceof Object && !(value instanceof Array) + ? Object.keys(value) + .sort() + .reduce((sorted, key) => { + sorted[key] = value[key] + return sorted + }, {} as Record) + : value, + ), + ) + return sortedObj +}