fix: impersonation UX — banner contrast, route blocking, nav filtering

- Banner: white elevated button for contrast, fixed 48px height,
  layout top padding offset so content isn't obscured
- Middleware: allow GET me/profile (viewing), block mutations only;
  add auth/refresh to blocked routes
- Navigation: hide Platform section during impersonation; hide
  org-dependent items when impersonated user has no organisation
- Test: add read-only routes allowed test, auth/refresh blocked test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 02:51:50 +02:00
parent 4df668b5b8
commit 67ce1e9d9d
4 changed files with 64 additions and 37 deletions

View File

@@ -1,22 +1,36 @@
<script lang="ts" setup>
import { orgNavItems, platformNavItems } from '@/navigation/vertical'
import { useAuthStore } from '@/stores/useAuthStore'
import { useImpersonationStore } from '@/stores/useImpersonationStore'
const authStore = useAuthStore()
const impersonationStore = useImpersonationStore()
const hasOrganisation = computed(() => !!authStore.organisations.length)
const navItems = computed(() => {
const orgName = authStore.currentOrganisation?.name ?? 'Beheer'
const orgItems = orgNavItems.map(item => {
let orgItems = orgNavItems.map(item => {
if ('heading' in item && item.heading === 'Beheer') {
return { ...item, heading: orgName }
}
return item
})
if (authStore.isSuperAdmin) {
// During impersonation: hide org-dependent items if user has no organisation
if (impersonationStore.isImpersonating && !hasOrganisation.value) {
orgItems = orgItems.filter(item => {
if ('heading' in item) return false
return 'to' in item && item.to?.name === 'dashboard'
})
}
// Platform items: only for super_admin AND only when NOT impersonating
if (authStore.isSuperAdmin && !impersonationStore.isImpersonating) {
return [...orgItems, ...platformNavItems]
}
return orgItems
})
@@ -35,6 +49,7 @@ import { VerticalNavLayout } from '@layouts'
</script>
<template>
<div :style="{ paddingTop: impersonationStore.isImpersonating ? '48px' : '0' }">
<VerticalNavLayout :nav-items="navItems">
<!-- 👉 Organisation switcher -->
<template #before-vertical-nav-items>
@@ -82,4 +97,5 @@ import { VerticalNavLayout } from '@layouts'
<!-- 👉 Customizer -->
<!-- <TheCustomizer /> -->
</VerticalNavLayout>
</div>
</template>