gigafibre-fsm/apps/ops/src/App.vue
louispaulb 7b54e87a59 fix(ops): overlay accès — message exact « n'a pas pu charger » + détail erreur + piste extension
L'overlay disait à tort « pas de permissions » alors que le compte y a droit et que
le fetch /auth/permissions échoue (blocage client). Message corrigé : « OPS n'a pas pu
charger les permissions » + affiche le détail technique (usePermissions.error) + suggère
fenêtre privée/autre navigateur (une extension bloque souvent /auth/permissions). Rend
chaque capture d'écran auto-diagnostique.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 17:31:41 -04:00

59 lines
3.4 KiB
Vue

<template>
<router-view />
<!-- « FAIL-LOUD » : les permissions OPS n'ont pas chargé (mauvais compte / identité Authentik non transmise).
On affiche un message CLAIR avec le compte réellement reçu, au lieu d'une coquille vide (menu blanc) qu'on
prenait à tort pour un bug de token/session. Inerte en dev local (profil permissif). -->
<div v-if="showAccessError" class="ops-access-error">
<div class="ops-access-card">
<q-icon name="person_off" size="44px" color="negative" />
<div class="text-h6 q-mt-sm">Accès OPS indisponible</div>
<div class="text-body2 text-grey-7 q-mt-sm" style="max-width:400px;line-height:1.5">
<template v-if="authIdentity">
OPS n'a pas pu charger les permissions de <b>{{ authIdentity }}</b> (le compte y a pourtant droit).
<div class="q-mt-sm">Souvent une <b>extension</b> (bloqueur de pub/vie privée) ou un proxy qui bloque la requête
<code>/auth/permissions</code> : essaie une <b>fenêtre privée</b> ou un <b>autre navigateur</b>.</div>
</template>
<template v-else>
Authentik n'a pas transmis ton identité (session incomplète). Reconnecte-toi via
<b>erp.gigafibre.ca/ops</b>.
</template>
<div v-if="permsError" class="text-caption text-negative q-mt-sm" style="font-family:monospace">Détail : {{ permsError }}</div>
</div>
<div class="row q-gutter-sm q-mt-md justify-center">
<q-btn outline no-caps color="grey-8" icon="logout" label="Changer de compte" @click="auth.doLogout()" />
<q-btn unelevated no-caps color="primary" icon="refresh" label="Recharger" @click="reload" />
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted } from 'vue'
import { useAuthStore } from 'src/stores/auth'
import { usePermissions } from 'src/composables/usePermissions'
import { loadSavedTheme } from 'src/composables/useTheme'
import { startSessionKeepAlive } from 'src/composables/useSessionKeepAlive'
loadSavedTheme() // applique le thème enregistré (couleurs --ops-*) dès le démarrage
const auth = useAuthStore()
const { isLoaded, loading: permsLoading, error: permsError } = usePermissions()
const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'
// PROD uniquement : une fois le contrôle de session ET le chargement des permissions terminés, si aucune
// permission n'a chargé → accès indisponible (mauvais compte / identité vide) → overlay clair.
const showAccessError = computed(() => !isLocal && !auth.loading && !permsLoading.value && !isLoaded.value)
// Le compte réellement transmis à OPS (courriel whoami) — clé du diagnostic : « mauvais compte ? ».
const authIdentity = computed(() => (auth.user && auth.user !== 'authenticated') ? auth.user : '')
function reload () { window.location.reload() }
onMounted(() => {
auth.checkSession()
startSessionKeepAlive() // garde la session Authentik vivante (ping /auth/whoami /4 min + au retour d'onglet)
})
</script>
<style>
.ops-access-error { position: fixed; inset: 0; z-index: 99999; display: flex; align-items: center; justify-content: center; background: rgba(15, 23, 42, 0.55); backdrop-filter: blur(2px); }
.ops-access-card { background: #fff; border-radius: 14px; padding: 28px 32px; text-align: center; box-shadow: 0 12px 40px rgba(0,0,0,0.25); display: flex; flex-direction: column; align-items: center; max-width: 92vw; }
</style>