Add audit log viewer to Settings page
This commit is contained in:
@@ -4,8 +4,8 @@ import psutil
|
|||||||
import platform
|
import platform
|
||||||
import time
|
import time
|
||||||
import httpx
|
import httpx
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter, Query
|
||||||
from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID
|
from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, VOLUME_ROOT
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@@ -54,3 +54,17 @@ def system_stats():
|
|||||||
"uptime": f"{days}d {hours}h",
|
"uptime": f"{days}d {hours}h",
|
||||||
"platform": platform.platform(),
|
"platform": platform.platform(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/audit-log")
|
||||||
|
def audit_log(lines: int = Query(100, le=500)):
|
||||||
|
log_path = os.path.join(VOLUME_ROOT, "docker/nas-dashboard/audit.log")
|
||||||
|
if not os.path.exists(log_path):
|
||||||
|
return {"lines": []}
|
||||||
|
with open(log_path, "rb") as f:
|
||||||
|
f.seek(0, 2)
|
||||||
|
size = f.tell()
|
||||||
|
buf = min(size, lines * 200)
|
||||||
|
f.seek(max(0, size - buf))
|
||||||
|
data = f.read().decode(errors="replace").splitlines()
|
||||||
|
return {"lines": data[-lines:]}
|
||||||
|
|||||||
@@ -113,6 +113,18 @@
|
|||||||
}
|
}
|
||||||
saving = false;
|
saving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let auditLines = $state([]);
|
||||||
|
let auditLoading = $state(false);
|
||||||
|
|
||||||
|
async function loadAuditLog() {
|
||||||
|
auditLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await get("/system/audit-log?lines=100");
|
||||||
|
auditLines = res.lines.reverse();
|
||||||
|
} catch {}
|
||||||
|
auditLoading = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
@@ -189,4 +201,20 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white rounded-xl border border-surface-200 p-6 shadow-sm">
|
||||||
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
<h3 class="text-sm font-semibold text-surface-700">Audit Log</h3>
|
||||||
|
<button onclick={loadAuditLog} disabled={auditLoading} class="px-3 py-1.5 text-xs font-medium text-primary-600 bg-primary-50 hover:bg-primary-100 rounded-lg transition-colors disabled:opacity-50">
|
||||||
|
{auditLoading ? "Loading..." : auditLines.length ? "Refresh" : "Load"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if auditLines.length > 0}
|
||||||
|
<div class="max-h-80 overflow-auto rounded-lg bg-surface-950 p-3">
|
||||||
|
<pre class="text-xs text-surface-300 font-mono whitespace-pre leading-5">{auditLines.join('\n')}</pre>
|
||||||
|
</div>
|
||||||
|
{:else if !auditLoading}
|
||||||
|
<p class="text-sm text-surface-400">Click Load to view recent audit log entries</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user