Rework self-service kiosk account lookup for privacy and safety (1.3.2)

Replaces the explicit "look up existing account" search field with automatic
lookup as email/phone are entered, requires operator confirmation before any
matched account's name/email/phone/preference is changed, adds a password
show/hide toggle, and fixes two bugs found during testing: entering a phone
number belonging to a different account could silently overwrite the form
with that account's details, and re-checking an unchanged field (e.g. from
tapping a ticket quantity button) could revert edits already made. Also adds
a server-side check rejecting registrations whose email and phone resolve to
two different existing accounts, as defense in depth.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 12:56:26 +02:00
co-authored by Claude Sonnet 5
parent 8a75c9155b
commit b081ed3c8b
7 changed files with 310 additions and 133 deletions
+5 -1
View File
@@ -482,7 +482,7 @@ const checkUserExists = async (req, res) => {
const existingUser = await prisma.user.findFirst({
where: { OR: searchClauses },
select: { name: true, email: true, phoneNumber: true, notificationPreference: true },
select: { id: true, name: true, email: true, phoneNumber: true, notificationPreference: true },
});
const hasEmail = !!existingUser?.email && !existingUser.email.endsWith('@guest.local');
@@ -494,7 +494,11 @@ const checkUserExists = async (req, res) => {
hasPhone,
// Safe-to-display fields only, for autofilling a lookup form — never the password.
// Guest placeholder emails are withheld the same way hasEmail already treats them.
// `id` lets the kiosk tell two different matched accounts apart (e.g. when the
// typed email and phone number resolve to different people) — it's never shown,
// only compared client-side, and this endpoint is already Private/Supervisor.
user: existingUser ? {
id: existingUser.id,
name: existingUser.name,
email: hasEmail ? existingUser.email : null,
phoneNumber: hasPhone ? existingUser.phoneNumber : null,