From 9b2eff54176f4f6357a87e2289d3dcfa74e0ade2 Mon Sep 17 00:00:00 2001 From: SandObserver <260779319+SandObserver@users.noreply.github.com> Date: Tue, 20 Oct 2026 17:37:16 -0400 Subject: [PATCH] Refuse icon search in demo mode with the demo message The icon catalogues are fetched from outside, which demo mode blocks, so a search failed with a generic error. Demo mode now answers icon search with the blocked.demo refusal, and the admin explains that icon search is off in the live demo. --- api/src/routes/icons.js | 7 +++++++ api/test/demo-routes.test.js | 15 +++++++++++++++ ui/admin/index.html | 2 +- ui/i18n/de.json | 1 + ui/i18n/en.json | 1 + ui/i18n/es.json | 1 + ui/i18n/fa.json | 1 + ui/i18n/fr.json | 1 + ui/i18n/zh-Hans.json | 1 + ui/js/admin-app-form.js | 8 +++++--- ui/js/admin.js | 2 +- ui/test/icon-picker.test.mjs | 7 +++++-- 12 files changed, 40 insertions(+), 7 deletions(-) diff --git a/api/src/routes/icons.js b/api/src/routes/icons.js index 2b29bc7a..d7eb1652 100644 --- a/api/src/routes/icons.js +++ b/api/src/routes/icons.js @@ -54,6 +54,13 @@ const ICON_CACHE_TTL = 24 * 60 * 60 * 1000; on('GET', '/api/icons/search', async (req, res) => { const q = (new URL(req.url, 'http://x').searchParams.get('q') || '').trim(); if (!q) return json(res, 200, { results: [] }); + if (IS_DEMO) { + return json(res, 403, { + error: 'Outbound requests are disabled in demo mode', + kind: KIND.BLOCKED, + code: 'blocked.demo', + }); + } try { json(res, 200, { results: await searchIcons(q) }); } catch (e) { diff --git a/api/test/demo-routes.test.js b/api/test/demo-routes.test.js index e7a8d62e..1d99c238 100644 --- a/api/test/demo-routes.test.js +++ b/api/test/demo-routes.test.js @@ -98,3 +98,18 @@ test('no demo write reached the disk', () => { assert.equal(fs.existsSync(process.env.CONFIG_PATH), false); assert.deepEqual(fs.readdirSync(process.env.ICONS_PATH), []); }); + +test('icon search answers the demo refusal instead of failing on the blocked catalogues', async () => { + const r = await new Promise((resolve, reject) => { + http + .get(`${base}/api/icons/search?q=plex`, res => { + let raw = ''; + res.on('data', c => (raw += c)); + res.on('end', () => resolve({ status: res.statusCode, body: JSON.parse(raw) })); + }) + .on('error', reject); + }); + assert.equal(r.status, 403); + assert.equal(r.body.code, 'blocked.demo'); + assert.equal(r.body.kind, 'blocked'); +}); diff --git a/ui/admin/index.html b/ui/admin/index.html index 28a56421..cc9e837a 100644 --- a/ui/admin/index.html +++ b/ui/admin/index.html @@ -302,6 +302,6 @@