Add API key provisioning to accounts page

This commit is contained in:
2026-05-11 12:24:05 -05:00
parent f22d90ac6f
commit 18350761c5
4 changed files with 246 additions and 1 deletions
+87
View File
@@ -246,11 +246,98 @@ fn main() -> Void {
}
}
async function loadApiKeys() {
var apiSection = document.getElementById('api-keys-section');
if (apiSection) apiSection.style.display = '';
try {
var sess = await sb.auth.getSession();
var token = sess.data && sess.data.session ? sess.data.session.access_token : '';
if (!token) return;
var r = await fetch('/api/api-keys', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({access_token: token})
});
var d = await r.json();
if (!d.rows || !d.rows.length) return;
d.rows.forEach(function(row) {
var provider = row.provider;
var keyVal = row.key_value || '';
var maskedEl = document.getElementById('apikey-masked-' + provider);
var delBtn = document.getElementById('apikey-del-' + provider);
if (keyVal) {
var klen = keyVal.length;
var masked = klen <= 10 ? '••••••••' : keyVal.slice(0, 6) + '••••' + keyVal.slice(-4);
if (maskedEl) maskedEl.textContent = masked;
if (delBtn) delBtn.style.display = '';
}
});
} catch (e) {}
}
window.saveApiKey = async function(provider) {
var input = document.getElementById('apikey-input-' + provider);
var msg = document.getElementById('api-keys-msg');
if (!input || !input.value.trim()) {
if (msg) { msg.style.display = 'block'; msg.style.color = '#c44'; msg.textContent = 'Enter a key first.'; }
return;
}
var keyVal = input.value.trim();
var sess = await sb.auth.getSession();
var token = sess.data && sess.data.session ? sess.data.session.access_token : '';
if (!token) return;
try {
var r = await fetch('/api/api-keys/save', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({access_token: token, provider: provider, key: keyVal})
});
var d = await r.json();
if (d.ok) {
var maskedEl = document.getElementById('apikey-masked-' + provider);
var delBtn = document.getElementById('apikey-del-' + provider);
if (maskedEl) maskedEl.textContent = d.masked;
if (delBtn) delBtn.style.display = '';
input.value = '';
if (msg) { msg.style.display = 'block'; msg.style.color = 'var(--navy)'; msg.textContent = provider.charAt(0).toUpperCase() + provider.slice(1) + ' key saved.'; }
setTimeout(function() { if (msg) msg.style.display = 'none'; }, 3000);
} else {
if (msg) { msg.style.display = 'block'; msg.style.color = '#c44'; msg.textContent = d.error || 'Save failed.'; }
}
} catch (e) {
if (msg) { msg.style.display = 'block'; msg.style.color = '#c44'; msg.textContent = 'Network error.'; }
}
};
window.deleteApiKey = async function(provider) {
var sess = await sb.auth.getSession();
var token = sess.data && sess.data.session ? sess.data.session.access_token : '';
if (!token) return;
try {
var r = await fetch('/api/api-keys/delete', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({access_token: token, provider: provider})
});
var d = await r.json();
if (d.ok) {
var maskedEl = document.getElementById('apikey-masked-' + provider);
var delBtn = document.getElementById('apikey-del-' + provider);
if (maskedEl) maskedEl.textContent = 'Not configured';
if (delBtn) delBtn.style.display = 'none';
var msg = document.getElementById('api-keys-msg');
if (msg) { msg.style.display = 'block'; msg.style.color = 'var(--t3)'; msg.textContent = provider.charAt(0).toUpperCase() + provider.slice(1) + ' key removed.'; }
setTimeout(function() { if (msg) msg.style.display = 'none'; }, 3000);
}
} catch (e) {}
};
function showDashboard(user) {
hide('signin-section');
show('dashboard-section');
renderUserChip(user);
loadWaitlistData();
loadApiKeys();
}
async function init() {