// #99/#139: admin lock + settings panel. Key lives in sessionStorage for this visit only. (function () { var KEY = 'palette_admin_key'; var keyInput = document.getElementById('admin-key'); var status = document.getElementById('admin-key-status'); var panel = document.getElementById('admin-panel'); function key() { return sessionStorage.getItem(KEY) || ''; } function api(path, opts) { opts = opts || {}; // allow callers to override the key header (e.g. validating a typed key, #99) opts.headers = Object.assign({ 'X-Admin-Key': key() }, opts.headers || {}); if (opts.body) opts.headers['Content-Type'] = 'application/json'; return fetch(path, opts); } function loadSettings() { api('/admin/api/settings').then(function (r) { if (r.status !== 200) { showLock(); return; } return r.json(); }).then(function (s) { if (!s) return; document.getElementById('rl-burst').value = s.rate_limit_burst; document.getElementById('rl-refill').value = s.rate_limit_per_minute; document.getElementById('max-content').value = s.max_content_bytes; document.getElementById('default-expiry').value = s.default_expiry; document.getElementById('slug-days').value = s.custom_slug_reservation_days; document.getElementById('burn-window').value = s.burn_viewer_window_minutes; panel.classList.remove('hidden'); }); } function showLock() { panel.classList.add('hidden'); sessionStorage.removeItem(KEY); } document.getElementById('admin-key-form').addEventListener('submit', function (e) { e.preventDefault(); // #99: don't persist the key until the server accepts it api('/admin/api/settings', { headers: { 'X-Admin-Key': keyInput.value } }).then(function (r) { if (r.status === 200) { sessionStorage.setItem(KEY, keyInput.value); status.textContent = '✓'; keyInput.value = ''; loadSettings(); } else { status.textContent = 'invalid key'; showLock(); } }); }); document.getElementById('admin-settings-form').addEventListener('submit', function (e) { e.preventDefault(); var body = { rate_limit_burst: parseFloat(document.getElementById('rl-burst').value), rate_limit_per_minute: parseFloat(document.getElementById('rl-refill').value), max_content_bytes: parseInt(document.getElementById('max-content').value, 10), default_expiry: document.getElementById('default-expiry').value, custom_slug_reservation_days: parseInt(document.getElementById('slug-days').value, 10), burn_viewer_window_minutes: parseInt(document.getElementById('burn-window').value, 10) }; api('/admin/api/settings', { method: 'POST', body: JSON.stringify(body) }).then(function (r) { document.getElementById('admin-save-status').textContent = r.status === 200 ? 'saved' : 'error'; if (r.status !== 200) showLock(); }); }); // #112: always show the lock on fresh load — do not auto-restore the // panel from a stale sessionStorage key. The key is only written after a // successful unlock (above) so in-page actions still work within this visit. })();