fix(06.2): CR-04 WR-05 audit export functions use 401-refresh-retry and safe URL.revokeObjectURL
This commit is contained in:
+35
-19
@@ -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 ────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user