mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 09:45:24 -04:00
Models: allow API keys for local endpoints
Self-hosted endpoints on a LAN are sometimes protected by an API key. The admin "Local" add/test form only sent base_url (+ model_type), so such an endpoint could not be added — it just errored out — even though the backend POST /api/model-endpoints and /model-endpoints/test already accept an optional api_key form field (the cloud "API" form already uses it). Adds an optional masked "API key" input (adm-epLocalApiKey) to the Local form and wires it into the local Test and Add handlers, sending api_key only when filled (an empty value is omitted so we never send a blank Bearer). The field is cleared after a successful add, matching the cloud form. Tested: tests/test_local_endpoint_api_key_js.py extracts the two click handlers and runs them under node with mocked DOM/FormData/fetch, asserting api_key is sent when the field is filled and omitted when blank, plus that the input exists as a password field. `node --check static/js/admin.js` passes. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2014,6 +2014,9 @@
|
||||
<option value="image">Image</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="admin-model-form-row">
|
||||
<input id="adm-epLocalApiKey" type="password" placeholder="API key (optional — for protected local endpoints)" autocomplete="off" style="flex:1">
|
||||
</div>
|
||||
<div class="admin-model-form-row">
|
||||
<span style="flex:1"></span>
|
||||
<button class="admin-btn-sm" id="adm-epLocalTestBtn" style="width:55px;text-align:center;">Test</button>
|
||||
|
||||
@@ -871,11 +871,14 @@ function initEndpointForm() {
|
||||
const raw = (el('adm-epLocalUrl').value || '').trim();
|
||||
if (!raw) { msg.textContent = 'Enter a base URL to test'; msg.className = 'admin-error'; return; }
|
||||
const url = _normalizeBaseUrl(raw);
|
||||
const keyEl = el('adm-epLocalApiKey');
|
||||
const apiKey = keyEl ? keyEl.value.trim() : '';
|
||||
localTestBtn.disabled = true;
|
||||
localTestBtn.textContent = 'Testing...';
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('base_url', url);
|
||||
if (apiKey) fd.append('api_key', apiKey);
|
||||
const res = await fetch('/api/model-endpoints/test', { method: 'POST', body: fd, credentials: 'same-origin' });
|
||||
const d = await res.json();
|
||||
_renderEndpointTestResult(msg, res, d);
|
||||
@@ -894,10 +897,13 @@ function initEndpointForm() {
|
||||
const raw = (el('adm-epLocalUrl').value || '').trim();
|
||||
if (!raw) { msg.textContent = 'Enter a base URL (e.g. http://localhost:8002/v1)'; msg.className = 'admin-error'; return; }
|
||||
const url = _normalizeBaseUrl(raw);
|
||||
const keyEl = el('adm-epLocalApiKey');
|
||||
const apiKey = keyEl ? keyEl.value.trim() : '';
|
||||
localAddBtn.disabled = true; localAddBtn.textContent = 'Adding...';
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('base_url', url);
|
||||
if (apiKey) fd.append('api_key', apiKey);
|
||||
const lt = el('adm-epLocalType');
|
||||
if (lt) fd.append('model_type', lt.value);
|
||||
fd.append('skip_probe', 'false');
|
||||
@@ -905,6 +911,7 @@ function initEndpointForm() {
|
||||
const d = await res.json();
|
||||
if (res.ok) {
|
||||
el('adm-epLocalUrl').value = '';
|
||||
if (keyEl) keyEl.value = '';
|
||||
if (lt) lt.value = 'llm';
|
||||
if (d.id) _recentlyAddedEpId = String(d.id);
|
||||
await loadEndpoints();
|
||||
|
||||
Reference in New Issue
Block a user