From 645a05bc9be6c34996e189158792b7dc87fd258d Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Tue, 21 Sep 2021 16:26:35 -0400 Subject: [PATCH 01/56] remove safari check --- components/Form.tsx | 15 ++++++--------- package-lock.json | 5 +++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index eae90bf..2d5858b 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -51,7 +51,6 @@ function Form(): JSX.Element { const getPassCount = async () => { const hitCount = await getHitCount(); - console.log(`hitcount = ${hitCount}`); setPassCount(hitCount); }; @@ -62,9 +61,7 @@ function Form(): JSX.Element { let response = await fetch(request); const counter = await response.text(); - - console.log('getHitCount returns ' + counter); - + return Promise.resolve(counter); } catch (e) { @@ -286,10 +283,10 @@ function Form(): JSX.Element { setErrorMessage('Sorry, iOS 13+ is needed for the Apple Wallet functionality to work') document.getElementById('download').setAttribute('disabled','true') } - if (isIOS && !isSafari) { - setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') - document.getElementById('download').setAttribute('disabled','true') - } + // if (isIOS && !isSafari) { + // setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') + // document.getElementById('download').setAttribute('disabled','true') + // } } return ( @@ -323,7 +320,7 @@ function Form(): JSX.Element { diff --git a/package-lock.json b/package-lock.json index ed9c154..8fbfdca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { "name": "grassroots_covidpass", - "version": "1.4.0", + "version": "1.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "grassroots_covidpass", - "version": "1.4.0", + "version": "1.8.0", + "license": "MIT", "dependencies": { "@headlessui/react": "^1.3.0", "@ninja-labs/verify-pdf": "^0.3.9", From 0955a35921057464ee61cecfb54a0d2d38e522ce Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Tue, 21 Sep 2021 18:57:50 -0400 Subject: [PATCH 02/56] added special case to show GREEN for 1 shot of JANSSEN --- src/payload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payload.ts b/src/payload.ts index 9fd89c6..1ac0222 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -106,7 +106,7 @@ export class Payload { this.receipt = body.receipt; this.rawData = body.rawData; - if (body.receipt.numDoses > 1) { + if (body.receipt.numDoses > 1 || body.receipt.vaccineName.includes('JANSSEN')) { this.backgroundColor = COLORS.GREEN; } else { this.backgroundColor = COLORS.YELLOW; From ed415a5c69756b82e5aa548fc91578c58186c030 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Tue, 21 Sep 2021 20:01:38 -0400 Subject: [PATCH 03/56] More logging for sentry to track down errors --- components/Form.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 2d5858b..739ed41 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -213,13 +213,19 @@ function Form(): JSX.Element { try { if (file) { - console.log('> generatePass'); - + console.log('> get payload'); payloadBody = await getPayloadBodyFromFile(file, color); + + console.log('> increment count'); await incrementCount(); + console.log('> generatePass'); let pass = await PassData.generatePass(payloadBody); + + console.log('> create blob'); const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"}); + + console.log('> save blob'); saveAs(passBlob, 'covid.pkpass'); setLoading(false); } From ec11d0614d608244ffb57edba1174014966a5197 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Tue, 21 Sep 2021 20:31:52 -0400 Subject: [PATCH 04/56] minor fixes to handle J&J and iOS Chrome issue... can't support iOS Chrome right now... lots of strange behaviors. --- components/Form.tsx | 8 +- deploy.sh | 1 + package-lock.json | 206 ++++++++++++++++++++++---------------------- package.json | 10 +-- src/payload.ts | 2 +- src/process.ts | 4 +- yarn.lock | 116 ++++++++++++------------- 7 files changed, 174 insertions(+), 173 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 2d5858b..9cc98b4 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -283,10 +283,10 @@ function Form(): JSX.Element { setErrorMessage('Sorry, iOS 13+ is needed for the Apple Wallet functionality to work') document.getElementById('download').setAttribute('disabled','true') } - // if (isIOS && !isSafari) { - // setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') - // document.getElementById('download').setAttribute('disabled','true') - // } + if (isIOS && !isSafari) { + setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') + document.getElementById('download').setAttribute('disabled','true') + } } return ( diff --git a/deploy.sh b/deploy.sh index ee4357a..e8ebaed 100755 --- a/deploy.sh +++ b/deploy.sh @@ -2,4 +2,5 @@ docker build . -t covidpass -t gcr.io/broadcast2patients/covidpass docker push gcr.io/broadcast2patients/covidpass gcloud config set project broadcast2patients gcloud config set run/region us-east1 +gcloud run services update-traffic covidpass --to-latest gcloud run deploy covidpass --image gcr.io/broadcast2patients/covidpass:latest --platform managed diff --git a/package-lock.json b/package-lock.json index 8fbfdca..10331e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,11 +11,11 @@ "dependencies": { "@headlessui/react": "^1.3.0", "@ninja-labs/verify-pdf": "^0.3.9", - "@sentry/browser": "^6.12.0", - "@sentry/integrations": "^6.12.0", - "@sentry/react": "^6.12.0", - "@sentry/tracing": "^6.12.0", - "@sentry/types": "^6.12.0", + "@sentry/browser": "^6.13.2", + "@sentry/integrations": "^6.13.2", + "@sentry/react": "^6.13.2", + "@sentry/tracing": "^6.13.2", + "@sentry/types": "^6.13.2", "@zxing/browser": "^0.0.9", "@zxing/library": "^0.18.6", "base45": "^3.0.0", @@ -306,13 +306,13 @@ } }, "node_modules/@sentry/browser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz", - "integrity": "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.13.2.tgz", + "integrity": "sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag==", "dependencies": { - "@sentry/core": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/core": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -320,14 +320,14 @@ } }, "node_modules/@sentry/core": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz", - "integrity": "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", + "integrity": "sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==", "dependencies": { - "@sentry/hub": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -335,12 +335,12 @@ } }, "node_modules/@sentry/hub": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz", - "integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.2.tgz", + "integrity": "sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==", "dependencies": { - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -348,12 +348,12 @@ } }, "node_modules/@sentry/integrations": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.12.0.tgz", - "integrity": "sha512-M9gsVdWZp5fAFFpTjK2IBuWzW4SBxGAI3tVbYZvVx16S/BY0GsPC1dYpjJx9OTBS/8CmCWdGxnUmjACo/8w1LA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.13.2.tgz", + "integrity": "sha512-CzxMtNr4nkZbifD0Rb6tXwqfqm+fWKl4IQTaFrJ92VNdgihBMVWYmflRqkMkGh1iFN8bVPpXrGyplY5tFN+2kA==", "dependencies": { - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "localforage": "^1.8.1", "tslib": "^1.9.3" }, @@ -362,12 +362,12 @@ } }, "node_modules/@sentry/minimal": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz", - "integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.2.tgz", + "integrity": "sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==", "dependencies": { - "@sentry/hub": "6.12.0", - "@sentry/types": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/types": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -375,14 +375,14 @@ } }, "node_modules/@sentry/react": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.12.0.tgz", - "integrity": "sha512-E8Nw9PPzP/EyMy64ksr9xcyYYlBmUA5ROnkPQp7o5wF0xf5/J+nMS1tQdyPnLQe2KUgHlN4kVs2HHft1m7mSYQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.13.2.tgz", + "integrity": "sha512-aLkWyn697LTcmK1PPnUg5UJcyBUPoI68motqgBY53SIYDAwOeYNUQt2aanDuOTY5aE2PdnJwU48klA8vuYkoRQ==", "dependencies": { - "@sentry/browser": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/browser": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "hoist-non-react-statics": "^3.3.2", "tslib": "^1.9.3" }, @@ -394,14 +394,14 @@ } }, "node_modules/@sentry/tracing": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz", - "integrity": "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.2.tgz", + "integrity": "sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==", "dependencies": { - "@sentry/hub": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -409,19 +409,19 @@ } }, "node_modules/@sentry/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", - "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.2.tgz", + "integrity": "sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==", "engines": { "node": ">=6" } }, "node_modules/@sentry/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==", "dependencies": { - "@sentry/types": "6.12.0", + "@sentry/types": "6.13.2", "tslib": "^1.9.3" }, "engines": { @@ -5492,95 +5492,95 @@ } }, "@sentry/browser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz", - "integrity": "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.13.2.tgz", + "integrity": "sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag==", "requires": { - "@sentry/core": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/core": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" } }, "@sentry/core": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz", - "integrity": "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", + "integrity": "sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==", "requires": { - "@sentry/hub": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" } }, "@sentry/hub": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz", - "integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.2.tgz", + "integrity": "sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==", "requires": { - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" } }, "@sentry/integrations": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.12.0.tgz", - "integrity": "sha512-M9gsVdWZp5fAFFpTjK2IBuWzW4SBxGAI3tVbYZvVx16S/BY0GsPC1dYpjJx9OTBS/8CmCWdGxnUmjACo/8w1LA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.13.2.tgz", + "integrity": "sha512-CzxMtNr4nkZbifD0Rb6tXwqfqm+fWKl4IQTaFrJ92VNdgihBMVWYmflRqkMkGh1iFN8bVPpXrGyplY5tFN+2kA==", "requires": { - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "localforage": "^1.8.1", "tslib": "^1.9.3" } }, "@sentry/minimal": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz", - "integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.2.tgz", + "integrity": "sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==", "requires": { - "@sentry/hub": "6.12.0", - "@sentry/types": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/types": "6.13.2", "tslib": "^1.9.3" } }, "@sentry/react": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.12.0.tgz", - "integrity": "sha512-E8Nw9PPzP/EyMy64ksr9xcyYYlBmUA5ROnkPQp7o5wF0xf5/J+nMS1tQdyPnLQe2KUgHlN4kVs2HHft1m7mSYQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.13.2.tgz", + "integrity": "sha512-aLkWyn697LTcmK1PPnUg5UJcyBUPoI68motqgBY53SIYDAwOeYNUQt2aanDuOTY5aE2PdnJwU48klA8vuYkoRQ==", "requires": { - "@sentry/browser": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/browser": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "hoist-non-react-statics": "^3.3.2", "tslib": "^1.9.3" } }, "@sentry/tracing": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz", - "integrity": "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.2.tgz", + "integrity": "sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==", "requires": { - "@sentry/hub": "6.12.0", - "@sentry/minimal": "6.12.0", - "@sentry/types": "6.12.0", - "@sentry/utils": "6.12.0", + "@sentry/hub": "6.13.2", + "@sentry/minimal": "6.13.2", + "@sentry/types": "6.13.2", + "@sentry/utils": "6.13.2", "tslib": "^1.9.3" } }, "@sentry/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", - "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.2.tgz", + "integrity": "sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==" }, "@sentry/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==", "requires": { - "@sentry/types": "6.12.0", + "@sentry/types": "6.13.2", "tslib": "^1.9.3" } }, diff --git a/package.json b/package.json index 9d0ef43..1baa9a7 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ "dependencies": { "@headlessui/react": "^1.3.0", "@ninja-labs/verify-pdf": "^0.3.9", - "@sentry/browser": "^6.12.0", - "@sentry/integrations": "^6.12.0", - "@sentry/react": "^6.12.0", - "@sentry/tracing": "^6.12.0", - "@sentry/types": "^6.12.0", + "@sentry/browser": "^6.13.2", + "@sentry/integrations": "^6.13.2", + "@sentry/react": "^6.13.2", + "@sentry/tracing": "^6.13.2", + "@sentry/types": "^6.13.2", "@zxing/browser": "^0.0.9", "@zxing/library": "^0.18.6", "base45": "^3.0.0", diff --git a/src/payload.ts b/src/payload.ts index 1ac0222..bb6186c 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -106,7 +106,7 @@ export class Payload { this.receipt = body.receipt; this.rawData = body.rawData; - if (body.receipt.numDoses > 1 || body.receipt.vaccineName.includes('JANSSEN')) { + if (body.receipt.numDoses > 1 || body.receipt.vaccineName.toLowerCase().includes('janssen') || body.receipt.vaccineName.toLowerCase().includes('johnson') || body.receipt.vaccineName.toLowerCase().includes('j&j')) { this.backgroundColor = COLORS.GREEN; } else { this.backgroundColor = COLORS.YELLOW; diff --git a/src/process.ts b/src/process.ts index 3df1e00..92bc5c7 100644 --- a/src/process.ts +++ b/src/process.ts @@ -46,9 +46,9 @@ async function loadPDF(signedPdfBuffer : ArrayBuffer): Promise { const issuedToOntarioHealth = (result.issuedTo.commonName == 'covid19signer.ontariohealth.ca'); console.log(`PDF is signed by ${result.issuedBy.organizationName}, issued to ${result.issuedTo.commonName}`); - const bypass = window.location.href.includes('grassroots2'); + // const bypass = window.location.href.includes('grassroots2'); - if ((isClientCertificate && issuedByEntrust && issuedToOntarioHealth) || bypass) { + if ((isClientCertificate && issuedByEntrust && issuedToOntarioHealth)) { console.log('getting receipt details inside PDF'); const receipt = await getPdfDetails(signedPdfBuffer); // console.log(JSON.stringify(receipt, null, 2)); diff --git a/yarn.lock b/yarn.lock index 1d24c6a..55e7e67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -145,89 +145,89 @@ "@nodelib/fs.scandir" "2.1.5" "fastq" "^1.6.0" -"@sentry/browser@^6.12.0", "@sentry/browser@6.12.0": - "integrity" "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==" - "resolved" "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz" - "version" "6.12.0" +"@sentry/browser@^6.13.2", "@sentry/browser@6.13.2": + "integrity" "sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag==" + "resolved" "https://registry.npmjs.org/@sentry/browser/-/browser-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/core" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/core" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "tslib" "^1.9.3" -"@sentry/core@6.12.0": - "integrity" "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==" - "resolved" "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz" - "version" "6.12.0" +"@sentry/core@6.13.2": + "integrity" "sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==" + "resolved" "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/hub" "6.12.0" - "@sentry/minimal" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/minimal" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "tslib" "^1.9.3" -"@sentry/hub@6.12.0": - "integrity" "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==" - "resolved" "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz" - "version" "6.12.0" +"@sentry/hub@6.13.2": + "integrity" "sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==" + "resolved" "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "tslib" "^1.9.3" -"@sentry/integrations@^6.12.0": - "integrity" "sha512-M9gsVdWZp5fAFFpTjK2IBuWzW4SBxGAI3tVbYZvVx16S/BY0GsPC1dYpjJx9OTBS/8CmCWdGxnUmjACo/8w1LA==" - "resolved" "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.12.0.tgz" - "version" "6.12.0" +"@sentry/integrations@^6.13.2": + "integrity" "sha512-CzxMtNr4nkZbifD0Rb6tXwqfqm+fWKl4IQTaFrJ92VNdgihBMVWYmflRqkMkGh1iFN8bVPpXrGyplY5tFN+2kA==" + "resolved" "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "localforage" "^1.8.1" "tslib" "^1.9.3" -"@sentry/minimal@6.12.0": - "integrity" "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==" - "resolved" "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz" - "version" "6.12.0" +"@sentry/minimal@6.13.2": + "integrity" "sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==" + "resolved" "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/hub" "6.12.0" - "@sentry/types" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/types" "6.13.2" "tslib" "^1.9.3" -"@sentry/react@^6.12.0": - "integrity" "sha512-E8Nw9PPzP/EyMy64ksr9xcyYYlBmUA5ROnkPQp7o5wF0xf5/J+nMS1tQdyPnLQe2KUgHlN4kVs2HHft1m7mSYQ==" - "resolved" "https://registry.npmjs.org/@sentry/react/-/react-6.12.0.tgz" - "version" "6.12.0" +"@sentry/react@^6.13.2": + "integrity" "sha512-aLkWyn697LTcmK1PPnUg5UJcyBUPoI68motqgBY53SIYDAwOeYNUQt2aanDuOTY5aE2PdnJwU48klA8vuYkoRQ==" + "resolved" "https://registry.npmjs.org/@sentry/react/-/react-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/browser" "6.12.0" - "@sentry/minimal" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/browser" "6.13.2" + "@sentry/minimal" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "hoist-non-react-statics" "^3.3.2" "tslib" "^1.9.3" -"@sentry/tracing@^6.12.0": - "integrity" "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==" - "resolved" "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz" - "version" "6.12.0" +"@sentry/tracing@^6.13.2": + "integrity" "sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==" + "resolved" "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/hub" "6.12.0" - "@sentry/minimal" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/minimal" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" "tslib" "^1.9.3" -"@sentry/types@^6.12.0", "@sentry/types@6.12.0": - "integrity" "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" - "resolved" "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz" - "version" "6.12.0" +"@sentry/types@^6.13.2", "@sentry/types@6.13.2": + "integrity" "sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==" + "resolved" "https://registry.npmjs.org/@sentry/types/-/types-6.13.2.tgz" + "version" "6.13.2" -"@sentry/utils@6.12.0": - "integrity" "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==" - "resolved" "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz" - "version" "6.12.0" +"@sentry/utils@6.13.2": + "integrity" "sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==" + "resolved" "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.2.tgz" + "version" "6.13.2" dependencies: - "@sentry/types" "6.12.0" + "@sentry/types" "6.13.2" "tslib" "^1.9.3" "@types/eslint-scope@^3.7.0": From 13406b688eb95ce1ab6ffbaf772eb75f456b47e6 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Tue, 21 Sep 2021 23:17:45 -0400 Subject: [PATCH 05/56] added some extra debug code to troubleshoot Object Not found problem. --- components/Form.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 9cc98b4..cb54578 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -17,6 +17,7 @@ import Colors from './Colors'; import {isChrome, isIOS, isIPad13, isMacOs, isSafari, deviceDetect, osName, osVersion} from 'react-device-detect'; import * as Sentry from '@sentry/react'; import { counterReset } from 'html2canvas/dist/types/css/property-descriptors/counter-reset'; +import { color } from 'html2canvas/dist/types/css/types/color'; function Form(): JSX.Element { @@ -215,7 +216,7 @@ function Form(): JSX.Element { console.log('> generatePass'); - payloadBody = await getPayloadBodyFromFile(file, color); + payloadBody = await getPayloadBodyFromFile(file, COLORS.GREEN); await incrementCount(); let pass = await PassData.generatePass(payloadBody); @@ -227,8 +228,15 @@ function Form(): JSX.Element { } catch (e) { console.error(e); - setErrorMessage(e.message); + Sentry.captureException(e); + + if (e.message != undefined) { + setErrorMessage(e.message); + } else { + setErrorMessage("Unable to continue."); + } + setLoading(false); } } @@ -248,7 +256,7 @@ function Form(): JSX.Element { let payloadBody: PayloadBody; try { - payloadBody = await getPayloadBodyFromFile(file, null); + payloadBody = await getPayloadBodyFromFile(file, COLORS.GREEN); await incrementCount(); let photoBlob = await Photo.generatePass(payloadBody); From 67d56c942d2431999293cbfed332da4f8e5d397e Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Thu, 23 Sep 2021 05:10:11 -0400 Subject: [PATCH 06/56] v1.9 - added support for versioning of registration functions to allow concurrent operations of v.Current and v.Next --- .env.production | 1 + .gitignore | 1 + components/Form.tsx | 19 +++++++++++++------ components/Page.tsx | 2 +- package.json | 2 +- pages/api/config.tsx | 4 +++- pages/index.tsx | 2 +- public/locales/en/common.yml | 3 +++ src/pass.ts | 33 +++++++++++++++++++++++++-------- 9 files changed, 49 insertions(+), 18 deletions(-) diff --git a/.env.production b/.env.production index 2418bbf..24f1b82 100644 --- a/.env.production +++ b/.env.production @@ -1,3 +1,4 @@ API_BASE_URL=https://covidpassapinet-pnrnxf7lvq-pd.a.run.app VERIFIER_HOST=https://verifier.vaccine-ontario.ca HITCOUNT_HOST=https://hitcount.vaccine-ontario.ca +REGISTRATION_HOST=https://us-central1-grassroot-verifier.cloudfunctions.net \ No newline at end of file diff --git a/.gitignore b/.gitignore index ea5d8c7..abc6792 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ yarn-error.log* # Idea files .idea +.env.production diff --git a/components/Form.tsx b/components/Form.tsx index 4a002f3..a002a58 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -233,17 +233,24 @@ function Form(): JSX.Element { } catch (e) { - console.error(e); - Sentry.captureException(e); + if (e != undefined) { + console.error(e); + + Sentry.captureException(e); + + if (e.message != undefined) { + setErrorMessage(e.message); + } else { + setErrorMessage("Unable to continue."); + } - if (e.message != undefined) { - setErrorMessage(e.message); } else { - setErrorMessage("Unable to continue."); - } + setErrorMessage("Unexpected error. Sorry."); + } setLoading(false); + } } diff --git a/components/Page.tsx b/components/Page.tsx index a14fb67..ea926d1 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
Last updated: 2021-09-18 (v1.8)
+
Last updated: 2021-09-23 (v1.9)
diff --git a/package.json b/package.json index 1baa9a7..5a35716 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grassroots_covidpass", - "version": "1.8.0", + "version": "1.9.0", "author": "Billy Lo ", "license": "MIT", "private": false, diff --git a/pages/api/config.tsx b/pages/api/config.tsx index ba41633..f54aa33 100644 --- a/pages/api/config.tsx +++ b/pages/api/config.tsx @@ -4,11 +4,13 @@ type ConfigData = { apiBaseUrl: string verifierHost: string hitcountHost: string + registrationHost: string + functionSuffix: string } export default function handler(req: NextApiRequest, res: NextApiResponse) { // Return the API_BASE_URL. This Endpoint allows us to access the env Variable in client javascript - res.status(200).json({apiBaseUrl: process.env.API_BASE_URL, verifierHost: process.env.VERIFIER_HOST, hitcountHost: process.env.HITCOUNT_HOST}) + res.status(200).json({apiBaseUrl: process.env.API_BASE_URL, verifierHost: process.env.VERIFIER_HOST, hitcountHost: process.env.HITCOUNT_HOST, registrationHost: process.env.REGISTRATION_HOST, functionSuffix: process.env.FUNCTION_SUFFIX}) } diff --git a/pages/index.tsx b/pages/index.tsx index 24c1865..e221115 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -41,7 +41,7 @@ function Index(): JSX.Element {

{t('common:subtitle')}


{t('common:subtitle2')}

+

{t('common:subtitle')}


{t('common:subtitle2')}


{t('common:update1Date')} - {t('common:update1')}


{t('common:continueSpirit')}

}/>
diff --git a/public/locales/en/common.yml b/public/locales/en/common.yml index 28a0fb8..76e72fa 100644 --- a/public/locales/en/common.yml +++ b/public/locales/en/common.yml @@ -1,6 +1,9 @@ title: Vaccination Receipt to Wallet subtitle: This tool converts your vaccination receipt from Ontario Ministry of Health to an Apple Wallet pass for easy access in the interim. subtitle2: Once Ontario's official QR code is released on Oct 22, you will be able to update your Apple Wallet pass by visiting this site again. +update1Date: Sep 23 Updates +update1: Thanks so much for all the encouragements and suggestions to make this better. We plan to keep enhancing this to help more Canadians. Stay tuned! +continueSpirit: Continuing the spirit of ❤️ @VaxHuntersCanada ❤️ beyond vax hunting. 390K receipts processed already, thanks for keeping the community safe! privacyPolicy: Privacy Policy donate: Sponsor gitHub: GitHub diff --git a/src/pass.ts b/src/pass.ts index 692e709..e85f5eb 100644 --- a/src/pass.ts +++ b/src/pass.ts @@ -4,6 +4,7 @@ import {v4 as uuid4} from 'uuid'; import {Constants} from "./constants"; import {Payload, PayloadBody, PassDictionary} from "./payload"; import * as Sentry from '@sentry/react'; +import { QRCodeMatrixUtil } from '@zxing/library'; const crypto = require('crypto') @@ -105,22 +106,38 @@ export class PassData { } console.log('registering ' + JSON.stringify(clonedReceipt, null, 2)); - const configResponse = await fetch('/api/config') - const verifierHost = (await configResponse.json()).verifierHost + const configResponse = await fetch('/api/config'); - // const verifierHost = 'https://verifier.vaccine-ontario.ca'; + const configResponseJson = await configResponse.json(); - const response = await fetch('https://us-central1-grassroot-verifier.cloudfunctions.net/register', requestOptions); + const verifierHost = configResponseJson.verifierHost; + const registrationHost = configResponseJson.registrationHost; + let functionSuffix = configResponseJson.functionSuffix; + + if (functionSuffix == undefined) + functionSuffix = ''; + + const registerUrl = `${registrationHost}/register${functionSuffix}`; + console.log(registerUrl); + + const response = await fetch(registerUrl, requestOptions); const responseJson = await response.json(); - // console.log(JSON.stringify(responseJson,null,2)); + console.log(JSON.stringify(responseJson,null,2)); - if (responseJson["result"] != 'OK') + if (responseJson["result"] != 'OK') { + console.error(responseJson); return Promise.reject(); + } + + const encodedUri = encodeURI(`serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`); + const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; + + console.log(qrCodeUrl); // Create QR Code Object const qrCode: QrCode = { - message: `${verifierHost}/verify?serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`, + message: qrCodeUrl, format: QrFormat.PKBarcodeFormatQR, messageEncoding: Encoding.iso88591, // altText : payload.rawData @@ -135,7 +152,7 @@ export class PassData { // Adding required fields - // console.log(pass); + console.log(pass); // Create pass.json const passJson = JSON.stringify(pass); From 088c2de84c0a6ec0bb6ee61b53d4dfc1e0f89f03 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Thu, 23 Sep 2021 11:59:20 -0400 Subject: [PATCH 07/56] 1.9.2 - Date of Birth added to pass, commercial vaccine name in brackets For pass and photos --- components/Form.tsx | 24 ++++++++++++------------ components/Page.tsx | 6 ++++-- src/pass.ts | 8 ++++---- src/payload.ts | 28 ++++++++++++++++++++-------- src/photo.ts | 19 +++++++++++++++++-- 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index a002a58..1e5cba7 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -292,22 +292,22 @@ function Form(): JSX.Element { async function checkBrowserType() { - if (isIPad13) { - setErrorMessage('Sorry. Apple does not support the use of Wallet on iPad. Please use iPhone/Safari.'); - document.getElementById('download').setAttribute('disabled','true'); - } + // if (isIPad13) { + // setErrorMessage('Sorry. Apple does not support the use of Wallet on iPad. Please use iPhone/Safari.'); + // document.getElementById('download').setAttribute('disabled','true'); + // } if (!isSafari && !isChrome) { setErrorMessage('Sorry. Apple Wallet pass can be added using Safari or Chrome only.'); document.getElementById('download').setAttribute('disabled','true'); } - if (isIOS && (!osVersion.includes('13') && !osVersion.includes('14') && !osVersion.includes('15'))) { - setErrorMessage('Sorry, iOS 13+ is needed for the Apple Wallet functionality to work') - document.getElementById('download').setAttribute('disabled','true') - } - if (isIOS && !isSafari) { - setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') - document.getElementById('download').setAttribute('disabled','true') - } + // if (isIOS && (!osVersion.includes('13') && !osVersion.includes('14') && !osVersion.includes('15'))) { + // setErrorMessage('Sorry, iOS 13+ is needed for the Apple Wallet functionality to work') + // document.getElementById('download').setAttribute('disabled','true') + // } + // if (isIOS && !isSafari) { + // setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') + // document.getElementById('download').setAttribute('disabled','true') + // } } return ( diff --git a/components/Page.tsx b/components/Page.tsx index ea926d1..9e994de 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
Last updated: 2021-09-23 (v1.9)
+
Last updated: 2021-09-23 (v1.9.2)
@@ -71,9 +71,11 @@ function Page(props: PageProps): JSX.Element { NAME + DATE OF BIRTH - + + diff --git a/src/pass.ts b/src/pass.ts index e85f5eb..ec831eb 100644 --- a/src/pass.ts +++ b/src/pass.ts @@ -105,7 +105,7 @@ export class PassData { body: JSON.stringify(clonedReceipt) // body data type must match "Content-Type" header } - console.log('registering ' + JSON.stringify(clonedReceipt, null, 2)); + // console.log('registering ' + JSON.stringify(clonedReceipt, null, 2)); const configResponse = await fetch('/api/config'); const configResponseJson = await configResponse.json(); @@ -118,7 +118,7 @@ export class PassData { functionSuffix = ''; const registerUrl = `${registrationHost}/register${functionSuffix}`; - console.log(registerUrl); + // console.log(registerUrl); const response = await fetch(registerUrl, requestOptions); const responseJson = await response.json(); @@ -133,7 +133,7 @@ export class PassData { const encodedUri = encodeURI(`serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`); const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; - console.log(qrCodeUrl); + // console.log(qrCodeUrl); // Create QR Code Object const qrCode: QrCode = { @@ -152,7 +152,7 @@ export class PassData { // Adding required fields - console.log(pass); + // console.log(pass); // Create pass.json const passJson = JSON.stringify(pass); diff --git a/src/payload.ts b/src/payload.ts index bb6186c..765b79b 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -49,8 +49,20 @@ export class Payload { const name = body.receipt.name; const dateOfBirth = body.receipt.dateOfBirth; const vaccineName = body.receipt.vaccineName; - const vaccineNameProper = vaccineName.charAt(0) + vaccineName.substr(1).toLowerCase(); - const doseVaccine = "Dose " + String(body.receipt.numDoses) + ": " + vaccineNameProper; + let vaccineNameProper = vaccineName.charAt(0) + vaccineName.substr(1).toLowerCase(); + + if (vaccineName.includes('PFIZER')) + vaccineNameProper = 'Pfizer (Comirnaty)' + + if (vaccineName.includes('MODERNA')) + vaccineNameProper = 'Moderna (SpikeVax)' + // vaccineNameProper = 'Pfizer (Comirnaty)' + + if (vaccineName.includes('ASTRAZENECA')) + vaccineNameProper = 'AstraZeneca (Vaxzevria)' + + let doseVaccine = "#" + String(body.receipt.numDoses) + ": " + vaccineNameProper; + if (name == undefined) { throw new Error('nameMissing'); } @@ -88,16 +100,16 @@ export class Payload { key: "name", label: "Name", value: name + }, + { + key: "dob", + label: "Date of Birth", + value: dateOfBirth } ], backFields: [ - // { - // key: "dob", - // label: "Date of Birth", - // value: body.receipt.dateOfBirth, - // textAlignment: TextAlignment.right - // } + //TODO: add url link back to grassroots site ] } diff --git a/src/photo.ts b/src/photo.ts index 2da3f28..4982efe 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -94,14 +94,29 @@ export class Photo { else body.style.backgroundColor = 'orangered'; + const name = payload.receipt.name; + const dateOfBirth = payload.receipt.dateOfBirth; const vaccineName = payload.receipt.vaccineName; - const vaccineNameProper = vaccineName.charAt(0) + vaccineName.substr(1).toLowerCase(); - const doseVaccine = "Dose " + String(payload.receipt.numDoses) + ": " + vaccineNameProper; + let vaccineNameProper = vaccineName.charAt(0) + vaccineName.substr(1).toLowerCase(); + + if (vaccineName.includes('PFIZER')) + vaccineNameProper = 'Pfizer (Comirnaty)' + + if (vaccineName.includes('MODERNA')) + vaccineNameProper = 'Moderna (SpikeVax)' + // vaccineNameProper = 'Pfizer (Comirnaty)' + + if (vaccineName.includes('ASTRAZENECA')) + vaccineNameProper = 'AstraZeneca (Vaxzevria)' + + let doseVaccine = "#" + String(payload.receipt.numDoses) + ": " + vaccineNameProper; + document.getElementById('vaccineName').innerText = doseVaccine; document.getElementById('vaccinationDate').innerText = payload.receipt.vaccinationDate; document.getElementById('organization').innerText = payload.receipt.organization; document.getElementById('name').innerText = payload.receipt.name; + document.getElementById('dob').innerText = payload.receipt.dateOfBirth; const codeWriter = new BrowserQRCodeSvgWriter(); const svg = codeWriter.write(qrCode.message,200,200); From 6ecc054bc9ab4a64c0ea56d0c93f9e40b4ef1c2c Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 16:48:26 -0400 Subject: [PATCH 08/56] cleaned up alert banner with option to prevent closing TODO: Allow different types of alerts --- components/Alert.tsx | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/components/Alert.tsx b/components/Alert.tsx index 4fffdfb..a253178 100644 --- a/components/Alert.tsx +++ b/components/Alert.tsx @@ -1,24 +1,39 @@ -import {useTranslation} from 'next-i18next'; +import { useTranslation } from 'next-i18next'; interface AlertProps { - onClose: () => void; - errorMessage: string; + onClose?: () => void; + type: 'error' | 'warning'; + message: string; } function Alert(props: AlertProps): JSX.Element { const { t } = useTranslation(['index', 'errors']); + let color = 'red'; + let icon; + switch (props.type) { + case 'error': + color = 'red' + // icon = () => + // + break; + case 'warning': + color = 'yellow' + break; + } + return ( -
- {props.errorMessage} - - - {t('index:errorClose')} - - - +
+ {icon && icon()} + {props.message} + {props.onClose && + + {t('index:errorClose')} + + + }
) } From ae12a7eb9c3ae7ecc19f04e2d4785d2823aa3f2e Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 16:49:07 -0400 Subject: [PATCH 09/56] added error handling in an array added error message for unsupported browsers --- components/Form.tsx | 73 +++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 1e5cba7..10853f9 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -36,11 +36,13 @@ function Form(): JSX.Element { const [qrCode, setQrCode] = useState(undefined); const [file, setFile] = useState(undefined); - const [errorMessage, _setErrorMessage] = useState(undefined); const [loading, setLoading] = useState(false); const [passCount, setPassCount] = useState(''); const [generated, setGenerated] = useState(false); // this flag represents the file has been used to generate a pass + + const [isDisabledAppleWallet, setIsDisabledAppleWallet] = useState(false); + const [errorMessages, _setErrorMessages] = useState>([]); const hitcountHost = 'https://stats.vaccine-ontario.ca'; @@ -75,14 +77,18 @@ function Form(): JSX.Element { // Check if there is a translation and replace message accordingly const setErrorMessage = (message: string) => { if (message == undefined) { - _setErrorMessage(undefined); return; } const translation = t('errors:'.concat(message)); - _setErrorMessage(translation !== message ? translation : message); + _setErrorMessages(Array.from(new Set([...errorMessages, translation !== message ? translation : message]))); }; + const deleteErrorMessage = (message: string) =>{ + console.log(errorMessages) + _setErrorMessages(errorMessages.filter(item => item !== message)) + } + // File Input ref const inputFile = useRef(undefined) @@ -95,6 +101,8 @@ function Form(): JSX.Element { setQrCode(undefined); setFile(selectedFile); setGenerated(false); + deleteErrorMessage(t('errors:'.concat('noFileOrQrCode'))); + checkBrowserType(); } }); } @@ -261,7 +269,7 @@ function Form(): JSX.Element { setLoading(true); if (!file && !qrCode) { - setErrorMessage('noFileOrQrCode') + setErrorMessage('noFileOrQrCode'); setLoading(false); return; } @@ -289,25 +297,38 @@ function Form(): JSX.Element { setLoading(false); } } + const verifierLink = () =>
  • + + + +

    + {t('verifierLink')}  + + verifier.vaccine-ontario.ca + +

    +
  • - async function checkBrowserType() { + function checkBrowserType() { // if (isIPad13) { // setErrorMessage('Sorry. Apple does not support the use of Wallet on iPad. Please use iPhone/Safari.'); - // document.getElementById('download').setAttribute('disabled','true'); + // setIsDisabledAppleWallet(true); // } - if (!isSafari && !isChrome) { - setErrorMessage('Sorry. Apple Wallet pass can be added using Safari or Chrome only.'); - document.getElementById('download').setAttribute('disabled','true'); - } + // if (!isSafari && !isChrome) { + // setErrorMessage('Sorry. Apple Wallet pass can be added using Safari or Chrome only.'); + // setIsDisabledAppleWallet(true); + // } // if (isIOS && (!osVersion.includes('13') && !osVersion.includes('14') && !osVersion.includes('15'))) { // setErrorMessage('Sorry, iOS 13+ is needed for the Apple Wallet functionality to work') - // document.getElementById('download').setAttribute('disabled','true') - // } - // if (isIOS && !isSafari) { - // setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS') - // document.getElementById('download').setAttribute('disabled','true') + // setIsDisabledAppleWallet(true); // } + if (isIOS && !isSafari) { + // setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS'); + setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS'); + setIsDisabledAppleWallet(true); + console.log('not safari') + } } return ( @@ -374,20 +395,20 @@ function Form(): JSX.Element { -

    + {/*

    {t('index:dataPrivacyDescription')} - {/* + {t('index:privacyPolicy')} - . */} -

    + . +

    */}
      - + {verifierLink()} {passCount && } {/* */} @@ -395,8 +416,8 @@ function Form(): JSX.Element {
    -      @@ -414,13 +435,13 @@ function Form(): JSX.Element {
    + {errorMessages.map((message, i) => + + )} }/> - - { - errorMessage && setErrorMessage(undefined)}/> - } + ) } From dfe9bed7a98f508a566afc7979e055758b2b2cfa Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 16:49:23 -0400 Subject: [PATCH 10/56] updated array keys and added supported browsers --- pages/faq.tsx | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/pages/faq.tsx b/pages/faq.tsx index 42ec2bc..d894e80 100644 --- a/pages/faq.tsx +++ b/pages/faq.tsx @@ -7,20 +7,21 @@ import Card from '../components/Card' function Faq(): JSX.Element { const { t } = useTranslation(['common', 'index', 'faq']); const questionList = [ - {description: 'Which version of iOS does this support?', answer: 'iOS 13.7 is the minimum at the moment. We are looking for adjustments for older iOSes, but it will take a bit of time.', key: 1}, - {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.', key: 2}, - {description: 'Who made this?', answer: 'The same group of volunteers (Billy Lo, Ryan Slobojan, Evert Timberg, Jason Liu, Anujan Mathisekaran, Lisa Discepola, Samantha Finn, Madison Pearce) who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.', key: 3}, - {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, you will also be able to refresh what\'s in your Apple Wallet as well. More details will follow.', key: 4}, - {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.', key: 5}, - {description: 'How can organizations validate this QR code?', answer: 'Just aim your standard camera app (iPhone/Android) at the code, and it will bring up a web page that shows the verification result.', key: 6}, - {description: 'Is this free and private?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.', key: 7}, - {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay.', key: 8}, - {description: 'How about BC, Quebec and Alberta?', answer: 'We will be investigating BC shortly. If you are interested in contributing, email us at grassroots@vaccine-ontario.ca', key: 9}, - {description: 'How can I stay up-to-date on your progress?', answer: 'We will post regular updates on Twitter @grassroots_team.', key: 10}, - {description: 'I only have an emailed receipt (e.g. Red/White OHIP card users). Can I still use this tool?', answer: 'Not right now unfortunately. But we expect to be able to support that after the official app is released on 22 Oct.', key: 11}, - {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.', key: 12}, - {description: 'How about Apple Watch?', answer: 'If you have iCloud sync enabled, you will see the pass on the watch too.', key: 13}, - {description: 'I have more questions. Can you please help me?', answer: 'Sure. Just email us at grassroots@vaccine-ontario.ca.', key: 14} + {description: 'Which version of iOS does this support?', answer: 'iOS 13.7 is the minimum at the moment. We are looking for adjustments for older iOSes, but it will take a bit of time.'}, + {description: "What are the supported browsers?", answer: 'For iPhones, only Safari is supported for importing to your Apple Wallet. For any other devices, we recommend that you save it as photo using your browser of choice. Broswers built internally into mobile apps (e.g. Facebook, Twitter, Instagram) are known to have issues.'}, + {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.'}, + {description: 'Who made this?', answer: 'The same group of volunteers (Billy Lo, Ryan Slobojan, Evert Timberg, Jason Liu, Anujan Mathisekaran, Lisa Discepola, Samantha Finn, Madison Pearce) who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.'}, + {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, you will also be able to refresh what\'s in your Apple Wallet as well. More details will follow.'}, + {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.'}, + {description: 'How can organizations validate this QR code?', answer: 'Just aim your standard camera app (iPhone/Android) at the code, and it will bring up a web page that shows the verification result.'}, + {description: 'Is this free and private?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.'}, + {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay.'}, + {description: 'How about BC, Quebec and Alberta?', answer: 'We will be investigating BC shortly. If you are interested in contributing, email us at grassroots@vaccine-ontario.ca'}, + {description: 'How can I stay up-to-date on your progress?', answer: 'We will post regular updates on Twitter @grassroots_team.'}, + {description: 'I only have an emailed receipt (e.g. Red/White OHIP card users). Can I still use this tool?', answer: 'Not right now unfortunately. But we expect to be able to support that after the official app is released on 22 Oct.'}, + {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.'}, + {description: 'How about Apple Watch?', answer: 'If you have iCloud sync enabled, you will see the pass on the watch too.'}, + {description: 'I have more questions. Can you please help me?', answer: 'Sure. Just email us at grassroots@vaccine-ontario.ca.'} ]; @@ -30,11 +31,11 @@ function Faq(): JSX.Element {

    {t('faq:heading')}

      - {questionList.map(question => { + {questionList.map((question, i) => { return (
      -
    1. {question.key}. {question.description}
    2. -
    3. {question.answer}
    4. +
    5. {i+1}. {question.description}
    6. +
    7. {question.answer}


    8. ); From dac3ed3c11b2a7c07c7acf5a1fa93d3e8bbd8185 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 16:49:49 -0400 Subject: [PATCH 11/56] added warning banner for receipts without date of birth --- pages/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/index.tsx b/pages/index.tsx index e221115..13ad07a 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,11 +5,14 @@ import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; import Form from '../components/Form'; import Card from '../components/Card'; import Page from '../components/Page'; +import Alert from '../components/Alert'; import { useEffect, useState } from 'react'; function Index(): JSX.Element { const { t } = useTranslation(['common', 'index', 'errors']); + const [warning, setWarning] = useState("If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt.") + const title = 'Grassroots - Ontario vaccination receipt to your Apple wallet'; const description = 'Stores it on iPhone with a QR code for others to validate in a privacy respecting way.'; @@ -40,10 +43,10 @@ function Index(): JSX.Element { /> + {warning && setWarning(undefined)} message={warning} />}

      {t('common:subtitle')}


      {t('common:subtitle2')}


      {t('common:update1Date')} - {t('common:update1')}


      {t('common:continueSpirit')}

    }/> -
    }/> From 803844b1055469f7c94ff3103e64b739b1ae12a9 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 16:50:20 -0400 Subject: [PATCH 12/56] updated locales --- public/locales/en/index.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/en/index.yml b/public/locales/en/index.yml index c977376..464a68e 100644 --- a/public/locales/en/index.yml +++ b/public/locales/en/index.yml @@ -13,7 +13,7 @@ downloadReceipt: Download official receipt from Ontario Ministry of Health visit: Visit ontarioHealth: Ontario Ministry of Health gotoOntarioHealth: Go to Ontario Ministry of Health -downloadSignedPDF: and enter your information to display your official vaccination receipt. Press the Share Icon at the bottom, "Save As Files" to store it onto your iPhone. +downloadSignedPDF: and enter your information to display your official vaccination receipt. Press the Share Icon at the bottom, "Save As Files" to store it onto your iPhone. If you have completed this step before, you can proceed to the next step to prevent downloading the same file multiple times. pickColor: Pick a Color pickColorDescription: Pick a background color for your pass. colorWhite: white @@ -34,7 +34,7 @@ privacyPolicy: Privacy Policy createdOnDevice: No personal data is sent to the Internet. qrCode: QR code is for verification only, with no personal info. openSourceTransparent: Source code is free and open for re-use/contributions on GitHub. -verifierLink: QR code verifier available at https://verifier.vaccine-ontario.ca +verifierLink: QR code verifier available at numPasses: receipts processed since Sept 2, 2021 demo: Video Demo whatsnew: What's New From e1ab60485882bfad9cfe5c0b9185f90838d968b3 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Thu, 23 Sep 2021 17:20:21 -0400 Subject: [PATCH 13/56] 1.9.3 - verbiage change and fix janssen photo color issue --- public/locales/en/common.yml | 2 +- src/photo.ts | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/public/locales/en/common.yml b/public/locales/en/common.yml index 76e72fa..54776ad 100644 --- a/public/locales/en/common.yml +++ b/public/locales/en/common.yml @@ -1,5 +1,5 @@ title: Vaccination Receipt to Wallet -subtitle: This tool converts your vaccination receipt from Ontario Ministry of Health to an Apple Wallet pass for easy access in the interim. +subtitle: This utility (created by volunteers) converts your vaccination receipt from Ontario Ministry of Health to an Apple Wallet pass for easy access in the interim. subtitle2: Once Ontario's official QR code is released on Oct 22, you will be able to update your Apple Wallet pass by visiting this site again. update1Date: Sep 23 Updates update1: Thanks so much for all the encouragements and suggestions to make this better. We plan to keep enhancing this to help more Canadians. Stay tuned! diff --git a/src/photo.ts b/src/photo.ts index 4982efe..2edc3fa 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -89,11 +89,6 @@ export class Photo { const body = document.getElementById('pass-image'); body.hidden = false; - if (payload.receipt.numDoses > 1) - body.style.backgroundColor = 'green'; - else - body.style.backgroundColor = 'orangered'; - const name = payload.receipt.name; const dateOfBirth = payload.receipt.dateOfBirth; const vaccineName = payload.receipt.vaccineName; @@ -104,14 +99,12 @@ export class Photo { if (vaccineName.includes('MODERNA')) vaccineNameProper = 'Moderna (SpikeVax)' - // vaccineNameProper = 'Pfizer (Comirnaty)' if (vaccineName.includes('ASTRAZENECA')) vaccineNameProper = 'AstraZeneca (Vaxzevria)' let doseVaccine = "#" + String(payload.receipt.numDoses) + ": " + vaccineNameProper; - document.getElementById('vaccineName').innerText = doseVaccine; document.getElementById('vaccinationDate').innerText = payload.receipt.vaccinationDate; document.getElementById('organization').innerText = payload.receipt.organization; From 513fea2df2dba748ae1fcc30fe3c9b6097ceed29 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Thu, 23 Sep 2021 19:15:24 -0400 Subject: [PATCH 14/56] 1.9.4 - color fix for photo part 2 --- components/Page.tsx | 2 +- src/photo.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/Page.tsx b/components/Page.tsx index 9e994de..8af3266 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
    Last updated: 2021-09-23 (v1.9.2)
    +
    Last updated: 2021-09-23 (v1.9.4)
    diff --git a/src/photo.ts b/src/photo.ts index 2edc3fa..66a4cc0 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -88,6 +88,7 @@ export class Photo { // const body = domTree.getElementById('main'); const body = document.getElementById('pass-image'); body.hidden = false; + body.style.backgroundColor = payload.backgroundColor const name = payload.receipt.name; const dateOfBirth = payload.receipt.dateOfBirth; @@ -110,6 +111,7 @@ export class Photo { document.getElementById('organization').innerText = payload.receipt.organization; document.getElementById('name').innerText = payload.receipt.name; document.getElementById('dob').innerText = payload.receipt.dateOfBirth; + const codeWriter = new BrowserQRCodeSvgWriter(); const svg = codeWriter.write(qrCode.message,200,200); From c4b0fde7e10685ede2fbd328d6ea8cce587a8b5b Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 20:04:32 -0400 Subject: [PATCH 15/56] added component for nicer list bullets --- components/Bullet.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 components/Bullet.tsx diff --git a/components/Bullet.tsx b/components/Bullet.tsx new file mode 100644 index 0000000..59439bb --- /dev/null +++ b/components/Bullet.tsx @@ -0,0 +1,20 @@ +import {useTranslation} from 'next-i18next'; + +interface BulletProps { + text: string; +} + +function Bullet(props: BulletProps): JSX.Element { + const { t } = useTranslation(["index"]); + + return ( +
  • + + + + {props.text} +
  • + ) +} + +export default Bullet; \ No newline at end of file From 96605031c95b273ec69b7eff697883a0950c0d92 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 20:11:50 -0400 Subject: [PATCH 16/56] added more to FAQ and fixed spelling --- pages/faq.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pages/faq.tsx b/pages/faq.tsx index d894e80..320cf17 100644 --- a/pages/faq.tsx +++ b/pages/faq.tsx @@ -7,27 +7,29 @@ import Card from '../components/Card' function Faq(): JSX.Element { const { t } = useTranslation(['common', 'index', 'faq']); const questionList = [ - {description: 'Which version of iOS does this support?', answer: 'iOS 13.7 is the minimum at the moment. We are looking for adjustments for older iOSes, but it will take a bit of time.'}, - {description: "What are the supported browsers?", answer: 'For iPhones, only Safari is supported for importing to your Apple Wallet. For any other devices, we recommend that you save it as photo using your browser of choice. Broswers built internally into mobile apps (e.g. Facebook, Twitter, Instagram) are known to have issues.'}, - {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.'}, - {description: 'Who made this?', answer: 'The same group of volunteers (Billy Lo, Ryan Slobojan, Evert Timberg, Jason Liu, Anujan Mathisekaran, Lisa Discepola, Samantha Finn, Madison Pearce) who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.'}, + {description: 'Which version of iOS does this support?', answer: 'iOS 13.7 is the minimum at the moment. We are looking for adjustments for older iOS versions, but it will take a bit of time.'}, + {description: 'I\'m having issues with adding it to my iPhone 6.', answer: 'Unfortunately, the iPhone 6 supports up to iOS 12.5 while the minimum requirement is iOS 13.7. In the meantime you can try it on a computer or another device and save it as a photo.'}, + {description: "What are the supported browsers?", answer: 'For iPhones, only Safari is supported for importing to your Apple Wallet. For any other devices, we recommend that you save it as photo using your browser of choice. Browsers built internally into mobile apps (e.g. Facebook, Twitter, Instagram) are known to have issues.'}, + {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay or simply save it as a photo.'}, + {description: 'I have a Red/White OHIP card. Can I still use this tool?', answer: 'Yes you can! Just call the Provincial Vaccine Contact Centre at 1-833-943-3900. The call centre agent can email you a copy of the receipt.'}, + {description: 'I dont\'t have a health card. Can I still use this tool?', answer: 'First contact your local public health unit to verify your identity and receive a COVIDcovid ID/Personal Access Code. You can then call the Provincial Vaccine Contact Centre at 1-833-943-3900 to get an email copy of your receipt.'}, + {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.'}, {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, you will also be able to refresh what\'s in your Apple Wallet as well. More details will follow.'}, {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.'}, {description: 'How can organizations validate this QR code?', answer: 'Just aim your standard camera app (iPhone/Android) at the code, and it will bring up a web page that shows the verification result.'}, {description: 'Is this free and private?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.'}, - {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay.'}, {description: 'How about BC, Quebec and Alberta?', answer: 'We will be investigating BC shortly. If you are interested in contributing, email us at grassroots@vaccine-ontario.ca'}, - {description: 'How can I stay up-to-date on your progress?', answer: 'We will post regular updates on Twitter @grassroots_team.'}, - {description: 'I only have an emailed receipt (e.g. Red/White OHIP card users). Can I still use this tool?', answer: 'Not right now unfortunately. But we expect to be able to support that after the official app is released on 22 Oct.'}, - {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.'}, {description: 'How about Apple Watch?', answer: 'If you have iCloud sync enabled, you will see the pass on the watch too.'}, + {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.'}, + {description: 'Who made this?', answer: 'The same group of volunteers (Billy Lo, Ryan Slobojan, Evert Timberg, Jason Liu, Anujan Mathisekaran, Lisa Discepola, Samantha Finn, Madison Pearce) who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.'}, + {description: 'How can I stay up-to-date on your progress?', answer: 'We will post regular updates on Twitter @grassroots_team.'}, {description: 'I have more questions. Can you please help me?', answer: 'Sure. Just email us at grassroots@vaccine-ontario.ca.'} ]; return (

    {t('faq:heading')}

      From 4c21ed83ec21118940bd7b30c3213852b435a87b Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 20:12:07 -0400 Subject: [PATCH 17/56] created FAQ redirect card --- components/Form.tsx | 31 ++++++++++++++++++++++++++++++- public/locales/en/index.yml | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/components/Form.tsx b/components/Form.tsx index 10853f9..2f2b3c5 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -18,6 +18,7 @@ import {isChrome, isIOS, isIPad13, isMacOs, isSafari, deviceDetect, osName, osVe import * as Sentry from '@sentry/react'; import { counterReset } from 'html2canvas/dist/types/css/property-descriptors/counter-reset'; import { color } from 'html2canvas/dist/types/css/types/color'; +import Bullet from './Bullet'; function Form(): JSX.Element { @@ -114,9 +115,14 @@ function Form(): JSX.Element { inputFile.current.click(); } - async function gotoOntarioHealth() { + async function gotoOntarioHealth(e) { + e.preventDefault(); window.location.href = 'https://covid19.ontariohealth.ca'; } + async function goToFAQ(e) { + e.preventDefault(); + window.location.href = '/faq'; + } // Hide camera view async function hideCameraView() { @@ -440,6 +446,29 @@ function Form(): JSX.Element { )} }/> + + +

      Do you want to use this tool but...

      +
      +
        + + + + + +
      +
      + +
      + +      +
      + + }/> diff --git a/public/locales/en/index.yml b/public/locales/en/index.yml index 464a68e..a79d156 100644 --- a/public/locales/en/index.yml +++ b/public/locales/en/index.yml @@ -38,4 +38,5 @@ verifierLink: QR code verifier available at numPasses: receipts processed since Sept 2, 2021 demo: Video Demo whatsnew: What's New +experiencingIssues: Experiencing Issues? #hostedInEU: Hosted in the EU \ No newline at end of file From eaeca0dd9f0cc0e3fe7c98cdb63fbe10e7a7056d Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 20:27:52 -0400 Subject: [PATCH 18/56] FAQ touch ups --- components/Form.tsx | 3 +-- pages/faq.tsx | 1 + public/locales/en/index.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 2f2b3c5..b7b4d36 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -451,12 +451,11 @@ function Form(): JSX.Element {

      Do you want to use this tool but...

      -
        +
          -
      diff --git a/pages/faq.tsx b/pages/faq.tsx index 320cf17..b07e04b 100644 --- a/pages/faq.tsx +++ b/pages/faq.tsx @@ -13,6 +13,7 @@ function Faq(): JSX.Element { {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay or simply save it as a photo.'}, {description: 'I have a Red/White OHIP card. Can I still use this tool?', answer: 'Yes you can! Just call the Provincial Vaccine Contact Centre at 1-833-943-3900. The call centre agent can email you a copy of the receipt.'}, {description: 'I dont\'t have a health card. Can I still use this tool?', answer: 'First contact your local public health unit to verify your identity and receive a COVIDcovid ID/Personal Access Code. You can then call the Provincial Vaccine Contact Centre at 1-833-943-3900 to get an email copy of your receipt.'}, + {description: 'I\'m seeing an error message saying “Failed byte range verification." What do I do?', answer: 'If you see this error then please try re-downloading your receipt from the provincial proof-of-vaccination portal and trying again. We have received reports from some people that this has resolved the problem for them.'}, {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.'}, {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, you will also be able to refresh what\'s in your Apple Wallet as well. More details will follow.'}, {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.'}, diff --git a/public/locales/en/index.yml b/public/locales/en/index.yml index a79d156..8a56940 100644 --- a/public/locales/en/index.yml +++ b/public/locales/en/index.yml @@ -38,5 +38,5 @@ verifierLink: QR code verifier available at numPasses: receipts processed since Sept 2, 2021 demo: Video Demo whatsnew: What's New -experiencingIssues: Experiencing Issues? +questions: Have Questions? #hostedInEU: Hosted in the EU \ No newline at end of file From b38540a0bc845b11998d2a4b539cb17a9a04b8e2 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Thu, 23 Sep 2021 21:19:37 -0400 Subject: [PATCH 19/56] 1.9.5 --- components/Page.tsx | 2 +- pages/index.tsx | 3 ++- src/photo.ts | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/components/Page.tsx b/components/Page.tsx index 8af3266..8193e5c 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
      Last updated: 2021-09-23 (v1.9.4)
      +
      Last updated: 2021-09-23 (v1.9.5)
      diff --git a/pages/index.tsx b/pages/index.tsx index 13ad07a..ddbf32c 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -11,7 +11,8 @@ import { useEffect, useState } from 'react'; function Index(): JSX.Element { const { t } = useTranslation(['common', 'index', 'errors']); - const [warning, setWarning] = useState("If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt.") + const [warning, setWarning] = useState("") + // If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt const title = 'Grassroots - Ontario vaccination receipt to your Apple wallet'; const description = 'Stores it on iPhone with a QR code for others to validate in a privacy respecting way.'; diff --git a/src/photo.ts b/src/photo.ts index 66a4cc0..721158d 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -73,9 +73,12 @@ export class Photo { if (responseJson["result"] != 'OK') return Promise.reject(); + const encodedUri = encodeURI(`serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`); + const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; + // Create QR Code Object const qrCode: QrCode = { - message: `${verifierHost}/verify?serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`, + message: qrCodeUrl, format: QrFormat.PKBarcodeFormatQR, messageEncoding: Encoding.iso88591, // altText : payload.rawData From aa1ea4a50726e61580dc3e4762d29870a733874c Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 23 Sep 2021 22:09:48 -0400 Subject: [PATCH 20/56] more FAQ changes --- components/Form.tsx | 2 +- pages/faq.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index b7b4d36..bc3277d 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -447,7 +447,7 @@ function Form(): JSX.Element { }/> -

      Do you want to use this tool but...

      diff --git a/pages/faq.tsx b/pages/faq.tsx index b07e04b..31954a6 100644 --- a/pages/faq.tsx +++ b/pages/faq.tsx @@ -14,15 +14,15 @@ function Faq(): JSX.Element { {description: 'I have a Red/White OHIP card. Can I still use this tool?', answer: 'Yes you can! Just call the Provincial Vaccine Contact Centre at 1-833-943-3900. The call centre agent can email you a copy of the receipt.'}, {description: 'I dont\'t have a health card. Can I still use this tool?', answer: 'First contact your local public health unit to verify your identity and receive a COVIDcovid ID/Personal Access Code. You can then call the Provincial Vaccine Contact Centre at 1-833-943-3900 to get an email copy of your receipt.'}, {description: 'I\'m seeing an error message saying “Failed byte range verification." What do I do?', answer: 'If you see this error then please try re-downloading your receipt from the provincial proof-of-vaccination portal and trying again. We have received reports from some people that this has resolved the problem for them.'}, - {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text.'}, - {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, you will also be able to refresh what\'s in your Apple Wallet as well. More details will follow.'}, + {description: 'What does the colour of the Apple Wallet pass mean?', answer: 'Dose 1 is shown as Orange; dose 2+ in green for easy differentiation without reading the text. For the Janssen (Johnson & Johnson) vaccine, dose 1 is shown as green.'}, + {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, Once the official QR code from the province is available, please come back to this site and you will be able to generate a new vaccination receipt which uses that new QR code'}, {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.'}, - {description: 'How can organizations validate this QR code?', answer: 'Just aim your standard camera app (iPhone/Android) at the code, and it will bring up a web page that shows the verification result.'}, + {description: 'How can organizations validate this QR code?', answer: 'You can use our verifier app at verifier.vaccine-ontario.ca to verify these passes quickly if you are a business - you should also be able to use any normal QR code scanner to scan this code and it will take you to a verification site which tells you whether the receipt is valid or not'}, {description: 'Is this free and private?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.'}, {description: 'How about BC, Quebec and Alberta?', answer: 'We will be investigating BC shortly. If you are interested in contributing, email us at grassroots@vaccine-ontario.ca'}, {description: 'How about Apple Watch?', answer: 'If you have iCloud sync enabled, you will see the pass on the watch too.'}, {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.'}, - {description: 'Who made this?', answer: 'The same group of volunteers (Billy Lo, Ryan Slobojan, Evert Timberg, Jason Liu, Anujan Mathisekaran, Lisa Discepola, Samantha Finn, Madison Pearce) who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.'}, + {description: 'Who made this?', answer: 'The same group of volunteers who created the all-in-one vaccine appointment finding tool at vaccine-ontario.ca.'}, {description: 'How can I stay up-to-date on your progress?', answer: 'We will post regular updates on Twitter @grassroots_team.'}, {description: 'I have more questions. Can you please help me?', answer: 'Sure. Just email us at grassroots@vaccine-ontario.ca.'} ]; From 98c60aa3e79092e5c5c291fcf6e9d2cc077a1736 Mon Sep 17 00:00:00 2001 From: Samuel Yeung Date: Fri, 24 Sep 2021 01:53:16 -0400 Subject: [PATCH 21/56] enable non-iOS device to add to wallet with warning message --- components/Form.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/Form.tsx b/components/Form.tsx index 10853f9..b2d48f6 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -43,6 +43,7 @@ function Form(): JSX.Element { const [isDisabledAppleWallet, setIsDisabledAppleWallet] = useState(false); const [errorMessages, _setErrorMessages] = useState>([]); + const [warningMessages, _setWarningMessages] = useState>([]); const hitcountHost = 'https://stats.vaccine-ontario.ca'; @@ -84,6 +85,15 @@ function Form(): JSX.Element { _setErrorMessages(Array.from(new Set([...errorMessages, translation !== message ? translation : message]))); }; + const setWarningMessage = (message: string) => { + if (message == undefined) { + return; + } + + const translation = t('errors:'.concat(message)); + _setWarningMessages(Array.from(new Set([...warningMessages, translation !== message ? translation : message]))); + } + const deleteErrorMessage = (message: string) =>{ console.log(errorMessages) _setErrorMessages(errorMessages.filter(item => item !== message)) @@ -328,6 +338,10 @@ function Form(): JSX.Element { setErrorMessage('Sorry, only Safari can be used to add a Wallet Pass on iOS'); setIsDisabledAppleWallet(true); console.log('not safari') + } else if (!isIOS) { + setWarningMessage('Only Safari is officially supported at the moment. ' + + 'Please download a compitable apps on other platform to open .pkpass'); + setIsDisabledAppleWallet(false); } } @@ -438,6 +452,9 @@ function Form(): JSX.Element { {errorMessages.map((message, i) => )} + {warningMessages.map((message, i) => + + )}
      }/> @@ -446,4 +463,4 @@ function Form(): JSX.Element { ) } -export default Form; \ No newline at end of file +export default Form; From 8c91ccaac4ac5961c70342697bc1cdca1dbfeeb5 Mon Sep 17 00:00:00 2001 From: scottjw Date: Fri, 24 Sep 2021 09:03:14 -0400 Subject: [PATCH 22/56] pin cert --- src/process.ts | 51 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/process.ts b/src/process.ts index 92bc5c7..2d0ee99 100644 --- a/src/process.ts +++ b/src/process.ts @@ -41,14 +41,57 @@ async function loadPDF(signedPdfBuffer : ArrayBuffer): Promise { const certs = getCertificatesInfoFromPDF(signedPdfBuffer); const result = certs[0]; - const isClientCertificate = result.clientCertificate; - const issuedByEntrust = (result.issuedBy.organizationName == 'Entrust, Inc.'); - const issuedToOntarioHealth = (result.issuedTo.commonName == 'covid19signer.ontariohealth.ca'); + const refcert = '-----BEGIN CERTIFICATE-----\r\n'+ + 'MIIHNTCCBh2gAwIBAgIQanhJa+fBXT8GQ8QG/t9p4TANBgkqhkiG9w0BAQsFADCB\r\n'+ + 'ujELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsT\r\n'+ + 'H1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAy\r\n'+ + 'MDE0IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwG\r\n'+ + 'A1UEAxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxTTAeFw0y\r\n'+ + 'MTA1MjAxMzQxNTBaFw0yMjA2MTkxMzQxNDlaMIHTMQswCQYDVQQGEwJDQTEQMA4G\r\n'+ + 'A1UECBMHT250YXJpbzEQMA4GA1UEBxMHVG9yb250bzETMBEGCysGAQQBgjc8AgED\r\n'+ + 'EwJDQTEYMBYGCysGAQQBgjc8AgECEwdPbnRhcmlvMRcwFQYDVQQKEw5PbnRhcmlv\r\n'+ + 'IEhlYWx0aDEaMBgGA1UEDxMRR292ZXJubWVudCBFbnRpdHkxEzARBgNVBAUTCjE4\r\n'+ + 'LTA0LTIwMTkxJzAlBgNVBAMTHmNvdmlkMTlzaWduZXIub250YXJpb2hlYWx0aC5j\r\n'+ + 'YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2bD+Ng1RNYCNVVtEQ3\r\n'+ + 'zg8JKFvRWFFPIF/UTXGg3iArK1tKr1xtjx6OdFtwosHyo+3ksPRicc4KeuV6/QMF\r\n'+ + 'qiVJ5IOy9TSVImJsmONgFyEiak0dGYG5SeHiWwyaUvkniWd7U3wWEl4nOZuLAYu4\r\n'+ + '8ZLot8p8Q/UaNvAoNsRDv6YDGjL2yGHaXxi3Bb6XTQTLcevuEQeM6g1LtKyisZfB\r\n'+ + 'Q8TKThBq99EojwHfXIhddxbPKLeXvWJgK1TcL17UFIwx6ig74s0LyYqEPm8Oa8qR\r\n'+ + '+IesFUT9Liv7xhV+tU52wmNfDi4znmLvs5Cmh/vmcHKyhEbxhYqciWJocACth5ij\r\n'+ + 'E3kCAwEAAaOCAxowggMWMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFFoW3zt+jaHS\r\n'+ + 'pm1EV5hU4XD+mwO5MB8GA1UdIwQYMBaAFMP30LUqMK2vDZEhcDlU3byJcMc6MGgG\r\n'+ + 'CCsGAQUFBwEBBFwwWjAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5u\r\n'+ + 'ZXQwMwYIKwYBBQUHMAKGJ2h0dHA6Ly9haWEuZW50cnVzdC5uZXQvbDFtLWNoYWlu\r\n'+ + 'MjU2LmNlcjAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmVudHJ1c3QubmV0\r\n'+ + 'L2xldmVsMW0uY3JsMCkGA1UdEQQiMCCCHmNvdmlkMTlzaWduZXIub250YXJpb2hl\r\n'+ + 'YWx0aC5jYTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\r\n'+ + 'AQUFBwMCMEsGA1UdIAREMEIwNwYKYIZIAYb6bAoBAjApMCcGCCsGAQUFBwIBFhto\r\n'+ + 'dHRwczovL3d3dy5lbnRydXN0Lm5ldC9ycGEwBwYFZ4EMAQEwggF+BgorBgEEAdZ5\r\n'+ + 'AgQCBIIBbgSCAWoBaAB3AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFcwO+UmFXWidDd\r\n'+ + 'AAABeYoCz+MAAAQDAEgwRgIhAKGKAoZMzwkh/3sZXq6vtEYhoYHfZzsjh9jqZvfS\r\n'+ + 'xQVZAiEAmJu/ftbkNFBr8751Z9wA2dpI0Qt+LoeL1TJQ833Kdg4AdQDfpV6raIJP\r\n'+ + 'H2yt7rhfTj5a6s2iEqRqXo47EsAgRFwqcwAAAXmKAs/cAAAEAwBGMEQCICsD/Vj+\r\n'+ + 'ypZeHhesMyv/TkS5ftQjqyIaAFTL/02Gtem4AiBcWdPQspH3vfzZr4LO9z4u5jTg\r\n'+ + 'Psfm5PZr66tI7yASrAB2AEalVet1+pEgMLWiiWn0830RLEF0vv1JuIWr8vxw/m1H\r\n'+ + 'AAABeYoC0WkAAAQDAEcwRQIgTL5F11+7KhQ60jnODm9AkyvXRLY32Mj6tgudRAXO\r\n'+ + 'y7UCIQDd/dU+Ax1y15yiAA5xM+bWJ7T+Ztd99SD1lw/o8fEmOjANBgkqhkiG9w0B\r\n'+ + 'AQsFAAOCAQEAlpV3RoNvnhDgd2iFSF39wytf1R6/0u5FdL7eIkYNfnkqXu9Ux9cO\r\n'+ + '/OeaGAFMSzaDPA8Xt9A0HqkEbh1pr7UmZVqBwDr4a7gczvt7+HFJRn//Q2fwhmaw\r\n'+ + 'vXTLLxcAPQF00G6ySsc9MUbsArh6AVhMf9tSXgNaTDj3X3UyYDfR+G8H9eVG/LPp\r\n'+ + '34QV/8uvPUFXGj6MjdQysx6YG+K3mae0GEVpODEl4MiceEFZ7v4CPA6pFNadijRF\r\n'+ + '6tdXky2psuo7VXfnE2WIlahKr56x+8R6To5pcWglKTywTqvCbnKRRVZhXXYo3Awd\r\n'+ + '8h9+TbL3ACHDqA4fi5sAbZ7nMXp8RK4o5A==\r\n'+ + '-----END CERTIFICATE-----'; + + const issuedpemCertificate = ( result.pemCertificate.trim() == refcert.trim()); + + console.log(`pdf is signed by this cert ${result.pemCertificate.trim()}`); + console.log(issuedpemCertificate); console.log(`PDF is signed by ${result.issuedBy.organizationName}, issued to ${result.issuedTo.commonName}`); // const bypass = window.location.href.includes('grassroots2'); - if ((isClientCertificate && issuedByEntrust && issuedToOntarioHealth)) { + if (( issuedpemCertificate )) { console.log('getting receipt details inside PDF'); const receipt = await getPdfDetails(signedPdfBuffer); // console.log(JSON.stringify(receipt, null, 2)); From 559eab3df6ef9f8e0b52da5c018d1cad3a98a742 Mon Sep 17 00:00:00 2001 From: scottjw Date: Fri, 24 Sep 2021 09:20:48 -0400 Subject: [PATCH 23/56] comment console log calls --- src/process.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/process.ts b/src/process.ts index 2d0ee99..572d615 100644 --- a/src/process.ts +++ b/src/process.ts @@ -85,14 +85,14 @@ async function loadPDF(signedPdfBuffer : ArrayBuffer): Promise { const issuedpemCertificate = ( result.pemCertificate.trim() == refcert.trim()); - console.log(`pdf is signed by this cert ${result.pemCertificate.trim()}`); - console.log(issuedpemCertificate); - console.log(`PDF is signed by ${result.issuedBy.organizationName}, issued to ${result.issuedTo.commonName}`); + //console.log(`pdf is signed by this cert ${result.pemCertificate.trim()}`); + //console.log(issuedpemCertificate); + //console.log(`PDF is signed by ${result.issuedBy.organizationName}, issued to ${result.issuedTo.commonName}`); // const bypass = window.location.href.includes('grassroots2'); if (( issuedpemCertificate )) { - console.log('getting receipt details inside PDF'); + //console.log('getting receipt details inside PDF'); const receipt = await getPdfDetails(signedPdfBuffer); // console.log(JSON.stringify(receipt, null, 2)); return Promise.resolve(receipt); From 81fa8bbe728663f459cd9e9837b1f7b0af171308 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Fri, 24 Sep 2021 10:12:21 -0400 Subject: [PATCH 24/56] Log failed cert validations --- src/process.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/process.ts b/src/process.ts index 572d615..0191ff1 100644 --- a/src/process.ts +++ b/src/process.ts @@ -1,7 +1,7 @@ import {PayloadBody, Receipt} from "./payload"; import * as PdfJS from 'pdfjs-dist' import {COLORS} from "./colors"; -import { getCertificatesInfoFromPDF } from "@ninja-labs/verify-pdf"; // ES6 +import { getCertificatesInfoFromPDF } from "@ninja-labs/verify-pdf"; // ES6 import * as Sentry from '@sentry/react'; import { TextItem } from "pdfjs-dist/types/display/api"; @@ -83,12 +83,14 @@ async function loadPDF(signedPdfBuffer : ArrayBuffer): Promise { '8h9+TbL3ACHDqA4fi5sAbZ7nMXp8RK4o5A==\r\n'+ '-----END CERTIFICATE-----'; - const issuedpemCertificate = ( result.pemCertificate.trim() == refcert.trim()); - + const pdfCert = result.pemCertificate.trim(); + const pdfOrg = result.issuedBy.organizationName; + const issuedpemCertificate = (pdfCert == refcert.trim()); + //console.log(`pdf is signed by this cert ${result.pemCertificate.trim()}`); //console.log(issuedpemCertificate); //console.log(`PDF is signed by ${result.issuedBy.organizationName}, issued to ${result.issuedTo.commonName}`); - + // const bypass = window.location.href.includes('grassroots2'); if (( issuedpemCertificate )) { @@ -98,6 +100,13 @@ async function loadPDF(signedPdfBuffer : ArrayBuffer): Promise { return Promise.resolve(receipt); } else { + // According to the Sentry docs, this can be up to 8KB in size + // https://develop.sentry.dev/sdk/data-handling/#variable-size + Sentry.setContext("certificate", { + pdfCert: pdfCert, + pdfOrg: pdfOrg, + }); + Sentry.captureMessage('Certificate validation failed'); console.error('invalid certificate'); return Promise.reject(`invalid certificate + ${JSON.stringify(result)}`); } @@ -142,11 +151,11 @@ async function getPdfDetails(fileBuffer: ArrayBuffer): Promise { if (value.includes('Product name')) { vaccineName = (content.items[i+1] as TextItem).str; vaccineName = vaccineName.split(' ')[0]; - } + } if (value.includes('Date of birth')) dateOfBirth = (content.items[i+1] as TextItem).str; if (value.includes('Authorized organization')) - organization = (content.items[i+1] as TextItem).str; + organization = (content.items[i+1] as TextItem).str; if (value.includes('You have received')) numDoses = Number(value.split(' ')[3]); } From a09103797b83f750763658e853b9092a31bc6f81 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Fri, 24 Sep 2021 12:17:29 -0400 Subject: [PATCH 25/56] Fix URI encoding for indivual params --- src/pass.ts | 4 ++-- src/photo.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pass.ts b/src/pass.ts index ec831eb..7c47cd9 100644 --- a/src/pass.ts +++ b/src/pass.ts @@ -130,9 +130,9 @@ export class PassData { return Promise.reject(); } - const encodedUri = encodeURI(`serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`); + const encodedUri = encodeURI(`serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`); const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; - + // console.log(qrCodeUrl); // Create QR Code Object diff --git a/src/photo.ts b/src/photo.ts index 721158d..3084197 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -70,10 +70,10 @@ export class Photo { console.log(JSON.stringify(responseJson,null,2)); - if (responseJson["result"] != 'OK') + if (responseJson["result"] != 'OK') return Promise.reject(); - const encodedUri = encodeURI(`serialNumber=${payload.serialNumber}&vaccineName=${payload.receipt.vaccineName}&vaccinationDate=${payload.receipt.vaccinationDate}&organization=${payload.receipt.organization}&dose=${payload.receipt.numDoses}`); + const encodedUri = encodeURI(`serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`); const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; // Create QR Code Object @@ -102,25 +102,25 @@ export class Photo { vaccineNameProper = 'Pfizer (Comirnaty)' if (vaccineName.includes('MODERNA')) - vaccineNameProper = 'Moderna (SpikeVax)' + vaccineNameProper = 'Moderna (SpikeVax)' if (vaccineName.includes('ASTRAZENECA')) - vaccineNameProper = 'AstraZeneca (Vaxzevria)' + vaccineNameProper = 'AstraZeneca (Vaxzevria)' let doseVaccine = "#" + String(payload.receipt.numDoses) + ": " + vaccineNameProper; - + document.getElementById('vaccineName').innerText = doseVaccine; document.getElementById('vaccinationDate').innerText = payload.receipt.vaccinationDate; document.getElementById('organization').innerText = payload.receipt.organization; document.getElementById('name').innerText = payload.receipt.name; document.getElementById('dob').innerText = payload.receipt.dateOfBirth; - + const codeWriter = new BrowserQRCodeSvgWriter(); const svg = codeWriter.write(qrCode.message,200,200); svg.setAttribute('style','background-color: white'); document.getElementById('qrcode').appendChild(svg); - + const blobPromise = toBlob(body); return blobPromise; } catch (e) { From 0650e89a1fc5fae5c7047101dafa3821b74099ec Mon Sep 17 00:00:00 2001 From: Samuel Yeung Date: Fri, 24 Sep 2021 13:18:15 -0400 Subject: [PATCH 26/56] reword warning message --- components/Form.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index b2d48f6..0908da8 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -339,8 +339,8 @@ function Form(): JSX.Element { setIsDisabledAppleWallet(true); console.log('not safari') } else if (!isIOS) { - setWarningMessage('Only Safari is officially supported at the moment. ' + - 'Please download a compitable apps on other platform to open .pkpass'); + setWarningMessage('Only Safari on iOS is officially supported for Wallet import at the moment - ' + + 'for other platforms, please ensure you have an application which can open Apple Wallet .pkpass files'); setIsDisabledAppleWallet(false); } } From 6aafd987b6a0792e7a31db7cc4fb5f0d807a92cc Mon Sep 17 00:00:00 2001 From: Samuel Yeung Date: Fri, 24 Sep 2021 13:19:10 -0400 Subject: [PATCH 27/56] check warning message for null or empty as well in addition to undefined --- components/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Form.tsx b/components/Form.tsx index 0908da8..b09a37b 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -86,7 +86,7 @@ function Form(): JSX.Element { }; const setWarningMessage = (message: string) => { - if (message == undefined) { + if (!message) { return; } From cd5fd9a8b6eaae645b4ee5ca282beca4990c56e0 Mon Sep 17 00:00:00 2001 From: Samuel Yeung Date: Fri, 24 Sep 2021 13:19:33 -0400 Subject: [PATCH 28/56] check error message for null or empty as well in addition to undefined --- components/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Form.tsx b/components/Form.tsx index b09a37b..f112734 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -77,7 +77,7 @@ function Form(): JSX.Element { // Check if there is a translation and replace message accordingly const setErrorMessage = (message: string) => { - if (message == undefined) { + if (!message) { return; } From 7c22310356666bdcd988e6a7d22b814a82ab1412 Mon Sep 17 00:00:00 2001 From: Ryan Slobojan Date: Fri, 24 Sep 2021 15:15:27 -0400 Subject: [PATCH 29/56] Fix double-encoding breaking generated URLs * We encoded spaces once to %20, and then a second time to %2520 :( --- src/pass.ts | 2 +- src/photo.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pass.ts b/src/pass.ts index 7c47cd9..806630c 100644 --- a/src/pass.ts +++ b/src/pass.ts @@ -130,7 +130,7 @@ export class PassData { return Promise.reject(); } - const encodedUri = encodeURI(`serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`); + const encodedUri = `serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`; const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; // console.log(qrCodeUrl); diff --git a/src/photo.ts b/src/photo.ts index 3084197..496f859 100644 --- a/src/photo.ts +++ b/src/photo.ts @@ -73,7 +73,7 @@ export class Photo { if (responseJson["result"] != 'OK') return Promise.reject(); - const encodedUri = encodeURI(`serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`); + const encodedUri = `serialNumber=${encodeURIComponent(payload.serialNumber)}&vaccineName=${encodeURIComponent(payload.receipt.vaccineName)}&vaccinationDate=${encodeURIComponent(payload.receipt.vaccinationDate)}&organization=${encodeURIComponent(payload.receipt.organization)}&dose=${encodeURIComponent(payload.receipt.numDoses)}`; const qrCodeUrl = `${verifierHost}/verify?${encodedUri}`; // Create QR Code Object From 48c120706a485d42e1243339e503a4e8689437bc Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Fri, 24 Sep 2021 19:07:00 -0400 Subject: [PATCH 30/56] turned single warning message to array added iphone safari banner --- pages/index.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index ddbf32c..fb903f3 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -7,11 +7,28 @@ import Card from '../components/Card'; import Page from '../components/Page'; import Alert from '../components/Alert'; import { useEffect, useState } from 'react'; +import { isIOS, isSafari } from 'react-device-detect'; + function Index(): JSX.Element { const { t } = useTranslation(['common', 'index', 'errors']); - const [warning, setWarning] = useState("") + const [warningMessages, _setWarningMessages] = useState>(["If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt"]); + + const setWarningMessage = (message: string) => { + if (!message) return; + + const translation = t('errors:'.concat(message)); + _setWarningMessages(Array.from(new Set([...warningMessages, translation !== message ? translation : message]))); + }; + + const deleteWarningMessage = (message: string) => _setWarningMessages(warningMessages.filter(item => item !== message)); + + useEffect(() => { + if ( !isSafari) setWarningMessage("iPhone users, only Safari is supported at the moment. Please switch to Safari to prevent any unexpected errors.") + }) + + // If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt const title = 'Grassroots - Ontario vaccination receipt to your Apple wallet'; @@ -44,7 +61,9 @@ function Index(): JSX.Element { /> - {warning && setWarning(undefined)} message={warning} />} + {warningMessages.map((message, i) => + deleteWarningMessage(message)} /> + )}

      {t('common:subtitle')}


      {t('common:subtitle2')}


      {t('common:update1Date')} - {t('common:update1')}


      {t('common:continueSpirit')}

      }/> From 80e3ee684954ebdf64d18c74c59bedb80d33b0b3 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Fri, 24 Sep 2021 19:08:18 -0400 Subject: [PATCH 31/56] 1.9.6 - brief updates for users for Sept 24 --- components/Page.tsx | 2 +- pages/index.tsx | 15 ++++++++++++++- public/locales/en/common.yml | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/components/Page.tsx b/components/Page.tsx index 8193e5c..7819936 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
      Last updated: 2021-09-23 (v1.9.5)
      +
      Last updated: 2021-09-24 (v1.9.6)
      diff --git a/pages/index.tsx b/pages/index.tsx index ddbf32c..6c3ee98 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -46,7 +46,20 @@ function Index(): JSX.Element {
      {warning && setWarning(undefined)} message={warning} />}

      {t('common:subtitle')}


      {t('common:subtitle2')}


      {t('common:update1Date')} - {t('common:update1')}


      {t('common:continueSpirit')}

      +

      {t('common:subtitle')}


      {t('common:subtitle2')}


      + Sept 24 updates - Improvements: +
      +
      +
        +
      • Added date of birth to the pass (to save more time for staff)
      • +
      • Corrected the color of Janssen receipts
      • +
      • Corrected 'Not Found' error for some users
      • +
      • Reduced # of errors (thanks for your patience, traffic grew 100x in 3 days, we are working hard to keep things smooth without line-ups.)
      • +

      + If you need to regenerate your pass, you can skip Step 1 altogether. This will reduce the province's workload too. 🙏 +
      +
      +

      {t('common:continueSpirit')}

      }/>
      diff --git a/public/locales/en/common.yml b/public/locales/en/common.yml index 54776ad..958c209 100644 --- a/public/locales/en/common.yml +++ b/public/locales/en/common.yml @@ -3,7 +3,7 @@ subtitle: This utility (created by volunteers) converts your vaccination receipt subtitle2: Once Ontario's official QR code is released on Oct 22, you will be able to update your Apple Wallet pass by visiting this site again. update1Date: Sep 23 Updates update1: Thanks so much for all the encouragements and suggestions to make this better. We plan to keep enhancing this to help more Canadians. Stay tuned! -continueSpirit: Continuing the spirit of ❤️ @VaxHuntersCanada ❤️ beyond vax hunting. 390K receipts processed already, thanks for keeping the community safe! +continueSpirit: Continuing the spirit of ❤️ @VaxHuntersCanada ❤️. 700K receipts processed already, thanks for keeping the community safe! privacyPolicy: Privacy Policy donate: Sponsor gitHub: GitHub From 4c2a68d6e07e011ed24de4113b568dd8fe629b9a Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Fri, 24 Sep 2021 21:47:26 -0400 Subject: [PATCH 32/56] updated build # --- package.json | 2 +- src/sentry.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5a35716..5ba68a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grassroots_covidpass", - "version": "1.9.0", + "version": "1.9.6", "author": "Billy Lo ", "license": "MIT", "private": false, diff --git a/src/sentry.ts b/src/sentry.ts index 23a73ee..ad5118d 100644 --- a/src/sentry.ts +++ b/src/sentry.ts @@ -3,7 +3,7 @@ import { Integrations } from '@sentry/tracing'; export const initSentry = () => { SentryModule.init({ - release: 'grassroots_covidpass@1.8.0', // App version. Needs to be manually updated as we go unless we make the build smarter + release: 'grassroots_covidpass@1.9.6', // App version. Needs to be manually updated as we go unless we make the build smarter dsn: 'https://51370d7af0994761b465bc148129c1de@o997324.ingest.sentry.io/5955697', integrations: [ new Integrations.BrowserTracing(), From 1e323d322b3f7a09672b6e90a3a88a666b8923ac Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Sat, 25 Sep 2021 01:15:35 -0400 Subject: [PATCH 33/56] removed placeholder wraning messages --- pages/index.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index d6df219..89b5f71 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -7,13 +7,13 @@ import Card from '../components/Card'; import Page from '../components/Page'; import Alert from '../components/Alert'; import { useEffect, useState } from 'react'; -import { isIOS, isSafari } from 'react-device-detect'; +import { isIOS, isSafari, isAndroid} from 'react-device-detect'; function Index(): JSX.Element { const { t } = useTranslation(['common', 'index', 'errors']); - const [warningMessages, _setWarningMessages] = useState>(["If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt"]); + const [warningMessages, _setWarningMessages] = useState>([]); const setWarningMessage = (message: string) => { if (!message) return; @@ -24,9 +24,9 @@ function Index(): JSX.Element { const deleteWarningMessage = (message: string) => _setWarningMessages(warningMessages.filter(item => item !== message)); - useEffect(() => { - if ( !isSafari) setWarningMessage("iPhone users, only Safari is supported at the moment. Please switch to Safari to prevent any unexpected errors.") - }) + // useEffect(() => { + // if (!isSafari) setWarningMessage("iPhone users, only Safari is supported at the moment. Please switch to Safari to prevent any unexpected errors.") + // }) // If you previously created a vaccination receipt before Sept. 23rd and need to add your date of birth on your vaccination receipt, please reimport your Ministry of Health official vaccination receipt again below and the date of birth will now be visible on the created receipt From 24d3c69ff063bc83f4405e090c66b45043c85da2 Mon Sep 17 00:00:00 2001 From: Ryan Slobojan Date: Sat, 25 Sep 2021 21:47:48 -0400 Subject: [PATCH 34/56] Updated Apple Wallet PKPass to dynamic name * Changing filename should hopefully prevent duplication errors on some devices * Filename includes name, dose, and vaccine to make path collisions less likely --- components/Form.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index bc3277d..1b1e125 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -228,20 +228,25 @@ function Form(): JSX.Element { try { if (file) { - console.log('> get payload'); + //console.log('> get payload'); payloadBody = await getPayloadBodyFromFile(file, color); - - console.log('> increment count'); + + const passName = payloadBody.receipt.name.replace(' ', '-'); + const vaxName = payloadBody.receipt.vaccineName.replace(' ', '-'); + const passDose = payloadBody.receipt.numDoses; + const covidPassFilename = `grassroots-receipt-${passName}-${vaxName}-${passDose}.pkpass`; + + //console.log('> increment count'); await incrementCount(); - console.log('> generatePass'); + //console.log('> generatePass'); let pass = await PassData.generatePass(payloadBody); - console.log('> create blob'); + //console.log('> create blob'); const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"}); - console.log('> save blob'); - saveAs(passBlob, 'covid.pkpass'); + //console.log(`> save blob as ${covidPassFilename}`); + saveAs(passBlob, covidPassFilename); setLoading(false); } From c47091684a0d12307a1f26a815d97f58b271dc07 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Sat, 25 Sep 2021 22:40:32 -0400 Subject: [PATCH 35/56] open ontario health link in new tab --- components/Form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Form.tsx b/components/Form.tsx index 9a904f9..b1d6c49 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -365,7 +365,7 @@ function Form(): JSX.Element { {t('index:visit')}  - + {t('index:ontarioHealth')}   From 3574b4490d4ddcc51bddccad07a5f5927d8f2c91 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Sat, 25 Sep 2021 23:09:46 -0400 Subject: [PATCH 36/56] 1.9.7 --- components/Form.tsx | 1 + components/Page.tsx | 2 +- package.json | 2 +- pages/faq.tsx | 4 +++- pages/index.tsx | 12 ++++-------- public/locales/en/common.yml | 2 +- public/locales/en/index.yml | 6 +++--- src/sentry.ts | 2 +- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 9a904f9..45dd967 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -474,6 +474,7 @@ function Form(): JSX.Element {

      Do you want to use this tool but...

        + diff --git a/components/Page.tsx b/components/Page.tsx index 7819936..b8df6b9 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
        Last updated: 2021-09-24 (v1.9.6)
        +
        Last updated: 2021-09-25 (v1.9.7)
      diff --git a/package.json b/package.json index 5ba68a7..99ab19b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grassroots_covidpass", - "version": "1.9.6", + "version": "1.9.7", "author": "Billy Lo ", "license": "MIT", "private": false, diff --git a/pages/faq.tsx b/pages/faq.tsx index 31954a6..ac53f39 100644 --- a/pages/faq.tsx +++ b/pages/faq.tsx @@ -10,6 +10,7 @@ function Faq(): JSX.Element { {description: 'Which version of iOS does this support?', answer: 'iOS 13.7 is the minimum at the moment. We are looking for adjustments for older iOS versions, but it will take a bit of time.'}, {description: 'I\'m having issues with adding it to my iPhone 6.', answer: 'Unfortunately, the iPhone 6 supports up to iOS 12.5 while the minimum requirement is iOS 13.7. In the meantime you can try it on a computer or another device and save it as a photo.'}, {description: "What are the supported browsers?", answer: 'For iPhones, only Safari is supported for importing to your Apple Wallet. For any other devices, we recommend that you save it as photo using your browser of choice. Browsers built internally into mobile apps (e.g. Facebook, Twitter, Instagram) are known to have issues.'}, + {description: "How is my private information handled?", answer: 'Your proof-of-vaccination PDF (and most of the information in it) never leaves your device, and does NOT get sent to our server - the only information we send and store is non-personally-identifiable information such as vaccine type, date, and which organization gave you the vaccine. We share your concern about personal data being stored and lost, which is why we chose not to store or send any of it to our servers so there is no chance of it being lost or leaked.'}, {description: 'Do you have plans for Android support?', answer: 'Yes. We are working with Google to gain access to the APIs required. Meanwhile, you can also use this tool to download an Apple Wallet pass and import that into Google Pay Wallet using apps such as Pass2Pay or simply save it as a photo.'}, {description: 'I have a Red/White OHIP card. Can I still use this tool?', answer: 'Yes you can! Just call the Provincial Vaccine Contact Centre at 1-833-943-3900. The call centre agent can email you a copy of the receipt.'}, {description: 'I dont\'t have a health card. Can I still use this tool?', answer: 'First contact your local public health unit to verify your identity and receive a COVIDcovid ID/Personal Access Code. You can then call the Provincial Vaccine Contact Centre at 1-833-943-3900 to get an email copy of your receipt.'}, @@ -18,7 +19,8 @@ function Faq(): JSX.Element { {description: 'Should I use the official provincial apps when they come out on 22nd October?', answer: 'YES. Once the official QR code from the province is available, Once the official QR code from the province is available, please come back to this site and you will be able to generate a new vaccination receipt which uses that new QR code'}, {description: 'How is the data on my vaccination receipt processed?', answer: 'It checks the receipt for an official signature from the province. If present, the receipt data is converted into Apple\'s format and then added into your iOS Wallet app.'}, {description: 'How can organizations validate this QR code?', answer: 'You can use our verifier app at verifier.vaccine-ontario.ca to verify these passes quickly if you are a business - you should also be able to use any normal QR code scanner to scan this code and it will take you to a verification site which tells you whether the receipt is valid or not'}, - {description: 'Is this free and private?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.'}, + {description: 'Can I use the same iPhone to store passes for my entire family?', answer: 'Yes.'}, + {description: 'Is this free and non-commercial?', answer: 'Similar to VaxHuntersCanada, there are no commerical interests. Just volunteers trying to do our part to help the community.'}, {description: 'How about BC, Quebec and Alberta?', answer: 'We will be investigating BC shortly. If you are interested in contributing, email us at grassroots@vaccine-ontario.ca'}, {description: 'How about Apple Watch?', answer: 'If you have iCloud sync enabled, you will see the pass on the watch too.'}, {description: 'Why have we taken time to build this?', answer: 'Gives Ontarians/organizations something easy to use (volunteered-developed, unofficial) until the official provincial app comes out in October.'}, diff --git a/pages/index.tsx b/pages/index.tsx index 89b5f71..2dd49d2 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -66,18 +66,14 @@ function Index(): JSX.Element { )}

      {t('common:subtitle')}


      {t('common:subtitle2')}


      - Sept 24 updates - Improvements: + Sept 25 evening updates - Improvements:

        -
      • Added date of birth to the pass (to save more time for staff)
      • -
      • Corrected the color of Janssen receipts
      • -
      • Corrected 'Not Found' error for some users
      • -
      • Reduced # of errors (thanks for your patience, traffic grew 100x in 3 days, we are working hard to keep things smooth without line-ups.)
      • +
      • Better support the use of .pkpass files on non-iOS platforms (thx samuelyeungkc)
      • +
      • Improved multiple passes handling
      • +
      • Added FAQ on how critical data (name & date of birth) is protected and they stay private to you.

      - If you need to regenerate your pass, you can skip Step 1 altogether. This will reduce the province's workload too. 🙏 -
      -

      {t('common:continueSpirit')}

      }/> diff --git a/public/locales/en/common.yml b/public/locales/en/common.yml index 958c209..1e8d14d 100644 --- a/public/locales/en/common.yml +++ b/public/locales/en/common.yml @@ -3,7 +3,7 @@ subtitle: This utility (created by volunteers) converts your vaccination receipt subtitle2: Once Ontario's official QR code is released on Oct 22, you will be able to update your Apple Wallet pass by visiting this site again. update1Date: Sep 23 Updates update1: Thanks so much for all the encouragements and suggestions to make this better. We plan to keep enhancing this to help more Canadians. Stay tuned! -continueSpirit: Continuing the spirit of ❤️ @VaxHuntersCanada ❤️. 700K receipts processed already, thanks for keeping the community safe! +continueSpirit: Continuing the spirit of ❤️ @VaxHuntersCanada ❤️. 820K receipts processed already, thanks for keeping the community safe! privacyPolicy: Privacy Policy donate: Sponsor gitHub: GitHub diff --git a/public/locales/en/index.yml b/public/locales/en/index.yml index 8a56940..fd0f8bd 100644 --- a/public/locales/en/index.yml +++ b/public/locales/en/index.yml @@ -31,9 +31,9 @@ dataPrivacyDescription: | Press the "Add to Wallet" below to import data into Wallet. iAcceptThe: I accept the privacyPolicy: Privacy Policy -createdOnDevice: No personal data is sent to the Internet. -qrCode: QR code is for verification only, with no personal info. -openSourceTransparent: Source code is free and open for re-use/contributions on GitHub. +createdOnDevice: The receipt data is processed on your device only - no personally-identifiable information is sent to our servers +qrCode: QR code is for verification only. It does not contain your name or date of birth. +openSourceTransparent: Source code is open for re-use/contributions on GitHub. verifierLink: QR code verifier available at numPasses: receipts processed since Sept 2, 2021 demo: Video Demo diff --git a/src/sentry.ts b/src/sentry.ts index ad5118d..d559f7b 100644 --- a/src/sentry.ts +++ b/src/sentry.ts @@ -3,7 +3,7 @@ import { Integrations } from '@sentry/tracing'; export const initSentry = () => { SentryModule.init({ - release: 'grassroots_covidpass@1.9.6', // App version. Needs to be manually updated as we go unless we make the build smarter + release: 'grassroots_covidpass@1.9.7', // App version. Needs to be manually updated as we go unless we make the build smarter dsn: 'https://51370d7af0994761b465bc148129c1de@o997324.ingest.sentry.io/5955697', integrations: [ new Integrations.BrowserTracing(), From 8d8d6376451a2750672e0935ef9041ed73434a97 Mon Sep 17 00:00:00 2001 From: Billy Lo Date: Sat, 25 Sep 2021 23:23:25 -0400 Subject: [PATCH 37/56] 1.9.8 - layout fixes to Step 3 bullets --- components/Form.tsx | 2 +- components/Page.tsx | 2 +- public/locales/en/index.yml | 4 ++-- src/sentry.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index ca75963..b0bbc46 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -431,7 +431,7 @@ function Form(): JSX.Element {
        - + {verifierLink()} {passCount && } diff --git a/components/Page.tsx b/components/Page.tsx index b8df6b9..8b1dfbd 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -34,7 +34,7 @@ function Page(props: PageProps): JSX.Element { {t('common:gitHub')} {t('common:returnToMainSite')} -
        Last updated: 2021-09-25 (v1.9.7)
        +
        Last updated: 2021-09-25 (v1.9.8)
      diff --git a/public/locales/en/index.yml b/public/locales/en/index.yml index fd0f8bd..15d2411 100644 --- a/public/locales/en/index.yml +++ b/public/locales/en/index.yml @@ -31,8 +31,8 @@ dataPrivacyDescription: | Press the "Add to Wallet" below to import data into Wallet. iAcceptThe: I accept the privacyPolicy: Privacy Policy -createdOnDevice: The receipt data is processed on your device only - no personally-identifiable information is sent to our servers -qrCode: QR code is for verification only. It does not contain your name or date of birth. +createdOnDevice: Your receipt is processed on your device only. +piiNotSent: No personally-identifiable information is sent to servers openSourceTransparent: Source code is open for re-use/contributions on GitHub. verifierLink: QR code verifier available at numPasses: receipts processed since Sept 2, 2021 diff --git a/src/sentry.ts b/src/sentry.ts index d559f7b..84ea4d7 100644 --- a/src/sentry.ts +++ b/src/sentry.ts @@ -3,7 +3,7 @@ import { Integrations } from '@sentry/tracing'; export const initSentry = () => { SentryModule.init({ - release: 'grassroots_covidpass@1.9.7', // App version. Needs to be manually updated as we go unless we make the build smarter + release: 'grassroots_covidpass@1.9.8', // App version. Needs to be manually updated as we go unless we make the build smarter dsn: 'https://51370d7af0994761b465bc148129c1de@o997324.ingest.sentry.io/5955697', integrations: [ new Integrations.BrowserTracing(), From 5bc6c93d13c4abc602852df8a0ec0df87bed44cc Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sun, 26 Sep 2021 08:54:09 -0400 Subject: [PATCH 38/56] Block buttons when requests are running --- components/Form.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index b0bbc46..67bf46c 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -441,12 +441,12 @@ function Form(): JSX.Element {
      -      - From 7fc971ab79d4caed4e0f56c55198c83b3ca1ff57 Mon Sep 17 00:00:00 2001 From: Ryan Slobojan Date: Sun, 26 Sep 2021 19:05:02 -0400 Subject: [PATCH 39/56] Moved pass count from bottom of page to title for more visibility --- components/Form.tsx | 45 ++------------------------------------------- components/Page.tsx | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/components/Form.tsx b/components/Form.tsx index 67bf46c..80f4461 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -39,7 +39,6 @@ function Form(): JSX.Element { const [loading, setLoading] = useState(false); - const [passCount, setPassCount] = useState(''); const [generated, setGenerated] = useState(false); // this flag represents the file has been used to generate a pass const [isDisabledAppleWallet, setIsDisabledAppleWallet] = useState(false); @@ -48,34 +47,6 @@ function Form(): JSX.Element { const hitcountHost = 'https://stats.vaccine-ontario.ca'; - useEffect(() => { - if (passCount.length == 0) { - getPassCount(); - } - }, []); - - const getPassCount = async () => { - const hitCount = await getHitCount(); - setPassCount(hitCount); - }; - - async function getHitCount() { - - try { - const request = `${hitcountHost}/nocount?url=pass.vaccine-ontario.ca`; - - let response = await fetch(request); - const counter = await response.text(); - - return Promise.resolve(counter); - - } catch (e) { - console.error(e); - return Promise.reject(e); - } - - } - // Check if there is a translation and replace message accordingly const setErrorMessage = (message: string) => { if (!message) { @@ -193,31 +164,22 @@ function Form(): JSX.Element { } async function incrementCount() { - try { if (typeof generated == undefined || !generated) { const request = `${hitcountHost}/count?url=pass.vaccine-ontario.ca`; - console.log(request); + //console.log(request); let response = await fetch(request); - console.log(request); + //console.log(response); - const counter = await response.text(); // response count is not used intentionally so it always goes up by 1 only even if the server has changed - - let newPasscount = Number(passCount) + 1; - console.log(counter); - setPassCount(counter); setGenerated(true); - console.log(`new PassCount = ${newPasscount}`); - } } catch (e) { console.error(e); return Promise.reject(e); } - } // Add Pass to wallet @@ -434,9 +396,6 @@ function Form(): JSX.Element { {verifierLink()} - {passCount && } - - {/* */}
      diff --git a/components/Page.tsx b/components/Page.tsx index 8b1dfbd..36689eb 100644 --- a/components/Page.tsx +++ b/components/Page.tsx @@ -10,11 +10,41 @@ interface PageProps { function Page(props: PageProps): JSX.Element { const { t } = useTranslation('common'); + const [passCount, setPassCount] = useState(''); + + useEffect(() => { + if (passCount.length == 0) { + getPassCount(); + } + }, []); + + const getPassCount = async () => { + const hitCount = await getHitCount(); + setPassCount(hitCount); + }; + + async function getHitCount() { + + try { + const request = `${hitcountHost}/nocount?url=pass.vaccine-ontario.ca`; + + let response = await fetch(request); + const counter = await response.text(); + + return Promise.resolve(counter); + + } catch (e) { + console.error(e); + return Promise.reject(e); + } + } + + const displayPassCount = (passCount? ` - ${passCount.toLocaleString()} receipts processed to date!` : ''); return (
      - {t('common:title')} + {t('common:title')}{displayPassCount}