fix: per-field template guard, LIKE escaping, wait for all uploads
Codex review round 1 on #1266. Migration 194 gated all three German fields on body_html alone, so an admin who had translated only the subject would lose it the moment the HTML still matched English -- and down() is a deliberate no-op, making that loss unrecoverable. Each field is now judged independently, for both the translations table and the legacy _de columns. Archives search escapes LIKE wildcards. % and _ are literal characters to the client-side includes() this replaced but wildcards to LIKE, so searching "100%" matched every archive and reported a nonsense total. The ESCAPE clause is load-bearing: SQLite has no default LIKE escape character, so without it the escaped pattern matches literal backslashes there while working on PG. The post-upload poll waits for every queued file. Each is processed independently, so stopping at the first new photo left the rest of a multi-file upload hidden until a manual refresh -- the exact symptom the polling was added to prevent. UserPhotoUpload now reports how many files the server accepted. (The latter two are superseded by stronger fixes in #1267 -- the upload-status endpoint and the shared escape helper -- but each PR has to be correct on its own.)
This commit is contained in:
@@ -25,9 +25,19 @@ router.get('/', adminAuth, requirePermission('archives.view'), async (req, res)
|
||||
// Search and type filtering run in SQL so both the returned rows and
|
||||
// the total count cover the whole archive table, not just the page the
|
||||
// client happens to be on. Values are bound, never interpolated.
|
||||
// % and _ are wildcards to LIKE but literal characters to the client-side
|
||||
// `includes()` this replaced, so searching for "100%" would otherwise match
|
||||
// every archive and report a nonsense total. The ESCAPE clause is
|
||||
// load-bearing rather than decorative: SQLite has no default LIKE escape
|
||||
// character, so without it the escaped pattern matches literal backslashes
|
||||
// there while working on Postgres.
|
||||
const escapeLike = (value) => value.replace(/[\\%_]/g, '\\$&');
|
||||
const applyFilters = (query) => {
|
||||
if (search) {
|
||||
query.whereRaw('LOWER(events.event_name) LIKE ?', [`%${search.toLowerCase()}%`]);
|
||||
query.whereRaw(
|
||||
'LOWER(events.event_name) LIKE ? ESCAPE \'\\\'',
|
||||
[`%${escapeLike(search.toLowerCase())}%`]
|
||||
);
|
||||
}
|
||||
if (type && type !== 'all') {
|
||||
query.where('events.event_type', type);
|
||||
|
||||
Reference in New Issue
Block a user