fix(ops): retry permission load (superuser plus jamais bloqué par un échec transitoire au boot)
Symptôme (overlay fail-loud confirmé) : « OPS a reçu louis@targo.ca mais pas de permissions », alors que le compte EST superuser (is_superuser=True, admin+sysadmin, vérifié live) et que le hub renvoie 200 (6/6, ~0,14 s). La recherche (même base /hub, appelée plus tard) marche → seul le 1er appel /hub au démarrage (checkSession) échoue = course de boot / session pas encore « chaude ». Fix : loadPermissions réessaie jusqu'à 4× (backoff 0,7→2,1 s, cache:no-store) avant de conclure « pas d'accès ». Un échec transitoire ne verrouille plus l'app derrière un menu vide / overlay. (Les droits sont dans Authentik : groupes admin/sysadmin + is_superuser, inchangés — ce n'était ni le jeton ni les droits.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e6ac8b11ef
commit
f5d8d38b1e
|
|
@ -29,26 +29,31 @@ async function loadPermissions (email, username) {
|
|||
const qs = new URLSearchParams()
|
||||
if (email) qs.set('email', email)
|
||||
if (username) qs.set('username', username)
|
||||
fetchPromise = fetch(`${HUB_URL}/auth/permissions?${qs.toString()}`)
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Permission fetch failed: ' + r.status)
|
||||
return r.json()
|
||||
})
|
||||
.then(data => {
|
||||
const url = `${HUB_URL}/auth/permissions?${qs.toString()}`
|
||||
const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
|
||||
|
||||
// RÉSILIENCE : le tout 1er appel /hub au démarrage échoue parfois (session pas encore « chaude » / course au boot)
|
||||
// alors que les appels /hub suivants (ex. recherche) passent. On RÉESSAIE (jusqu'à 4 tentatives, backoff 0,7→2,1 s)
|
||||
// avant de conclure « pas d'accès » → un superuser n'est plus bloqué par un échec transitoire (le vrai bug observé).
|
||||
async function attempt (n) {
|
||||
try {
|
||||
const r = await fetch(url, { cache: 'no-store' })
|
||||
if (!r.ok) throw new Error('HTTP ' + r.status)
|
||||
const data = await r.json()
|
||||
permissions.value = data
|
||||
})
|
||||
.catch(e => {
|
||||
console.error('[usePermissions]', e.message)
|
||||
error.value = null
|
||||
} catch (e) {
|
||||
if (n < 4) { await new Promise(res => setTimeout(res, 700 * n)); return attempt(n + 1) }
|
||||
console.error('[usePermissions] load failed after retries:', e.message)
|
||||
error.value = e.message
|
||||
// DEV local (pas de hub devant) : le fetch échoue → on débloque l'app avec un profil permissif
|
||||
// pour pouvoir prévisualiser/auditer toutes les pages. En PROD on reste null (= restrictif/sûr).
|
||||
const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
|
||||
// DEV local (pas de hub devant) : profil permissif pour prévisualiser/auditer ; PROD → null (App.vue « fail-loud »).
|
||||
permissions.value = isLocal ? { email, is_superuser: true, capabilities: {}, groups: ['admin'] } : null
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
fetchPromise = null
|
||||
})
|
||||
}
|
||||
}
|
||||
fetchPromise = attempt(1).finally(() => {
|
||||
loading.value = false
|
||||
fetchPromise = null
|
||||
})
|
||||
|
||||
return fetchPromise
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user