forked from baron/baron-sso
ory용 MCP 제작, devfront/adminfront 백엔드 연결
This commit is contained in:
143
devfront/src/features/audit/AuditLogsPage.tsx
Normal file
143
devfront/src/features/audit/AuditLogsPage.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
import { Filter, ListChecks, Search, Terminal } from "lucide-react";
|
||||
|
||||
const auditFilters = [
|
||||
"Actor role = admin",
|
||||
"Action = client.rotate_secret",
|
||||
"Tenant = selected header",
|
||||
];
|
||||
|
||||
const auditRows = [
|
||||
{
|
||||
action: "client.create",
|
||||
tenant: "TENANT-12",
|
||||
actor: "ops.jane@baron",
|
||||
result: "ok",
|
||||
ts: "2026-01-26 15:21 KST",
|
||||
},
|
||||
{
|
||||
action: "client.rotate_secret",
|
||||
tenant: "TENANT-12",
|
||||
actor: "ops.jane@baron",
|
||||
result: "ok",
|
||||
ts: "2026-01-26 15:22 KST",
|
||||
},
|
||||
{
|
||||
action: "audit.export",
|
||||
tenant: "TENANT-07",
|
||||
actor: "auditor.lee@baron",
|
||||
result: "rate_limited",
|
||||
ts: "2026-01-26 15:30 KST",
|
||||
},
|
||||
];
|
||||
|
||||
function AuditLogsPage() {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
|
||||
Audit stream
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold">
|
||||
Observe admin actions per tenant
|
||||
</h2>
|
||||
<p className="text-sm text-[var(--color-muted)]">
|
||||
ClickHouse-backed feed. Filter by tenant, actor, action, and
|
||||
rate-limit status. Enforce admin-only access under /admin.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-2 text-sm text-[var(--color-muted)]"
|
||||
>
|
||||
<Filter size={14} />
|
||||
Saved filters
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 rounded-full bg-[var(--color-accent)] px-4 py-2 text-sm font-semibold text-black"
|
||||
>
|
||||
<ListChecks size={14} />
|
||||
Export CSV
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-[1.1fr,0.9fr]">
|
||||
<div className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-5">
|
||||
<div className="flex items-center gap-2 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-3 py-2 text-[var(--color-muted)]">
|
||||
<Search size={14} />
|
||||
<span className="text-sm">
|
||||
Try: tenant:TENANT-12 action:client.*
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-4 space-y-3">
|
||||
{auditFilters.map((filter) => (
|
||||
<span
|
||||
key={filter}
|
||||
className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-1 text-xs text-[var(--color-muted)]"
|
||||
>
|
||||
<Terminal size={12} />
|
||||
{filter}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-5 divide-y divide-[var(--color-border)]">
|
||||
{auditRows.map((row) => (
|
||||
<div
|
||||
key={`${row.action}-${row.ts}`}
|
||||
className="grid grid-cols-[1.2fr,1fr,1fr,1fr] items-center gap-2 py-3 text-sm"
|
||||
>
|
||||
<div className="font-semibold">{row.action}</div>
|
||||
<div className="text-[var(--color-muted)]">{row.tenant}</div>
|
||||
<div className="text-[var(--color-muted)]">{row.actor}</div>
|
||||
<div className="inline-flex items-center gap-2">
|
||||
<span
|
||||
className={`rounded-full px-2 py-1 text-xs ${
|
||||
row.result === "ok"
|
||||
? "bg-[rgba(54,211,153,0.16)] text-[var(--color-accent)]"
|
||||
: "bg-[rgba(249,168,38,0.16)] text-[var(--color-accent-strong)]"
|
||||
}`}
|
||||
>
|
||||
{row.result}
|
||||
</span>
|
||||
<span className="text-[var(--color-muted)]">{row.ts}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-5">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-[var(--color-muted)]">
|
||||
Guard rails
|
||||
</p>
|
||||
<h3 className="mt-1 text-lg font-semibold">Tenant admin only</h3>
|
||||
<p className="text-sm text-[var(--color-muted)]">
|
||||
Enforce Tenant Admin middleware and admin session TTL before
|
||||
surfacing any audit feed. Super Admin role can bypass tenant
|
||||
filter when needed.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-5">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-[var(--color-muted)]">
|
||||
Export rules
|
||||
</p>
|
||||
<h3 className="mt-1 text-lg font-semibold">
|
||||
Rate-limit sensitive exports
|
||||
</h3>
|
||||
<p className="text-sm text-[var(--color-muted)]">
|
||||
Keep export endpoints behind admin-only routes with ClickHouse
|
||||
query limits. Log download attempts with IP, role, and tenant
|
||||
scope.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AuditLogsPage;
|
||||
Reference in New Issue
Block a user