Web page: use an edited API key at once, even when browser storage is blocked (#3435)

Ported from #3435 by engharat.

Co-authored-by: engharat <[email protected]>
This commit is contained in:
Niko1221andengharat committed 2026-10-22 17:32:35 +02:00
1 parent 0351ecb11d
commit 2ba95cf61f
2 files changed
+113 -5

No files matched your search

+99
View File
@@ -0,0 +1,99 @@
"""The web app uses an edited API key immediately, even when site storage is blocked.
Runs the page's storage and server-access code with Node, without a GPU or server:
python -m unittest serve.test_web_api_key -v
"""
import json
from pathlib import Path
import shutil
import subprocess
import unittest
APP = Path(__file__).with_name("web") / "app.js"
@unittest.skipUnless(shutil.which("node"), "node is not installed")
class WebApiKey(unittest.TestCase):
def run_js(self, actions, *, stored=None, blocked=False, quota=False):
src = APP.read_text(encoding="utf-8")
store = src[src.index("const store ="):src.index("// ------------------------------------------------------------------ toasts")]
access = src[src.index("// ------------------------------------------------------------------ server access"):src.index("let health =")]
js = f"""
const data = new Map(Object.entries({json.dumps(stored or {})}));
const field = {{value: ""}};
const notices = [];
const $ = () => field;
const toast = (...args) => notices.push(args);
const localStorage = {{
getItem(k) {{
if ({json.dumps(blocked)}) throw new Error("Storage blocked");
return data.has(k) ? data.get(k) : null;
}},
setItem(k, v) {{
if ({json.dumps(blocked or quota)}) throw new Error("Storage unavailable");
data.set(k, v);
}},
}};
function edit(value, event = "input") {{
field.value = value;
const handler = field["on" + event];
if (handler) handler();
}}
{store}
{access}
{actions}
"""
result = subprocess.run(["node", "-e", js], capture_output=True, text=True, timeout=30)
self.assertEqual(result.returncode, 0, result.stderr)
return json.loads(result.stdout)
def test_input_is_used_and_saved_without_blur(self):
got = self.run_js('''
edit(" test-key ");
console.log(JSON.stringify({headers: headers(true), saved: data.get("strata.apikey")}));
''')
self.assertEqual(got, {"headers": {"Authorization": "Bearer test-key", "Content-Type": "application/json"},
"saved": '"test-key"'})
def test_saved_key_is_restored_on_reload(self):
got = self.run_js('console.log(JSON.stringify({value: field.value, headers: headers()}));',
stored={"strata.apikey": '"saved-key"'})
self.assertEqual(got, {"value": "saved-key", "headers": {"Authorization": "Bearer saved-key"}})
def test_blocked_storage_still_uses_key_in_memory(self):
got = self.run_js('edit("test-key", "change"); console.log(JSON.stringify(headers()));', blocked=True)
self.assertEqual(got, {"Authorization": "Bearer test-key"})
def test_failed_write_does_not_reuse_old_key(self):
got = self.run_js('edit("new-key", "change"); console.log(JSON.stringify(headers()));',
stored={"strata.apikey": '"old-key"'}, quota=True)
self.assertEqual(got, {"Authorization": "Bearer new-key"})
def test_clearing_key_removes_authorization(self):
for quota in (False, True):
with self.subTest(quota=quota):
got = self.run_js('edit(" "); console.log(JSON.stringify(headers()));',
stored={"strata.apikey": '"old-key"'}, quota=quota)
self.assertEqual(got, {})
def test_successful_save_notifies_only_on_change(self):
got = self.run_js('''
edit("test-key");
const before = notices.length;
edit("test-key", "change");
console.log(JSON.stringify({before, kinds: notices.map(n => n[0])}));
''')
self.assertEqual(got, {"before": 0, "kinds": ["success"]})
def test_failed_save_warns_instead_of_claiming_success(self):
got = self.run_js('edit("test-key", "change"); console.log(JSON.stringify(notices.map(n => n[0])));',
blocked=True)
self.assertEqual(got, ["warn"])
def test_server_without_key_keeps_json_header_only(self):
got = self.run_js('console.log(JSON.stringify(headers(true)));')
self.assertEqual(got, {"Content-Type": "application/json"})
if __name__ == "__main__":
unittest.main()
+14 -5
View File
@@ -14,7 +14,7 @@ const gb = (b, d = 1) => (b == null ? "–" : fmt(b / 1073741824, d)); // memo
const store = {
get(k, d) { try { const v = localStorage.getItem("strata." + k); return v === null ? d : JSON.parse(v); } catch (e) { return d; } },
set(k, v) { try { localStorage.setItem("strata." + k, JSON.stringify(v)); } catch (e) { /* private mode: in memory only */ } },
set(k, v) { try { localStorage.setItem("strata." + k, JSON.stringify(v)); return true; } catch (e) { return false; } },
};
// ------------------------------------------------------------------ toasts
@@ -87,15 +87,24 @@ for (const b of document.querySelectorAll(".st-tab")) b.onclick = () => showTab(
window.addEventListener("hashchange", () => showTab(location.hash.slice(1)));
// ------------------------------------------------------------------ server access
let apiKey = store.get("apikey", "");
function headers(json = false) {
const h = {};
const key = store.get("apikey", "");
if (key) h.Authorization = "Bearer " + key;
if (apiKey) h.Authorization = "Bearer " + apiKey;
if (json) h["Content-Type"] = "application/json";
return h;
}
$("api-key").value = store.get("apikey", "");
$("api-key").onchange = () => { store.set("apikey", $("api-key").value.trim()); toast("success", "API key saved", "Kept in this browser only."); };
$("api-key").value = apiKey;
function saveApiKey(notify = false) {
apiKey = $("api-key").value.trim(); // usable even when browser storage is blocked or full
const saved = store.set("apikey", apiKey);
if (notify) {
if (saved) toast("success", "API key saved", "Kept in this browser only.");
else toast("warn", "API key used for this page only", "Browser storage is unavailable. Enter it again after reloading.");
}
}
$("api-key").oninput = () => saveApiKey();
$("api-key").onchange = () => saveApiKey(true);
let health = {model: "strata", images: false, max_context: 0};
async function loadHealth() {