From a0385cfb9b9208ee48eff1483d1c2b9deff193a4 Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Thu, 4 Jun 2026 10:33:10 +0000 Subject: [PATCH] Fix unauthorized errors on recipe stream and direct fetch calls. Send API token headers on generate_recipe_stream, expiry_history, and tts_proxy after security hardening. Co-authored-by: Cursor --- assets/js/app.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 900eaf6..a5f45ab 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -8827,7 +8827,9 @@ function recalculateAddExpiry() { async function _fetchExpiryHistoryAndUpdate(productId) { try { - const res = await fetch(`api/index.php?action=expiry_history&product_id=${encodeURIComponent(productId)}`); + const res = await fetch(`api/index.php?action=expiry_history&product_id=${encodeURIComponent(productId)}`, { + headers: { ...(typeof apiAuthHeaders === 'function' ? apiAuthHeaders() : {}) }, + }); const data = await res.json(); if (data.avg_days && data.avg_days > 0 && data.count >= 1) { window._historyExpiryDays = data.avg_days; @@ -14526,7 +14528,11 @@ async function _ttsViaProxy(req) { // Route through server-side proxy to avoid mixed-content / CORS issues return fetch('api/index.php?action=tts_proxy', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'X-EverShelf-Request': '1', + ...(typeof apiAuthHeaders === 'function' ? apiAuthHeaders() : {}), + }, body: JSON.stringify({ url: req.url, method: req.method, @@ -15738,7 +15744,11 @@ async function generateRecipe() { const response = await fetch('api/index.php?action=generate_recipe_stream', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'X-EverShelf-Request': '1', + ...(typeof apiAuthHeaders === 'function' ? apiAuthHeaders() : {}), + }, body: JSON.stringify(payload) }); @@ -15746,7 +15756,11 @@ async function generateRecipe() { const data = await response.json().catch(() => ({})); document.getElementById('recipe-loading').style.display = 'none'; document.getElementById('recipe-ask').style.display = ''; - if (data.error === 'no_api_key') { + if (response.status === 401) { + window._apiTokenRequired = true; + if (typeof _promptApiTokenIfNeeded === 'function') _promptApiTokenIfNeeded(); + showToast(t('startup.token_required') || 'Token API richiesto', 'warning'); + } else if (data.error === 'no_api_key') { showToast(t('error.no_api_key'), 'warning'); } else { showToast(data.error || t('recipes.generate_error'), 'error');