Skip to content

fix(timeentry): silent-drop unparseable from/to query params (#310)#311

Merged
CryptoJones merged 1 commit into
masterfrom
fix/timeentry-date-range-validation
May 19, 2026
Merged

fix(timeentry): silent-drop unparseable from/to query params (#310)#311
CryptoJones merged 1 commit into
masterfrom
fix/timeentry-date-range-validation

Conversation

@CryptoJones
Copy link
Copy Markdown
Owner

Closes #310.

Summary

Both listByCompany and exportCsv documented "bad dates are silently dropped" but the implementation passed the raw query-string straight into Sequelize, so garbage like ?from=not-a-date produced a 500 from Postgres's invalid input syntax for type timestamp.

Add a parseDateOrNull(s) helper, wire both handlers through it. Behavior now matches the documented contract.

Test plan

  • npm run lint && npm test — 777 passing (was 773), 4 new test cases in tests/api/timeentry.test.js for the helper (happy paths, silent-drop on garbage, non-string defensive).

Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/

Both `listByCompany` and `exportCsv` declare in a doc comment that
"bad dates are silently dropped rather than 400'd, so a typo in the
query string doesn't break the call." The implementation didn't
match: the raw `req.query.from` / `req.query.to` string was plugged
straight into Sequelize's `Op.gte` / `Op.lte`. Postgres can parse
ISO 8601 fine but throws `invalid input syntax for type timestamp`
on garbage like `?from=not-a-date`, which Sequelize surfaces — and
the controller's catch returns a 500.

Add `parseDateOrNull(s)` to the controller: returns a Date for any
input the `Date` constructor accepts (Number.isFinite on getTime()),
returns null otherwise. Wire both handlers through it so the
silent-drop behavior matches the documented contract.

Unit-test the helper directly via `_internals` — happy paths (ISO
8601, date-only), the silent-drop case (garbage strings), and the
defensive non-string-input branch. The helper is also wired through
the smoke-test harness's `vi.mock` for `db.config.js`, so failures
land cleanly without a live DB.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CryptoJones CryptoJones merged commit 9091b7b into master May 19, 2026
3 checks passed
@CryptoJones CryptoJones deleted the fix/timeentry-date-range-validation branch May 19, 2026 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

timeentry list/export: bad ?from / ?to dates cause 500 instead of the documented silent-drop

1 participant