Adds in authentication system and overhauls the navigation bar to be built dynamically.
This commit is contained in:
parent
7e98b5345d
commit
28c054de22
21 changed files with 1531 additions and 56 deletions
|
@ -1,6 +1,7 @@
|
|||
import { defineRouter } from '#q-app/wrappers'
|
||||
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||
import routes from './routes'
|
||||
import { useAuthStore } from 'stores/auth'; // Import the auth store
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
|
@ -11,7 +12,7 @@ import routes from './routes'
|
|||
* with the Router instance.
|
||||
*/
|
||||
|
||||
export default defineRouter(function (/* { store, ssrContext } */) {
|
||||
export default defineRouter(function ({ store /* { store, ssrContext } */ }) {
|
||||
const createHistory = process.env.SERVER
|
||||
? createMemoryHistory
|
||||
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory)
|
||||
|
@ -26,5 +27,45 @@ export default defineRouter(function (/* { store, ssrContext } */) {
|
|||
history: createHistory(process.env.VUE_ROUTER_BASE)
|
||||
})
|
||||
|
||||
// Navigation Guard using Pinia store
|
||||
Router.beforeEach(async (to, from, next) => {
|
||||
const authStore = useAuthStore(store); // Get store instance
|
||||
|
||||
// Ensure auth status is checked, especially on first load or refresh
|
||||
// This check might be better placed in App.vue or a boot file
|
||||
if (!authStore.user && !authStore.loading) { // Check only if user is not loaded and not already loading
|
||||
try {
|
||||
await authStore.checkAuthStatus();
|
||||
} catch (e) {
|
||||
console.error("Initial auth check failed", e);
|
||||
// Decide how to handle initial check failure (e.g., proceed, redirect to error page)
|
||||
}
|
||||
}
|
||||
|
||||
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
|
||||
const publicPages = ['/login', '/register'];
|
||||
const isPublicPage = publicPages.includes(to.path);
|
||||
const isAuthenticated = authStore.isAuthenticated; // Get status from store
|
||||
|
||||
console.log('Store Auth status:', isAuthenticated);
|
||||
console.log('Navigating to:', to.path);
|
||||
console.log('Requires auth:', requiresAuth);
|
||||
console.log('Is public page:', isPublicPage);
|
||||
|
||||
if (requiresAuth && !isAuthenticated) {
|
||||
// If route requires auth and user is not authenticated, redirect to login
|
||||
console.log('Redirecting to login (requires auth, not authenticated)');
|
||||
next('/login');
|
||||
} else if (isPublicPage && isAuthenticated) {
|
||||
// If user is authenticated and tries to access login/register, redirect to home
|
||||
console.log('Redirecting to home (public page, authenticated)');
|
||||
next('/');
|
||||
} else {
|
||||
// Otherwise, allow navigation
|
||||
console.log('Allowing navigation');
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
return Router
|
||||
})
|
||||
|
|
|
@ -3,15 +3,101 @@ const routes = [
|
|||
path: '/',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
children: [
|
||||
{ path: '', name: 'home', component: () => import('pages/FormListPage.vue') },
|
||||
{ path: 'forms', name: 'formList', component: () => import('pages/FormListPage.vue') },
|
||||
{ path: 'forms/new', name: 'formCreate', component: () => import('pages/FormCreatePage.vue') },
|
||||
{ path: 'forms/:id/edit', name: 'formEdit', component: () => import('pages/FormEditPage.vue'), props: true },
|
||||
{ path: 'forms/:id/fill', name: 'formFill', component: () => import('pages/FormFillPage.vue'), props: true },
|
||||
{ path: 'forms/:id/responses', name: 'formResponses', component: () => import('pages/FormResponsesPage.vue'), props: true },
|
||||
{ path: 'mantis-summaries', name: 'mantisSummaries', component: () => import('pages/MantisSummariesPage.vue') },
|
||||
{ path: 'email-summaries', name: 'emailSummaries', component: () => import('pages/EmailSummariesPage.vue') },
|
||||
{ path: 'settings', name: 'settings', component: () => import('pages/SettingsPage.vue') }
|
||||
{
|
||||
path: '',
|
||||
name: 'home',
|
||||
component: () => import('pages/LandingPage.vue'),
|
||||
meta: { requiresAuth: false } // Keep home accessible, but don't show in nav
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('pages/LoginPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
navGroup: 'noAuth', // Show only when logged out
|
||||
icon: 'login',
|
||||
title: 'Login',
|
||||
caption: 'Access your account'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
name: 'register',
|
||||
component: () => import('pages/RegisterPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
navGroup: 'noAuth', // Show only when logged out
|
||||
icon: 'person_add',
|
||||
title: 'Register',
|
||||
caption: 'Create an account'
|
||||
}
|
||||
},
|
||||
// Add a new route specifically for managing passkeys when logged in
|
||||
{
|
||||
path: '/passkeys',
|
||||
name: 'passkeys',
|
||||
component: () => import('pages/PasskeyManagementPage.vue'), // Assuming this page exists or will be created
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
navGroup: 'auth', // Show only when logged in
|
||||
icon: 'key',
|
||||
title: 'Passkeys',
|
||||
caption: 'Manage your passkeys'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'forms',
|
||||
name: 'formList',
|
||||
component: () => import('pages/FormListPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
navGroup: 'auth', // Show only when logged in
|
||||
icon: 'list_alt',
|
||||
title: 'Forms',
|
||||
caption: 'View existing forms'
|
||||
}
|
||||
},
|
||||
{ path: 'forms/new', name: 'formCreate', component: () => import('pages/FormCreatePage.vue'), meta: { requiresAuth: true } }, // Not in nav
|
||||
{ path: 'forms/:id/edit', name: 'formEdit', component: () => import('pages/FormEditPage.vue'), props: true, meta: { requiresAuth: true } }, // Not in nav
|
||||
{ path: 'forms/:id/fill', name: 'formFill', component: () => import('pages/FormFillPage.vue'), props: true, meta: { requiresAuth: true } }, // Not in nav
|
||||
{ path: 'forms/:id/responses', name: 'formResponses', component: () => import('pages/FormResponsesPage.vue'), props: true, meta: { requiresAuth: true } }, // Not in nav
|
||||
{
|
||||
path: 'mantis-summaries',
|
||||
name: 'mantisSummaries',
|
||||
component: () => import('pages/MantisSummariesPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
navGroup: 'auth', // Show only when logged in
|
||||
icon: 'summarize',
|
||||
title: 'Mantis Summaries',
|
||||
caption: 'View daily summaries'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'email-summaries',
|
||||
name: 'emailSummaries',
|
||||
component: () => import('pages/EmailSummariesPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
navGroup: 'auth', // Show only when logged in
|
||||
icon: 'email',
|
||||
title: 'Email Summaries',
|
||||
caption: 'View email summaries'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
name: 'settings',
|
||||
component: () => import('pages/SettingsPage.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
navGroup: 'auth', // Show only when logged in
|
||||
icon: 'settings',
|
||||
title: 'Settings',
|
||||
caption: 'Manage application settings'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue