feat: Scanned-Keys 'Alle prüfen' Button + EasyMDE Refresh nach More-Toggle

- POST /api/admin/api-keys/scanned/recheck-all: prüft alle nicht-adoptierten Scanned-Keys sequenziell
- Button mit Loading-State, Ergebnis-Toast und Auto-Reload
- EasyMDE/CodeMirror refresh() nach initMoreButton() Einblenden (behebt leeren Editor-Bug)
This commit is contained in:
Meleki committed 2026-03-13 15:58:31 +01:00
1 parent a13355d7e9
commit 7352438b11
5 files changed
+47 -1

No files matched your search

+22
View File
@@ -29,6 +29,7 @@ public static class ApiKeysEndpoint
app.MapPost("/api/admin/api-keys/scan", HandleScanTrigger);
app.MapGet("/api/admin/api-keys/scan/status", HandleScanStatus);
app.MapGet("/api/admin/api-keys/scanned", HandleGetScanned);
app.MapPost("/api/admin/api-keys/scanned/recheck-all", HandleRecheckAll);
app.MapPost("/api/admin/api-keys/scanned/{id}/recheck", HandleRecheck);
app.MapPost("/api/admin/api-keys/scanned/{id}/adopt", HandleAdopt);
app.MapDelete("/api/admin/api-keys/scanned/{id}", HandleDeleteScanned);
@@ -274,6 +275,27 @@ public static class ApiKeysEndpoint
await ctx.Response.WriteAsJsonAsync(result);
}
private static async Task HandleRecheckAll(HttpContext ctx, DatabaseService db, KeyScannerService scanner)
{
if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; }
var keys = await db.GetScannedKeys();
var notAdopted = keys.Where(k => k.AdoptedApiKeyId == null).ToList();
int success = 0, errors = 0;
foreach (var sk in notAdopted)
{
try
{
await scanner.CheckAndUpdateKey(sk);
success++;
}
catch { errors++; }
}
await ctx.Response.WriteAsJsonAsync(new { ok = true, total = notAdopted.Count, success, errors });
}
private static async Task HandleRecheck(HttpContext ctx, DatabaseService db, KeyScannerService scanner, string id)
{
if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; }
+1
View File
@@ -585,6 +585,7 @@
<h2>Key Scanner</h2>
<div style="display:flex;gap:.5rem;align-items:center">
<span id="scanStatus" class="admin-user-meta" style="font-size:.85em"></span>
<button id="recheckAllScannedBtn" class="section-add-btn"><i class="fa fa-refresh"></i> Alle prüfen</button>
<button id="scanQuickBtn" class="section-add-btn"><i class="fa fa-bolt"></i> Quick</button>
<button id="scanWebBtn" class="section-add-btn"><i class="fa fa-globe"></i> Web</button>
<button id="scanFullBtn" class="section-add-btn"><i class="fa fa-search"></i> Full</button>
+1
View File
@@ -235,6 +235,7 @@ function apiCheckAllApiKeys() { return _post('/api/admin/api-keys/check-all', un
function apiTriggerScan(mode) { return _post('/api/admin/api-keys/scan?mode=' + (mode || 'full'), undefined, 'Fehler beim Starten des Scans'); }
function apiScanStatus() { return _get('/api/admin/api-keys/scan/status', {}); }
function apiGetScannedKeys() { return _get('/api/admin/api-keys/scanned', []); }
function apiRecheckAllScannedKeys() { return _post('/api/admin/api-keys/scanned/recheck-all', undefined, 'Fehler beim Prüfen'); }
function apiRecheckScannedKey(id) { return _post('/api/admin/api-keys/scanned/' + id + '/recheck', undefined, 'Fehler beim Prüfen'); }
function apiAdoptScannedKey(id) { return _post('/api/admin/api-keys/scanned/' + id + '/adopt', undefined, 'Fehler beim Übernehmen'); }
function apiDeleteScannedKey(id) { return _del('/api/admin/api-keys/scanned/' + id, 'Fehler beim Löschen'); }
+16
View File
@@ -318,6 +318,7 @@ registerPage('api-keys', {
var scanQuickBtn = document.getElementById('scanQuickBtn');
var scanWebBtn = document.getElementById('scanWebBtn');
var scanFullBtn = document.getElementById('scanFullBtn');
var recheckAllScannedBtn = document.getElementById('recheckAllScannedBtn');
var scanBtns = [scanQuickBtn, scanWebBtn, scanFullBtn];
var scanStatusEl = document.getElementById('scanStatus');
var scannedList = document.getElementById('scannedKeysList');
@@ -497,6 +498,21 @@ registerPage('api-keys', {
scanWebBtn.addEventListener('click', function() { triggerScan('web', scanWebBtn); });
scanFullBtn.addEventListener('click', function() { triggerScan('full', scanFullBtn); });
recheckAllScannedBtn.addEventListener('click', async function() {
recheckAllScannedBtn.disabled = true;
recheckAllScannedBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Prüfe…';
try {
var result = await apiRecheckAllScannedKeys();
showToast('Alle geprüft: ' + result.success + '/' + result.total + ' OK' + (result.errors > 0 ? ', ' + result.errors + ' Fehler' : ''), result.errors > 0 ? 'warning' : 'success');
await loadScannedKeys();
} catch(e) {
showToast('Fehler beim Prüfen', 'error');
} finally {
recheckAllScannedBtn.disabled = false;
recheckAllScannedBtn.innerHTML = '<i class="fa fa-refresh"></i> Alle prüfen';
}
});
await loadScannedKeys();
await updateScanStatus();
},
+7 -1
View File
@@ -134,8 +134,14 @@ function initMoreButton(moreEl) {
if (!moreEl) return;
moreEl.addEventListener('click', () => {
const content = moreEl.querySelector('[hidden]');
while (content.firstChild) moreEl.parentNode.insertBefore(content.firstChild, moreEl);
const parent = moreEl.parentNode;
while (content.firstChild) parent.insertBefore(content.firstChild, moreEl);
moreEl.remove();
// EasyMDE/CodeMirror braucht refresh() nach Sichtbarwerden
parent.querySelectorAll('.EasyMDEContainer').forEach(c => {
const cm = c.querySelector('.CodeMirror');
if (cm && cm.CodeMirror) cm.CodeMirror.refresh();
});
});
}