fix: rename API Keys -> Sub-Keys, show key inline on creation, no reload

This commit is contained in:
M1 2026-03-17 06:37:29 +04:00
parent ab4f60e159
commit c684d96d90
2 changed files with 21 additions and 20 deletions

View File

@ -192,8 +192,8 @@ export const account = new Elysia({ prefix: "/account" })
const keyLookup = sha256(norm);
const keyHash = await Bun.password.hash(norm, { algorithm: "bcrypt", cost: 10 });
await sql`INSERT INTO api_keys (key_lookup, key_hash, account_id, label) VALUES (${keyLookup}, ${keyHash}, ${accountId}, ${body.label})`;
return { key: rawKey, label: body.label };
const [created] = await sql`INSERT INTO api_keys (key_lookup, key_hash, account_id, label) VALUES (${keyLookup}, ${keyHash}, ${accountId}, ${body.label}) RETURNING id`;
return { key: rawKey, id: created.id, label: body.label };
}, {
body: t.Object({
label: t.String({ description: "A name for this key, e.g. 'ci-pipeline' or 'mobile-app'" }),

View File

@ -49,10 +49,10 @@
<section class="bg-gray-900 rounded-xl border border-gray-800 p-6">
<div class="flex items-center justify-between mb-4">
<div>
<h2 class="text-sm font-semibold text-gray-300">API Keys</h2>
<h2 class="text-sm font-semibold text-gray-300">Sub-Keys</h2>
<p class="text-xs text-gray-600 mt-0.5">Create separate keys for different apps, scripts, or teammates.</p>
</div>
<button onclick="showCreateKey()" class="px-3 py-1.5 bg-blue-600 hover:bg-blue-500 text-white rounded-lg text-xs font-medium transition-colors">+ New Key</button>
<button onclick="showCreateKey()" class="px-3 py-1.5 bg-blue-600 hover:bg-blue-500 text-white rounded-lg text-xs font-medium transition-colors">+ New Sub-Key</button>
</div>
<!-- Create key form (hidden by default) -->
@ -66,19 +66,19 @@
</div>
</div>
<!-- New key reveal (shown after creation) -->
<!-- New sub-key reveal (shown after creation) -->
<div id="new-key-reveal" class="hidden mb-4 p-4 bg-green-950/30 rounded-lg border border-green-900/50">
<p class="text-xs text-green-400 mb-2">Key created — copy it now.</p>
<p class="text-xs text-green-400 mb-2">Sub-key created — copy it now, it won't be shown again.</p>
<div class="flex gap-2">
<code id="new-key-value" class="flex-1 bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-blue-400 text-sm tracking-widest"></code>
<code id="new-key-value" class="flex-1 bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-blue-400 text-sm font-mono select-all"></code>
<button onclick="copyNewKey()" class="px-3 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg text-gray-400 hover:text-white text-xs transition-colors">Copy</button>
</div>
</div>
<!-- Keys list -->
<!-- Sub-keys list -->
<div id="keys-list" class="space-y-2">
<% if (it.apiKeys.length === 0) { %>
<p class="text-xs text-gray-600 italic">No API keys yet.</p>
<p class="text-xs text-gray-600 italic">No sub-keys yet.</p>
<% } else { %>
<% it.apiKeys.forEach(function(k) { %>
<div class="flex items-center justify-between p-3 bg-gray-800/50 rounded-lg border border-gray-700/50">
@ -97,15 +97,7 @@
<script>
// On load: check sessionStorage for a newly created key to reveal
(function() {
const newKey = sessionStorage.getItem('_newApiKey');
if (newKey) {
sessionStorage.removeItem('_newApiKey');
document.getElementById('new-key-value').textContent = newKey;
document.getElementById('new-key-reveal').classList.remove('hidden');
}
})();
async function saveEmail() {
const email = document.getElementById('email-input').value.trim();
@ -152,8 +144,17 @@
const label = document.getElementById('key-label').value.trim();
if (!label) return;
const data = await api('/account/keys', { method: 'POST', body: { label } });
sessionStorage.setItem('_newApiKey', data.key);
location.reload();
hideCreateKey();
document.getElementById('new-key-value').textContent = data.key;
document.getElementById('new-key-reveal').classList.remove('hidden');
// Add to list without reload
const list = document.getElementById('keys-list');
const empty = list.querySelector('p.italic');
if (empty) empty.remove();
const item = document.createElement('div');
item.className = 'flex items-center justify-between p-3 bg-gray-800/50 rounded-lg border border-gray-700/50';
item.innerHTML = `<div><p class="text-sm text-gray-200">${label}</p><p class="text-xs text-gray-600 mt-0.5">just now · never used</p></div><button onclick="deleteKey('${data.id}')" class="text-xs text-gray-600 hover:text-red-400 transition-colors px-2 py-1">Revoke</button>`;
list.appendChild(item);
}
function copyNewKey() {