1 Commits

Author SHA1 Message Date
9eed051916 feat(web,api): row-level search, more sort columns, copy buttons
Three operator-quality-of-life features behind the same caching and
pagination contract that the existing tables already use:

- Search bar on /acc and /users (Find/Enter to apply, Clear to reset).
  Backed by a new `q` API param that filters via WHERE
  username/f_username LIKE 'q%' on both rows + count queries so the
  table header total stays consistent under a filter.
- Two more sortable columns: acc.status and user.t_username. Sort
  columns are whitelisted because sort_col is f-string'd into ORDER
  BY (parameterised binding doesn't apply to column names) — anything
  outside the allowed set falls back to the table's default.
- Copy button on every row that writes a multi-line credentials
  message to the clipboard. New lib/clipboard.ts helper tries
  navigator.clipboard.writeText() first and falls back to
  textarea+execCommand("copy") so it works over the internal-network
  HTTP deploy where the modern API is gated by secure-context rules.
  Acc message: Username/Password (+Link if set). User message:
  From/To username and password.

Also: inactive sort indicators now render ↓ (the direction they'll
sort on first click) instead of the more ambiguous ↕.

Test suite grows from 53 to 70: tests/test_user_search_filter.py
(9 tests) pins the q-filter contract on both /user/ and /acc/;
tests/test_sort_whitelist.py (8 tests) pins the allowed sort columns
and proves out-of-set values cannot reach the SQL parser.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 09:26:11 +08:00