diff --git a/app.vue b/app.vue index 7040953..5ac3830 100644 --- a/app.vue +++ b/app.vue @@ -1,5 +1,7 @@ diff --git a/docs/404-and-session-fixes.md b/docs/404-and-session-fixes.md new file mode 100644 index 0000000..54a4eef --- /dev/null +++ b/docs/404-and-session-fixes.md @@ -0,0 +1,100 @@ +# 404 and Session Expiration Fixes + +## Issues Addressed + +1. **404 Error on Expenses Page** - The expenses page was returning a 404 error +2. **Session Expiration After 404** - Users were getting logged out after encountering the 404 error + +## Root Cause Analysis + +### 404 Error Cause +- The expenses page was missing the authorization middleware configuration +- The dashboard layout referenced in the page metadata didn't exist +- Nuxt wasn't properly configured to use layouts + +### Session Expiration Cause +- The authentication middleware was incorrectly clearing the session cache on ALL errors (including 404s) +- This caused a valid session to be invalidated when encountering any page error + +## Fixes Implemented + +### 1. Fixed Expenses Page Metadata +**File**: `pages/dashboard/expenses.vue` + +Added proper middleware configuration: +```javascript +definePageMeta({ + middleware: ['authentication', 'authorization'], + layout: 'dashboard', + roles: ['sales', 'admin'] +}); +``` + +This ensures: +- Authentication is checked first +- Authorization checks for sales/admin roles +- Proper layout is applied + +### 2. Fixed Authentication Middleware +**File**: `middleware/authentication.ts` + +Updated error handling to only clear cache on actual auth errors: +```javascript +onResponseError({ response }) { + // Clear cache only on actual auth errors, not 404s or other errors + if (response.status === 401) { + console.log('[MIDDLEWARE] Unauthorized error detected, clearing cache') + sessionManager.clearCache(); + delete nuxtApp.payload.data?.authState; + } else if (response.status === 403) { + console.log('[MIDDLEWARE] Forbidden error detected, partial cache clear') + // Don't clear cache on 403 as user is authenticated but lacks permissions + } + // Ignore 404s and other errors - they're not authentication issues +} +``` + +### 3. Enabled Layout Support +**File**: `app.vue` + +Updated to support layouts: +```vue + +``` + +### 4. Created Dashboard Layout +**File**: `layouts/dashboard.vue` + +Created a full dashboard layout with: +- Navigation drawer with role-based menu items +- App bar showing user info and role badges +- Proper logout functionality +- Responsive design with rail mode + +## Expected Results + +1. **Expenses page should now load properly** for users with sales or admin roles +2. **404 errors won't cause session expiration** - only actual authentication failures (401) will clear the session +3. **Better error handling** - 403 errors (insufficient permissions) will redirect to dashboard with a message instead of logging out +4. **Consistent layout** across all dashboard pages + +## Testing Steps + +1. Log in with a user that has sales or admin role +2. Navigate to `/dashboard/expenses` +3. Verify the page loads without 404 +4. If you don't have the required role, you should be redirected to dashboard with an error message (not logged out) +5. Try navigating to a non-existent page - you should get a 404 but remain logged in + +## Additional Improvements + +- The authorization middleware now stores error messages that are displayed via toast +- The dashboard layout shows the current user and their role +- Navigation menu dynamically shows/hides items based on user roles +- Session validation continues to work with the 3-minute cache + jitter to prevent race conditions diff --git a/layouts/dashboard.vue b/layouts/dashboard.vue new file mode 100644 index 0000000..096cfde --- /dev/null +++ b/layouts/dashboard.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/middleware/authentication.ts b/middleware/authentication.ts index 944f23c..9e196a2 100644 --- a/middleware/authentication.ts +++ b/middleware/authentication.ts @@ -45,12 +45,16 @@ export default defineNuxtRouteMiddleware(async (to) => { console.log(`[MIDDLEWARE] Retrying auth check (attempt ${retries + 1})`) }, onResponseError({ response }) { - // Clear cache on auth errors - if (response.status === 401 || response.status === 403) { - console.log('[MIDDLEWARE] Auth error detected, clearing cache') + // Clear cache only on actual auth errors, not 404s or other errors + if (response.status === 401) { + console.log('[MIDDLEWARE] Unauthorized error detected, clearing cache') sessionManager.clearCache(); delete nuxtApp.payload.data?.authState; + } else if (response.status === 403) { + console.log('[MIDDLEWARE] Forbidden error detected, partial cache clear') + // Don't clear cache on 403 as user is authenticated but lacks permissions } + // Ignore 404s and other errors - they're not authentication issues } }) as any; diff --git a/pages/dashboard/expenses.vue b/pages/dashboard/expenses.vue index c33f7ed..ef33374 100644 --- a/pages/dashboard/expenses.vue +++ b/pages/dashboard/expenses.vue @@ -346,8 +346,9 @@ const ExpenseCreateModal = defineAsyncComponent(() => import('@/components/Expen // Page meta definePageMeta({ - middleware: ['authentication'], - layout: 'dashboard' + middleware: ['authentication', 'authorization'], + layout: 'dashboard', + roles: ['sales', 'admin'] }); useHead({