Public Access
Visitor sign in kiosk: multi-site, badge printing, WWCC expiry warnings, admin accounts with 2FA
This commit is contained in:
+54
-3
@@ -585,7 +585,18 @@ router.get('/frequent', (req, res) => {
|
||||
router.get('/frequent/:id', (req, res) => {
|
||||
const row = db.prepare('SELECT * FROM frequent_visitors WHERE id = ?').get(req.params.id);
|
||||
if (!row) return res.status(404).json({ error: 'Not found.' });
|
||||
res.json(shapeFrequent(row, true));
|
||||
res.json({
|
||||
...shapeFrequent(row, true),
|
||||
// Context for the removal confirmation.
|
||||
visitCount: db
|
||||
.prepare('SELECT COUNT(*) AS n FROM visits WHERE frequent_visitor_id = ?')
|
||||
.get(row.id).n,
|
||||
onSite: Boolean(
|
||||
db
|
||||
.prepare('SELECT 1 FROM visits WHERE frequent_visitor_id = ? AND signed_out_at IS NULL')
|
||||
.get(row.id)
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
/** Everyone whose check lapses inside the warning window, or already has. */
|
||||
@@ -763,9 +774,49 @@ router.post('/frequent/:id/pin', (req, res) => {
|
||||
res.json({ ok: true, pin });
|
||||
});
|
||||
|
||||
/**
|
||||
* Removes a recurring visitor for good.
|
||||
*
|
||||
* Their visit history is deliberately kept: visits store the name, contact details
|
||||
* and host as their own columns, so the log stays a complete record of who was in
|
||||
* the building even after the person's saved record is gone. Deleting the record
|
||||
* frees their mobile number, email and PIN for someone else.
|
||||
*
|
||||
* To keep someone on file but stop them signing in, untick Active instead.
|
||||
*/
|
||||
router.delete('/frequent/:id', (req, res) => {
|
||||
db.prepare('UPDATE frequent_visitors SET active = 0 WHERE id = ?').run(req.params.id);
|
||||
res.json({ ok: true });
|
||||
const row = db.prepare('SELECT * FROM frequent_visitors WHERE id = ?').get(req.params.id);
|
||||
if (!row) return res.status(404).json({ error: 'Not found.' });
|
||||
|
||||
const scope = scopedSiteId(req);
|
||||
if (scope && row.site_id && row.site_id !== scope) {
|
||||
return res.status(403).json({ error: 'That visitor belongs to another site.' });
|
||||
}
|
||||
|
||||
const openVisit = db
|
||||
.prepare('SELECT id FROM visits WHERE frequent_visitor_id = ? AND signed_out_at IS NULL')
|
||||
.get(row.id);
|
||||
if (openVisit && !req.query.force) {
|
||||
return res.status(409).json({
|
||||
error: `${row.first_name} is signed in right now. Sign them out first, or confirm to remove anyway.`,
|
||||
onSite: true,
|
||||
});
|
||||
}
|
||||
|
||||
const visitCount = db
|
||||
.prepare('SELECT COUNT(*) AS n FROM visits WHERE frequent_visitor_id = ?')
|
||||
.get(row.id).n;
|
||||
|
||||
if (row.photo_path) deletePhoto(row.photo_path);
|
||||
db.prepare('DELETE FROM pin_attempts WHERE phone = ?').run(row.phone);
|
||||
// visits.frequent_visitor_id is ON DELETE SET NULL, so the history survives.
|
||||
db.prepare('DELETE FROM frequent_visitors WHERE id = ?').run(row.id);
|
||||
|
||||
res.json({
|
||||
ok: true,
|
||||
name: `${row.first_name} ${row.last_name}`,
|
||||
visitsKept: visitCount,
|
||||
});
|
||||
});
|
||||
|
||||
/* ------------------------------------------------------------- visits */
|
||||
|
||||
Reference in New Issue
Block a user