Add confirmed audit reversals
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
<script lang="ts">
|
||||
import KpiFilters from '$lib/components/KpiFilters.svelte';
|
||||
import PendingForm from '$lib/components/PendingForm.svelte';
|
||||
import RegistryPagination from '$lib/components/RegistryPagination.svelte';
|
||||
let { data } = $props();
|
||||
let { data, form } = $props();
|
||||
let confirming = $state<any>(null);
|
||||
let handledResultToken = $state('');
|
||||
const date = (value: unknown) => new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'medium' }).format(new Date(String(value)));
|
||||
const pretty = (value: unknown) => {
|
||||
if (!value) return 'NO SNAPSHOT';
|
||||
try { return JSON.stringify(JSON.parse(String(value)), null, 2); } catch { return String(value); }
|
||||
};
|
||||
$effect(() => {
|
||||
if (form?.reverted && form.resultToken && form.resultToken !== handledResultToken) {
|
||||
handledResultToken = form.resultToken;
|
||||
confirming = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head><title>Audit history — ISAC</title></svelte:head>
|
||||
@@ -30,6 +39,20 @@
|
||||
<details class="audit-entry">
|
||||
<summary class="dashboard-row audit-row"><div><strong>{String(entry.action).toUpperCase()}</strong><small>{String(entry.entity_type).replaceAll('_',' ').toUpperCase()}</small></div><div><strong>{entry.actor_name}</strong><small>{entry.actor_login ?? entry.actor_id}</small></div><div><strong>{entry.entity_id}</strong><small>EVENT {String(entry.id).slice(0,8).toUpperCase()}</small></div><span>{date(entry.created_at)}</span><b>DETAILS +</b></summary>
|
||||
<div class="audit-comparison"><section><span>BEFORE</span><pre>{pretty(entry.before_json)}</pre></section><section><span>AFTER</span><pre>{pretty(entry.after_json)}</pre></section></div>
|
||||
{#if entry.reversible}<div class="audit-revert-bar"><span>SUPPORTED COMPENSATING ACTION · CURRENT STATE WILL BE VERIFIED FIRST</span><button class="danger" type="button" onclick={() => confirming = entry}>ATTEMPT REVERT</button></div>
|
||||
{:else if entry.reverted}<div class="audit-revert-bar completed"><span>THIS EVENT HAS ALREADY BEEN REVERTED</span></div>{/if}
|
||||
</details>
|
||||
{:else}<div class="empty-dashboard"><strong>NO AUDIT EVENTS FOUND</strong><span>Adjust the category, action, or search value.</span></div>{/each}
|
||||
</div>
|
||||
|
||||
{#if confirming}
|
||||
<div class="isac-modal-backdrop" role="presentation">
|
||||
<div class="isac-confirm-modal audit-revert-modal" role="dialog" aria-modal="true" aria-labelledby="revert-title">
|
||||
<div class="editor-title"><div><p class="eyebrow">CONFIRM COMPENSATING ACTION</p><h3 id="revert-title">REVERT {String(confirming.action).toUpperCase()}?</h3></div><button aria-label="Close confirmation" onclick={() => confirming = null}>×</button></div>
|
||||
<p>This does not erase history. ISAC will first verify that target <code>{confirming.entity_id}</code> still matches this event’s resulting state. If it has newer changes, the revert will be blocked.</p>
|
||||
<div class="audit-revert-summary"><div><span>ORIGINAL ACTION</span><b>{confirming.action}</b></div><div><span>ORIGINAL OPERATOR</span><b>{confirming.actor_name}</b></div><div><span>EVENT</span><b>{confirming.id}</b></div></div>
|
||||
{#if form?.revertError}<p class="error">{form.revertError}</p>{/if}
|
||||
<PendingForm action="?/revert">{#snippet children(pending)}<input type="hidden" name="eventId" value={confirming.id}/><div class="form-actions"><button class="secondary" type="button" onclick={() => confirming = null} disabled={pending}>CANCEL</button><button class="primary" aria-busy={pending} disabled={pending}>{pending ? 'VERIFYING STATE…' : 'CONFIRM REVERT →'}</button></div>{/snippet}</PendingForm>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user