Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion frontend/app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AuthInitializer } from '@/components/auth/AuthInitializer';

const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -14,6 +15,9 @@ const queryClient = new QueryClient({

export function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
<QueryClientProvider client={queryClient}>
<AuthInitializer />
{children}
</QueryClientProvider>
);
}
12 changes: 12 additions & 0 deletions frontend/components/auth/AuthInitializer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import { useEffect } from 'react';
import { useAuthStore } from '@/store/auth.store';

export function AuthInitializer() {
useEffect(() => {
useAuthStore.getState().initialize();
}, []);

return null;
}
30 changes: 21 additions & 9 deletions frontend/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const PROTECTED = [ '/assets', '/departments', '/users'];

const PROTECTED_ROUTES = ['/dashboard', '/assets', '/departments', '/users', '/reports', '/settings'];
const AUTH_PAGES = ['/login', '/register'];

export const middleware = (req: NextRequest) => {
export function middleware(req: NextRequest) {
const token = req.cookies.get('auth-token')?.value;
const { pathname } = req.nextUrl;

const isProtected = PROTECTED.some((route) => pathname.startsWith(route));
const isAuthPage = AUTH_PAGES.includes(pathname);
const isAuthenticated = !!token;
const isProtectedRoute = PROTECTED_ROUTES.some((route) => pathname.startsWith(route));
const isAuthPage = AUTH_PAGES.some((route) => pathname.startsWith(route));

// Redirect root to dashboard
if (pathname === '/') {
return NextResponse.redirect(new URL('/dashboard', req.url));
}

if (isProtected && !token) {
// Redirect unauthenticated users from protected routes to login
if (isProtectedRoute && !isAuthenticated) {
const url = new URL('/login', req.url);
url.searchParams.set('redirect', pathname);
return NextResponse.redirect(url);
}

// if (isAuthPage && token) {
// return NextResponse.redirect(new URL('/dashboard', req.url));
// }
// Redirect authenticated users away from auth pages to dashboard
if (isAuthPage && isAuthenticated) {
return NextResponse.redirect(new URL('/dashboard', req.url));
}

return NextResponse.next();
};
}

export const config = {
matcher: [
'/',
'/dashboard/:path*',
'/assets/:path*',
'/departments/:path*',
'/users/:path*',
'/reports/:path*',
'/settings/:path*',
'/login',
'/register',
],
Expand Down
26 changes: 24 additions & 2 deletions frontend/store/auth.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ interface AuthStore {
user: User | null;
token: string | null;
isAuthenticated: boolean;
isInitialized: boolean;
setAuth: (token: string, user: User) => void;
logout: () => void;
initialize: () => void;
loadAuthFromStorage: () => void;
}

Expand All @@ -25,6 +27,7 @@ export const useAuthStore = create<AuthStore>()(
user: null,
token: null,
isAuthenticated: false,
isInitialized: false,

setAuth: (token: string, user: User) => {
// Store token in localStorage for API calls
Expand Down Expand Up @@ -52,11 +55,29 @@ export const useAuthStore = create<AuthStore>()(
});
},

initialize: () => {
const { isInitialized } = get();
if (isInitialized) return;

const token = localStorage.getItem('token');
if (token) {
const user = JSON.parse(localStorage.getItem('user') || 'null');
if (user) {
set({
token,
user,
isAuthenticated: true,
isInitialized: true,
});
return;
}
}
set({ isInitialized: true });
},

loadAuthFromStorage: () => {
const token = localStorage.getItem('token');
if (token) {
// For now, we'll need to validate the token or decode it
// In a real app, you might want to validate the token on app load
const user = JSON.parse(localStorage.getItem('user') || 'null');
if (user) {
set({
Expand All @@ -74,6 +95,7 @@ export const useAuthStore = create<AuthStore>()(
user: state.user,
token: state.token,
isAuthenticated: state.isAuthenticated,
isInitialized: state.isInitialized,
}),
}
)
Expand Down
Loading