The audit #485 called for: on SQLite (native installs), timestamp columns written with a raw `new Date()` through knex store epoch-ms numbers; Postgres returns ISO strings. Frontend code written against Postgres calls parseISO() on them — parseISO(number) throws and crashes the page. #485 fixed admin Users and listed api tokens / photos / activity as out-of-scope follow-ups. Verified crash on main: Timeline gallery layout parseISO(uploaded_at) against photos written by the archive-RESTORE path (raw Date). Other raw-write surfaces (api_tokens last_used_at/revoked_at, email_queue) degrade rather than crash but violate the ISO contract. - extract toIso() from adminUsers.js into utils/dateNormalize.js (contract unchanged — the 10 existing #485 tests still pin it) - write-side: archive-restore uploaded_at, api-token last_used_at / revoked_at, email_queue created_at/sent_at now write ISO strings - read-side (heals existing corrupted rows): gallery /photos normalizes uploaded_at/captured_at; api-tokens list normalizes all four timestamp fields - frontend defence-in-depth: Timeline layout parses uploaded_at tolerantly (typeof guard) for stale caches / old backends - 2 regression tests seed literal epoch numbers and assert the API serves ISO strings activity_logs turned out safe (created_at comes from the DB default, not a raw Date) — left untouched. Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
2f05fcc39d
commit
c6ec93eef9
@@ -72,7 +72,7 @@ async function apiTokenAuth(req, res, next) {
|
||||
}
|
||||
|
||||
// Touch last_used_at — async, don't block the request.
|
||||
db('api_tokens').where({ id: row.id }).update({ last_used_at: new Date() })
|
||||
db('api_tokens').where({ id: row.id }).update({ last_used_at: new Date().toISOString() })
|
||||
.catch((err) => logger.debug('api_tokens last_used update failed', { err: err.message }));
|
||||
|
||||
req.admin = admin;
|
||||
|
||||
Reference in New Issue
Block a user