From f0168139f3a68087ac36e9b31e84539b45f3b98a Mon Sep 17 00:00:00 2001 From: Ludwig Lehnert Date: Mon, 12 Jan 2026 18:27:05 +0100 Subject: [PATCH] extended expressjs admin dashboard --- expressjs/src/server.js | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/expressjs/src/server.js b/expressjs/src/server.js index 82179ce..aec3fd6 100644 --- a/expressjs/src/server.js +++ b/expressjs/src/server.js @@ -510,6 +510,7 @@ app.get(`${basePath}/admin/dashboard`, requireAdminPage, async (req, res) => { totalDeletes, lastCleanup, recentLogs, + allUploads, ] = await Promise.all([ get('SELECT COUNT(*) as count FROM uploads'), get('SELECT COALESCE(SUM(size_bytes), 0) as total FROM uploads'), @@ -518,6 +519,7 @@ app.get(`${basePath}/admin/dashboard`, requireAdminPage, async (req, res) => { get('SELECT COUNT(*) as count FROM admin_logs WHERE event IN (?, ?)', ['delete', 'cleanup']), get('SELECT MAX(created_at) as ts FROM admin_logs WHERE event = ?', ['cleanup']), all('SELECT event, owner, detail, created_at FROM admin_logs ORDER BY created_at DESC LIMIT 500'), + all('SELECT id, owner, original_name, stored_name, size_bytes, expires_at FROM uploads ORDER BY uploaded_at DESC'), ]); const stats = ` @@ -540,6 +542,33 @@ app.get(`${basePath}/admin/dashboard`, requireAdminPage, async (req, res) => { `).join(''); + const adminUploadsRows = allUploads.map((item) => { + const fileUrl = `/_share/${item.stored_name}`; + return ` + + ${item.owner} + +
${item.original_name}
+
${item.stored_name}
+ + ${formatBytes(item.size_bytes)} + +
${formatTimestamp(item.expires_at)}
+
Noch ${formatCountdown(item.expires_at)}
+ + +
+ +
+
+ + +
+ + + `; + }).join(''); + const body = `
@@ -570,10 +599,65 @@ app.get(`${basePath}/admin/dashboard`, requireAdminPage, async (req, res) => { + +
+

Aktive Uploads

+ ${allUploads.length ? ` + + + + + + + + + + + + ${adminUploadsRows} + +
NutzerDateiGrößeLäuft abAktionen
+ ` : '
Keine aktiven Uploads.
'} +
`; res.send(renderPage('Adminübersicht', body)); }); +app.post(`${basePath}/admin/files/:id/delete`, requireAdminPage, async (req, res) => { + const uploadEntry = await get('SELECT id, stored_path FROM uploads WHERE id = ?', [req.params.id]); + if (!uploadEntry) { + res.status(404).send(renderPage('Nicht gefunden', '

Upload nicht gefunden.

')); + return; + } + try { + await fs.promises.unlink(uploadEntry.stored_path); + } catch (err) { + // Ignore missing files. + } + await run('DELETE FROM uploads WHERE id = ?', [uploadEntry.id]); + await logEvent('delete', 'admin', { id: uploadEntry.id }); + res.redirect(baseUrl('/admin/dashboard')); +}); + +app.post(`${basePath}/admin/files/:id/extend`, requireAdminPage, async (req, res) => { + const uploadEntry = await get('SELECT id, expires_at FROM uploads WHERE id = ?', [req.params.id]); + if (!uploadEntry) { + res.status(404).send(renderPage('Nicht gefunden', '

Upload nicht gefunden.

')); + return; + } + + const override = parseFloat(req.body.extendHours || ''); + const extensionSeconds = Number.isFinite(override) && override > 0 + ? Math.round(override * 3600) + : uploadTtlSeconds; + + const base = Math.max(uploadEntry.expires_at, Date.now()); + const nextExpiry = base + extensionSeconds * 1000; + await run('UPDATE uploads SET expires_at = ? WHERE id = ?', [nextExpiry, uploadEntry.id]); + await logEvent('extend', 'admin', { id: uploadEntry.id, expires_at: nextExpiry }); + res.redirect(baseUrl('/admin/dashboard')); +}); + app.get(`${basePath}/dashboard`, requireAuthPage, async (req, res) => { const uploads = await all( 'SELECT id, original_name, stored_name, size_bytes, uploaded_at, expires_at FROM uploads WHERE owner = ? ORDER BY uploaded_at DESC',