diff --git a/client/src/App.tsx b/client/src/App.tsx index f5eb4cd..c21b25f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,53 +1,4 @@ -import { useState, useEffect } from "react"; -import { Switch, Route, useLocation } from "wouter"; -import { Toaster } from "@/components/ui/toaster"; -import NotFound from "@/pages/not-found"; -import AuthPage from "@/pages/auth-page"; -import DashboardPage from "@/pages/dashboard-page"; -import UsersPage from "@/pages/users-page"; -import GroupsPage from "@/pages/groups-page"; -import OUsPage from "@/pages/ous-page"; -import ComputersPage from "@/pages/computers-page"; -import DomainsPage from "@/pages/domains-page"; -import ApiTokensPage from "@/pages/api-tokens-page"; -import LdapConnectionsPage from "@/pages/ldap-connections-page"; -import LdapQueryBuilderPage from "@/pages/ldap-query-builder-page"; -import SettingsPage from "@/pages/settings-page"; -import UserManagementPage from "@/pages/user-management-page"; -import AuditLogsPage from "@/pages/audit-logs-page"; -import { ProtectedRoute } from "./lib/protected-route"; -import { Loader2 } from "lucide-react"; - -function Router() { - return ( - - - - - - - - - - - - - - - - - - - ); +// This file is a placeholder - all the app logic is now in main.tsx +export default function App() { + return null; } - -function App() { - return ( - <> - - - - ); -} - -export default App; diff --git a/client/src/layouts/dashboard-layout.tsx b/client/src/layouts/dashboard-layout.tsx index d83c4ff..bbdbf21 100644 --- a/client/src/layouts/dashboard-layout.tsx +++ b/client/src/layouts/dashboard-layout.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useContext } from "react"; import { Link, useLocation } from "wouter"; import { Button } from "@/components/ui/button"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; @@ -33,6 +33,7 @@ import { } from "lucide-react"; import { useMobile } from "@/hooks/use-mobile"; import { useToast } from "@/hooks/use-toast"; +import { AuthContext } from "@/hooks/use-auth"; import { ThemeToggle } from "@/components/theme-toggle"; type MenuItem = { @@ -46,14 +47,6 @@ type MenuSection = { items: MenuItem[]; }; -type UserType = { - id: number; - username: string; - fullName?: string; - email?: string; - role?: string; -}; - const menuSections: MenuSection[] = [ { title: "Active Directory", @@ -88,57 +81,20 @@ export function DashboardLayout({ children, title, description }: DashboardLayou const [location, navigate] = useLocation(); const isMobile = useMobile(); const [sidebarOpen, setSidebarOpen] = useState(!isMobile); - const [user, setUser] = useState(null); + const auth = useContext(AuthContext); + if (!auth) { + console.error("Auth context not available"); + return
Authentication error. Please refresh the page.
; + } + const { user, logoutMutation } = auth; const { toast } = useToast(); - // Fetch user data on component mount - useEffect(() => { - const fetchUserData = async () => { - try { - const response = await fetch('/api/user', { - credentials: 'include' - }); - - if (response.ok) { - const userData = await response.json(); - setUser(userData); - } - } catch (error) { - console.error('Error fetching user data:', error); - } - }; - - fetchUserData(); - }, []); - const handleLogout = async () => { - try { - const response = await fetch('/api/logout', { - method: 'POST', - credentials: 'include' - }); - - if (response.ok) { - toast({ - title: "Logged out", - description: "You have been successfully logged out.", - }); + logoutMutation.mutate(undefined, { + onSuccess: () => { navigate('/auth'); - } else { - toast({ - title: "Logout failed", - description: "An error occurred during logout.", - variant: "destructive", - }); } - } catch (error) { - console.error('Error during logout:', error); - toast({ - title: "Logout failed", - description: "An error occurred during logout.", - variant: "destructive", - }); - } + }); }; // Get user initials for avatar diff --git a/client/src/lib/protected-route.tsx b/client/src/lib/protected-route.tsx index a2b91f3..a1d426b 100644 --- a/client/src/lib/protected-route.tsx +++ b/client/src/lib/protected-route.tsx @@ -1,6 +1,6 @@ -import { useState, useEffect } from "react"; -import { Loader2 } from "lucide-react"; import { Redirect, Route } from "wouter"; +import { useAuth } from "@/hooks/use-auth"; +import { Loader2 } from "lucide-react"; export function ProtectedRoute({ path, @@ -9,30 +9,10 @@ export function ProtectedRoute({ path: string; component: () => React.JSX.Element; }) { - const [isAuthenticated, setIsAuthenticated] = useState(null); - - useEffect(() => { - const checkAuth = async () => { - try { - const response = await fetch('/api/user', { - credentials: 'include' - }); - - if (response.ok) { - setIsAuthenticated(true); - } else { - setIsAuthenticated(false); - } - } catch (error) { - console.error('Error checking auth status:', error); - setIsAuthenticated(false); - } - }; - - checkAuth(); - }, []); + const { user, isLoading } = useAuth(); - if (isAuthenticated === null) { + // Show a loading indicator while authentication state is being determined + if (isLoading) { return (
@@ -42,7 +22,8 @@ export function ProtectedRoute({ ); } - if (!isAuthenticated) { + // Redirect to auth page if user is not authenticated + if (!user) { return ( @@ -50,6 +31,7 @@ export function ProtectedRoute({ ); } + // Render the component if the user is authenticated return ( diff --git a/client/src/main.tsx b/client/src/main.tsx index 48d6243..108e4d7 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -1,17 +1,93 @@ import { createRoot } from "react-dom/client"; import { QueryClientProvider } from "@tanstack/react-query"; -import App from "./App"; +import { Toaster } from "@/components/ui/toaster"; +import { Switch, Route, Redirect } from "wouter"; +import { Loader2 } from "lucide-react"; +import NotFound from "@/pages/not-found"; +import AuthPage from "@/pages/auth-page"; +import DashboardPage from "@/pages/dashboard-page"; +import UsersPage from "@/pages/users-page"; +import GroupsPage from "@/pages/groups-page"; +import OUsPage from "@/pages/ous-page"; +import ComputersPage from "@/pages/computers-page"; +import DomainsPage from "@/pages/domains-page"; +import ApiTokensPage from "@/pages/api-tokens-page"; +import LdapConnectionsPage from "@/pages/ldap-connections-page"; +import LdapQueryBuilderPage from "@/pages/ldap-query-builder-page"; +import SettingsPage from "@/pages/settings-page"; +import UserManagementPage from "@/pages/user-management-page"; +import AuditLogsPage from "@/pages/audit-logs-page"; import "./index.css"; -import { AuthProvider } from "./hooks/use-auth"; +import { AuthProvider, useAuth } from "./hooks/use-auth"; import { ThemeProvider } from "./hooks/use-theme"; import { queryClient } from "./lib/queryClient"; -createRoot(document.getElementById("root")!).render( - - - - - - - -); +// Create the App and use context appropriately +function App() { + return ( + <> + + + + + + + + + + ); +} + +// Protected route component that uses the useAuth hook +function ProtectedRoute({ + path, + component: Component +}: { + path: string; + component: () => React.JSX.Element; +}) { + const { user } = useAuth(); + + return ( + + {user ? : } + + ); +} + +// App content with routes that can safely use the useAuth hook +function AppContent() { + const { isLoading } = useAuth(); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( + + + + + + + + + + + + + + + + + + + ); +} + +// Render the app +createRoot(document.getElementById("root")!).render(); diff --git a/client/src/pages/auth-page.tsx b/client/src/pages/auth-page.tsx index 1b8eb6b..d1c735c 100644 --- a/client/src/pages/auth-page.tsx +++ b/client/src/pages/auth-page.tsx @@ -1,9 +1,8 @@ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useLocation } from "wouter"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useMutation } from "@tanstack/react-query"; import { Card, CardContent, @@ -24,7 +23,7 @@ import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Checkbox } from "@/components/ui/checkbox"; import { insertUserSchema } from "@shared/schema"; -import { apiRequest } from "@/lib/queryClient"; +import { useAuth } from "@/hooks/use-auth"; import { useToast } from "@/hooks/use-toast"; // Login form schema @@ -54,73 +53,19 @@ type RegisterFormValues = z.infer; export default function AuthPage() { const [location, navigate] = useLocation(); const { toast } = useToast(); - const [isChecking, setIsChecking] = useState(true); - - // Check if user is already logged in + const { user, isLoading, loginMutation, registerMutation } = useAuth(); + + // Redirect if user is already logged in useEffect(() => { - const checkAuth = async () => { - try { - const response = await fetch('/api/user', { - credentials: 'include' - }); - - if (response.ok) { - // User is already logged in, redirect to home - navigate('/'); - } - } catch (error) { - console.error('Error checking auth status:', error); - } finally { - setIsChecking(false); - } - }; - - checkAuth(); - }, [navigate]); - - // Login mutation - const loginMutation = useMutation({ - mutationFn: async (credentials: LoginFormValues) => { - const res = await apiRequest("POST", "/api/login", credentials); - return await res.json(); - }, - onSuccess: (user) => { - toast({ - title: "Login successful", - description: `Welcome back, ${user.username}!`, - }); + if (user) { navigate('/'); - }, - onError: (error: Error) => { - toast({ - title: "Login failed", - description: error.message, - variant: "destructive", - }); - }, - }); + } + }, [user, navigate]); - // Register mutation - const registerMutation = useMutation({ - mutationFn: async (credentials: any) => { - const res = await apiRequest("POST", "/api/register", credentials); - return await res.json(); - }, - onSuccess: (user) => { - toast({ - title: "Registration successful", - description: `Welcome, ${user.username}!`, - }); - navigate('/'); - }, - onError: (error: Error) => { - toast({ - title: "Registration failed", - description: error.message, - variant: "destructive", - }); - }, - }); + // If still checking authentication status, show nothing + if (isLoading) { + return null; + } // Login form const loginForm = useForm({