From fa8e46471dbccf5e945f04f81358a506df0b7932 Mon Sep 17 00:00:00 2001 From: matthieu Date: Wed, 22 Apr 2026 19:36:14 +0200 Subject: [PATCH] fix(frontend) : auto-reset useSidebar et useModules sur 401/logout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les deux composables ont un state singleton au niveau module mais n'etaient reinitialises que dans logout.vue — un 401 silencieux (JWT expire) laissait la sidebar et la liste de modules actifs de l'ancien user visible jusqu'a ce qu'un nouveau login complete `loadSidebar()`. Aligne le pattern sur useAuditLog (deja conforme) : enregistrement automatique sur `onAuthSessionCleared` au niveau module, via une fonction `reset*State()` privee reutilisee par la methode publique `reset*()` exposee dans le composable. Respect de la regle CLAUDE.md : "composables avec state singleton doivent etre reinitialises au logout". Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/shared/composables/useModules.ts | 16 ++++++++++++---- frontend/shared/composables/useSidebar.ts | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/frontend/shared/composables/useModules.ts b/frontend/shared/composables/useModules.ts index 73d7550..20ca187 100644 --- a/frontend/shared/composables/useModules.ts +++ b/frontend/shared/composables/useModules.ts @@ -2,14 +2,23 @@ * Composable de lecture des modules actifs (source : `/api/modules`). * * State singleton au niveau module : `useSidebar` suit la meme convention. - * Chargement idempotent via le flag `loaded`, reset explicite au logout - * (voir pages/logout.vue). + * Chargement idempotent via le flag `loaded`, reset automatique au logout + * via `onAuthSessionCleared` (cf. CLAUDE.md : « composables avec state + * singleton doivent etre reinitialises au logout »). */ import { ref } from 'vue' +import { onAuthSessionCleared } from '~/shared/stores/auth' const activeModuleIds = ref([]) const loaded = ref(false) +function resetModulesState(): void { + activeModuleIds.value = [] + loaded.value = false +} + +onAuthSessionCleared(resetModulesState) + export function useModules() { async function loadModules() { try { @@ -35,8 +44,7 @@ export function useModules() { } function resetModules() { - activeModuleIds.value = [] - loaded.value = false + resetModulesState() } return { diff --git a/frontend/shared/composables/useSidebar.ts b/frontend/shared/composables/useSidebar.ts index adbdbbf..1596ae1 100644 --- a/frontend/shared/composables/useSidebar.ts +++ b/frontend/shared/composables/useSidebar.ts @@ -1,10 +1,23 @@ import { ref } from 'vue' import type { SidebarSection } from '~/shared/types' +import { onAuthSessionCleared } from '~/shared/stores/auth' const sections = ref([]) const disabledRoutes = ref([]) const loaded = ref(false) +function resetSidebarState(): void { + sections.value = [] + disabledRoutes.value = [] + loaded.value = false +} + +// Auto-enregistrement singleton : purge la sidebar sur 401/logout pour +// eviter qu'un nouvel utilisateur logue sur le meme onglet voie transitoirement +// les items de l'ancienne session (cf. CLAUDE.md : « composables avec state +// singleton doivent etre reinitialises au logout »). +onAuthSessionCleared(resetSidebarState) + export function useSidebar() { async function loadSidebar() { try { @@ -31,9 +44,7 @@ export function useSidebar() { } function resetSidebar() { - sections.value = [] - disabledRoutes.value = [] - loaded.value = false + resetSidebarState() } return {