Gate both kiosks behind a device token, and make an unreachable setting a test failure

This commit is contained in:
2026-09-02 18:11:01 -04:00
parent 2f90419ceb
commit 4b21aa3887
14 changed files with 498 additions and 66 deletions

View File

@@ -92,7 +92,7 @@
<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { printedpartsApi, settingsApi, KIOSK_TOKEN_KEY } from '@/api'
import { printedpartsApi, settingsApi, claimKioskToken, KIOSK_TOKEN_KEYS } from '@/api'
import { withBase } from '@/utils/basePath'
import TouchKeypad from '@/components/TouchKeypad.vue'
@@ -116,28 +116,8 @@ const scannedRevision = ref(null)
const entryInput = ref(null)
let resetTimer = null
// Claim the device token, once, from the URL an admin used to set this screen
// up: /parts-kiosk?token=<value>. It is kept in THIS browser and stripped from
// the address bar immediately, so it does not sit in the URL for a shoulder to
// read, and does not travel in a bookmark or a screenshot. Every kiosk call
// then carries it as X-Kiosk-Token; without it the routes answer 404.
function claimTokenFromUrl() {
try {
const url = new URL(window.location.href)
const token = (url.searchParams.get('token') || '').trim()
if (!token) return
localStorage.setItem(KIOSK_TOKEN_KEY, token)
url.searchParams.delete('token')
window.history.replaceState({}, '', url.pathname + url.search + url.hash)
} catch {
// A browser refusing localStorage is a browser this kiosk cannot be
// provisioned in. Nothing to recover here; the routes will 404 and the
// operator sees the standard error.
}
}
onMounted(async () => {
claimTokenFromUrl()
claimKioskToken(KIOSK_TOKEN_KEYS['/printedparts/kiosk/'])
// A kiosk left running for weeks reads this once at load, which is fine: the
// label format is a property of the site's physical tags, not something that
// changes during a shift.