feat: add permanent deletion for revoked keys

DELETE /admin/api/keys/{id}/purge removes the key record; it requires the key to be revoked first and keeps historical logs. The keys page swaps the revoke button for a delete button once a key is revoked.
This commit is contained in:
2026-10-25 18:40:32 +08:00
parent 293f7f524a
commit 578afe509c
4 changed files with 86 additions and 4 deletions
+13 -2
View File
@@ -71,7 +71,16 @@ export function KeysPage({ keys, stats, channels, timezone, busy, error, notice,
action(async () => {
await api('/keys/' + encodeURIComponent(k.id), 'DELETE')
refresh()
notify('Key 已撤销,历史记录已保留。')
notify('Key 已撤销,历史记录已保留;如需彻底移除可点击“删除”。')
})
}
function purge(k: Key) {
if (!confirm(`确定永久删除 Key“${k.name}”?删除后不可恢复,历史调用记录会保留。`)) return
action(async () => {
await api('/keys/' + encodeURIComponent(k.id) + '/purge', 'DELETE')
refresh()
notify('Key 已删除,历史记录已保留。')
})
}
@@ -108,7 +117,9 @@ export function KeysPage({ keys, stats, channels, timezone, busy, error, notice,
<>{time(k.expires_at) === '—' ? '永不过期' : time(k.expires_at)}<small className="sub">创建于 {time(k.created_at)}</small></>,
<div className="actions">
<button disabled={busy || k.revoked} onClick={() => toggle(k)}>{k.enabled ? '停用' : '启用'}</button>
<button className="danger" disabled={busy} onClick={() => revoke(k)}>撤销</button>
{k.revoked
? <button className="danger" disabled={busy} onClick={() => purge(k)}>删除</button>
: <button className="danger" disabled={busy} onClick={() => revoke(k)}>撤销</button>}
</div>,
]
})}