fix(security): close the remaining image-security default gaps
Round-two review follow-ups. Settings survive the tab round trip. GET returns setting_value without decoding it and ImageSecurityTab PUTs the whole fetched object back through JSON.stringify, so on SQLite one visit to the tab re-encodes every value it read. A single parse then yields the string "true", the type checks reject it, and the defaults go quietly dead — the exact bug this change exists to fix, returning by a different route. The reader now unwraps until the value stops being a JSON string, bounded. Array overrides rejected. express-validator applies isInt/isIn/isBoolean element-wise, so `image_quality: [72]` passed the chain and arrived still an array — a PG insert error, and `[false]` coerced to true by formatBoolean. Both create routes now use .not().isArray(), and the shared resolver ignores non-scalars for any future caller. Two more creation paths covered. quoteService.convertToEvent builds its own events row, so CRM-converted galleries fell back to column defaults. /:id/duplicate copies fifteen source columns including enable_devtools_protection but missed these four, so duplicating a 'maximum' gallery produced a 'standard' one — a duplicate now inherits the source's values, not the current globals, since copying the gallery is the point. The PUT /:id chain has the same array weakness. Pre-existing and outside this fix; left alone deliberately. Refs #1296
This commit is contained in:
@@ -1683,6 +1683,8 @@ async function convertToEvent(quoteId, adminId, options = {}) {
|
||||
// ask the DB which columns exist and only keep the matching pairs
|
||||
// — bullet-proof against schema drift in either direction.
|
||||
const eventCols = await trx('events').columnInfo();
|
||||
const { getImageSecurityDefaults, resolveImageSecurityColumns } = require('../routes/adminEvents/helpers');
|
||||
const imageSecurityColumns = resolveImageSecurityColumns({}, await getImageSecurityDefaults());
|
||||
const candidate = {
|
||||
slug: `quote-${quote.quote_number.toLowerCase()}-${crypto.randomBytes(3).toString('hex')}`,
|
||||
event_name: quote.event_name || `Event ${quote.quote_number}`,
|
||||
@@ -1705,6 +1707,11 @@ async function convertToEvent(quoteId, adminId, options = {}) {
|
||||
quote_id: quote.id,
|
||||
created_at: new Date(),
|
||||
updated_at: new Date(),
|
||||
// #1296 — a converted quote produces a real gallery, so the global
|
||||
// Image Security defaults have to reach it too. Required lazily: this
|
||||
// is a service reaching into a route helper, and the lazy form keeps
|
||||
// the module graph acyclic the way the storage require below does.
|
||||
...imageSecurityColumns,
|
||||
};
|
||||
const eventRow = {};
|
||||
for (const [k, v] of Object.entries(candidate)) {
|
||||
|
||||
Reference in New Issue
Block a user