feat(02-06): auth layout switching + admin role guard (GAPs 2, 3, 4)
- App.vue: conditionally renders AuthLayout for auth routes, app shell otherwise - router/index.js: meta.layout='auth' on all four auth routes - router/index.js: meta.requiresAdmin=true on /admin route - router/index.js: beforeEach role check redirects non-admin to / - router/index.js: /account redirects to /settings
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="flex h-screen overflow-hidden">
|
||||
<AuthLayout v-if="route.meta.layout === 'auth'" />
|
||||
<div v-else class="flex h-screen overflow-hidden">
|
||||
<AppSidebar />
|
||||
<main class="flex-1 overflow-y-auto">
|
||||
<router-view />
|
||||
@@ -8,10 +9,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AppSidebar from './components/layout/AppSidebar.vue'
|
||||
import { useTopicsStore } from './stores/topics.js'
|
||||
import { onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import AppSidebar from './components/layout/AppSidebar.vue'
|
||||
import AuthLayout from './layouts/AuthLayout.vue'
|
||||
import { useTopicsStore } from './stores/topics.js'
|
||||
|
||||
const route = useRoute()
|
||||
const topicsStore = useTopicsStore()
|
||||
onMounted(() => topicsStore.fetchTopics())
|
||||
</script>
|
||||
|
||||
@@ -19,27 +19,27 @@ const routes = [
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('../views/auth/LoginView.vue'),
|
||||
meta: { public: true },
|
||||
meta: { public: true, layout: 'auth' },
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
component: () => import('../views/auth/RegisterView.vue'),
|
||||
meta: { public: true },
|
||||
meta: { public: true, layout: 'auth' },
|
||||
},
|
||||
{
|
||||
path: '/password-reset',
|
||||
component: () => import('../views/auth/PasswordResetView.vue'),
|
||||
meta: { public: true },
|
||||
meta: { public: true, layout: 'auth' },
|
||||
},
|
||||
{
|
||||
path: '/password-reset/confirm',
|
||||
component: () => import('../views/auth/NewPasswordView.vue'),
|
||||
meta: { public: true },
|
||||
meta: { public: true, layout: 'auth' },
|
||||
},
|
||||
|
||||
// Phase 2 — authenticated routes
|
||||
{ path: '/account', component: () => import('../views/AccountView.vue') },
|
||||
{ path: '/admin', component: () => import('../views/AdminView.vue') },
|
||||
{ path: '/account', redirect: '/settings' },
|
||||
{ path: '/admin', component: () => import('../views/AdminView.vue'), meta: { requiresAdmin: true } },
|
||||
|
||||
// Cloud storage overview and folder browser
|
||||
{
|
||||
@@ -87,6 +87,10 @@ router.beforeEach(async (to) => {
|
||||
return { path: '/login', query: { redirect: to.fullPath } }
|
||||
}
|
||||
}
|
||||
|
||||
if (to.meta.requiresAdmin && authStore.user?.role !== 'admin') {
|
||||
return { path: '/' }
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
Reference in New Issue
Block a user