From e6731dbdfa84bc8e0730378d3e2cd1e3cddff41b Mon Sep 17 00:00:00 2001 From: jessikitty Date: Thu, 3 Sep 2026 14:43:03 +1000 Subject: [PATCH] Visitor sign in kiosk: multi-site, badge printing, WWCC expiry warnings, admin accounts with 2FA --- README.md | 24 +++++++++++++++ public/admin.html | 2 +- public/css/kiosk.css | 3 ++ public/index.html | 5 ++++ public/js/admin.js | 23 +++++++++++++-- public/js/kiosk.js | 5 ++++ src/db.js | 5 ++++ src/routes/admin.js | 29 ++++++++++++------- src/routes/kiosk.js | 11 +++++-- src/sheets.js | 69 +++++++++++++++++++++++++++++++++++++++----- src/sites.js | 24 +++++++++++---- 11 files changed, 169 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a926be9..9afd3be 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ two factor. | | Guest sign in | Recurring visitor | |---|---|---| | First and last name | typed each visit | on file | +| Company or organisation | optional, typed each visit | on file | | Person being visited | picked from the list | picked each visit | | Photo | taken at the kiosk | on file if saved, otherwise taken at the kiosk | | WWCC / VIT / none | typed each visit | on file | @@ -27,6 +28,11 @@ two factor. Sign out only needs a **last name** plus a **mobile number or email**, which works for both. +The company field is optional and clearly marked as such — plenty of visitors are not from +anywhere in particular. When it is filled in it appears on the badge, in the on-site list, on the +evacuation sheet, and in the visit log, and the log search matches on it, so you can pull up every +visit from one contractor. + ## Quick start ```bash @@ -439,6 +445,24 @@ docker compose up -d --build **Changes to the code do nothing** — Compose reuses the existing image. Always `docker compose up -d --build` after a `git pull`. +**Google Sheet says "The caller does not have permission"** — the app authenticated fine and +Google refused the spreadsheet. Work through these in order: + +1. **Admin → System** shows the service account address. Open the sheet, press Share, paste that + address, set it to **Editor**, and untick "Notify people". This is the cause about nine times + in ten. +2. If your Google Workspace blocks sharing outside the organisation, the share will silently fail + or be refused — a service account address is external. Ask your Workspace admin to allow it, + or create the sheet in an account that permits external sharing. +3. If the sheet lives in a **Shared drive**, share the drive with the service account, not just + the file. +4. Check the spreadsheet ID matches the one in the sheet's URL. A wrong ID usually gives a 404, + but a valid ID for someone else's sheet gives this same 403. +5. Confirm the **Google Sheets API** is enabled on the project the key belongs to. A key from + project A cannot use an API enabled only on project B. + +Press **Test the sheet connection** after each step. + **Browser still warns about the certificate** — the authority is installed but not trusted. On iOS that is a second, separate step under Settings → General → About → Certificate Trust Settings. On Android, use a hostname rather than a bare IP. diff --git a/public/admin.html b/public/admin.html index 746c628..c3f35ba 100644 --- a/public/admin.html +++ b/public/admin.html @@ -52,7 +52,7 @@
- +
diff --git a/public/css/kiosk.css b/public/css/kiosk.css index cb7b668..fd8177b 100644 --- a/public/css/kiosk.css +++ b/public/css/kiosk.css @@ -397,3 +397,6 @@ a:focus-visible { min-height: 58px; } .picker:disabled { color: var(--muted); } + +/* An optional field says so quietly, without shouting for attention. */ +.field > span em { font-style: normal; opacity: 0.75; } diff --git a/public/index.html b/public/index.html index 714aaf2..6132d1a 100644 --- a/public/index.html +++ b/public/index.html @@ -53,6 +53,11 @@ Last name +