feat(audit) : envoie un device id persistant sur les requêtes API
This commit is contained in:
@@ -80,6 +80,14 @@ export const useApi = (): ApiClient => {
|
|||||||
baseURL,
|
baseURL,
|
||||||
retry: 0,
|
retry: 0,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
|
onRequest({ options }) {
|
||||||
|
const deviceId = useDeviceId()
|
||||||
|
if (deviceId) {
|
||||||
|
const headers = new Headers(options.headers as HeadersInit | undefined)
|
||||||
|
headers.set('X-Device-Id', deviceId)
|
||||||
|
options.headers = headers
|
||||||
|
}
|
||||||
|
},
|
||||||
onResponse({ options, response }) {
|
onResponse({ options, response }) {
|
||||||
const apiOptions = options as ApiFetchOptions<'json'>
|
const apiOptions = options as ApiFetchOptions<'json'>
|
||||||
if (apiOptions?.toast === false) {
|
if (apiOptions?.toast === false) {
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Stable per-device identifier used to add forensic context to audit logs.
|
||||||
|
// Persisted in localStorage so the same browser/device reuses it across sessions.
|
||||||
|
// NOTE: this identifies a device/browser, not a human — on a shared kiosk every
|
||||||
|
// user of the same browser shares one id (intended: it distinguishes devices).
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'sirh-device-id'
|
||||||
|
let cached: string | null = null
|
||||||
|
|
||||||
|
export const useDeviceId = (): string | null => {
|
||||||
|
if (!import.meta.client) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (cached) {
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let id = localStorage.getItem(STORAGE_KEY)
|
||||||
|
if (!id) {
|
||||||
|
id = crypto.randomUUID()
|
||||||
|
localStorage.setItem(STORAGE_KEY, id)
|
||||||
|
}
|
||||||
|
cached = id
|
||||||
|
return id
|
||||||
|
} catch {
|
||||||
|
// localStorage unavailable (private mode, disabled) — degrade gracefully.
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user