fix(06.2): CR-04 WR-05 audit export functions use 401-refresh-retry and safe URL.revokeObjectURL

This commit is contained in:
curo1305
2026-06-01 14:26:05 +02:00
parent 792d4639d1
commit 3fa7e8b866
+35 -19
View File
@@ -395,7 +395,7 @@ export function adminListAuditLog({ start, end, user_handle, event_type, page =
* the endpoint can authenticate the request (D-13, T-06.2-04-03).
* Must NOT call res.json() — CSV is text/csv (Pitfall 5).
*/
export async function adminExportAuditLogCsv(params = {}) {
export async function adminExportAuditLogCsv(params = {}, _retry = false) {
const { useAuthStore } = await import('../stores/auth.js')
const authStore = useAuthStore()
@@ -414,6 +414,18 @@ export async function adminExportAuditLogCsv(params = {}) {
headers,
credentials: 'include',
})
if (res.status === 401 && !_retry) {
try {
await authStore.refresh()
return adminExportAuditLogCsv(params, true)
} catch {
authStore.accessToken = null
authStore.user = null
throw new Error('Session expired')
}
}
if (!res.ok) throw new Error(`Export failed: ${res.status}`)
const text = await res.text()
@@ -422,8 +434,10 @@ export async function adminExportAuditLogCsv(params = {}) {
const a = document.createElement('a')
a.href = url
a.download = 'audit-export.csv'
document.body.appendChild(a)
a.click()
URL.revokeObjectURL(url)
document.body.removeChild(a)
setTimeout(() => URL.revokeObjectURL(url), 1000)
}
/**
@@ -431,22 +445,10 @@ export async function adminExportAuditLogCsv(params = {}) {
*
* Returns: { items: [{ date: "YYYY-MM-DD", key: "audit-logs/YYYY-MM-DD.csv" }] }
* Items are sorted descending by date.
* Routes through request() which has built-in 401-refresh-retry logic.
*/
export async function adminListDailyExports() {
const { useAuthStore } = await import('../stores/auth.js')
const authStore = useAuthStore()
const headers = {}
if (authStore.accessToken) {
headers['Authorization'] = `Bearer ${authStore.accessToken}`
}
const res = await fetch('/api/admin/audit-log/daily-exports', {
headers,
credentials: 'include',
})
if (!res.ok) throw new Error(`Failed to list daily exports: ${res.status}`)
return res.json()
export function adminListDailyExports() {
return request('/api/admin/audit-log/daily-exports')
}
/**
@@ -457,7 +459,7 @@ export async function adminListDailyExports() {
*
* @param {string} date — YYYY-MM-DD format date string
*/
export async function adminDownloadDailyExport(date) {
export async function adminDownloadDailyExport(date, _retry = false) {
const { useAuthStore } = await import('../stores/auth.js')
const authStore = useAuthStore()
@@ -470,6 +472,18 @@ export async function adminDownloadDailyExport(date) {
headers,
credentials: 'include',
})
if (res.status === 401 && !_retry) {
try {
await authStore.refresh()
return adminDownloadDailyExport(date, true)
} catch {
authStore.accessToken = null
authStore.user = null
throw new Error('Session expired')
}
}
if (!res.ok) throw new Error(`Download failed: ${res.status}`)
const text = await res.text()
@@ -478,8 +492,10 @@ export async function adminDownloadDailyExport(date) {
const a = document.createElement('a')
a.href = url
a.download = `audit-${date}.csv`
document.body.appendChild(a)
a.click()
URL.revokeObjectURL(url)
document.body.removeChild(a)
setTimeout(() => URL.revokeObjectURL(url), 1000)
}
// ── Document content proxy URL ────────────────────────────────────────────────