From 2f66c2ddcd2c168724b5c52313f6b8f524cee3db Mon Sep 17 00:00:00 2001
From: "gpt-engineer-app[bot]"
<159125892+gpt-engineer-app[bot]@users.noreply.github.com>
Date: Mon, 10 Mar 2025 09:26:18 +0000
Subject: [PATCH] Ensure authenticated access to dashboard
Implement authentication check for dashboard route, redirecting unauthenticated users to the authentication page.
---
src/App.tsx | 90 +++++++++++++++++++++++++-----------
src/contexts/AuthContext.tsx | 21 ++++++++-
src/pages/Auth.tsx | 16 ++++---
3 files changed, 90 insertions(+), 37 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 0cfa1ed..31cab99 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,7 +3,7 @@ import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
-import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
+import { BrowserRouter, Routes, Route, Navigate, useLocation } from "react-router-dom";
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
import Index from "./pages/Index";
import Auth from "./pages/Auth";
@@ -13,48 +13,82 @@ import Header from "./components/Header";
const queryClient = new QueryClient();
-// Protected route component
+// Enhanced Protected route component that preserves the intended destination
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
- const { user, loading } = useAuth();
+ const { user, loading, isAuthenticated } = useAuth();
+ const location = useLocation();
if (loading) {
return
Loading...
;
}
- if (!user) {
- return ;
+ if (!isAuthenticated) {
+ // Redirect to the auth page but save the current location they were trying to access
+ return ;
}
return <>{children}>;
};
-const App = () => (
-
-
+// Authentication guard to prevent authenticated users from accessing the auth page
+const AuthGuard = ({ children }: { children: React.ReactNode }) => {
+ const { isAuthenticated, loading } = useAuth();
+
+ if (loading) {
+ return Loading...
;
+ }
+
+ if (isAuthenticated) {
+ // If already logged in, redirect to dashboard
+ return ;
+ }
+
+ return <>{children}>;
+};
+
+// App needs to be wrapped with BrowserRouter to use the AuthProvider with routing capabilities
+const AppContent = () => {
+ return (
+ <>
-
-
-
-
- } />
- } />
-
-
-
- }
- />
- {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
- } />
-
-
-
+
+
+
+ } />
+
+
+
+ }
+ />
+
+
+
+ }
+ />
+ {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
+ } />
+
+
-
+ >
+ );
+};
+
+const App = () => (
+
+
+
+
+
+
);
diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx
index 5464709..3120e2f 100644
--- a/src/contexts/AuthContext.tsx
+++ b/src/contexts/AuthContext.tsx
@@ -1,8 +1,8 @@
-
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { Session, User } from '@supabase/supabase-js';
import { useToast } from '@/hooks/use-toast';
+import { useNavigate, useLocation } from 'react-router-dom';
type AuthContextType = {
session: Session | null;
@@ -12,6 +12,7 @@ type AuthContextType = {
signIn: (email: string, password: string) => Promise;
signUp: (email: string, password: string, fullName: string) => Promise;
signOut: () => Promise;
+ isAuthenticated: boolean;
};
const AuthContext = createContext(undefined);
@@ -21,13 +22,17 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [user, setUser] = useState(null);
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
const { toast } = useToast();
+ const navigate = useNavigate();
+ const location = useLocation();
useEffect(() => {
// Get the initial session
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
setUser(session?.user ?? null);
+ setIsAuthenticated(!!session?.user);
if (session?.user) {
fetchProfile(session.user.id);
}
@@ -39,10 +44,15 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
(_event, session) => {
setSession(session);
setUser(session?.user ?? null);
+ setIsAuthenticated(!!session?.user);
if (session?.user) {
fetchProfile(session.user.id);
} else {
setProfile(null);
+ // If on a protected route and logged out, redirect to auth
+ if (location.pathname === '/dashboard') {
+ navigate('/auth');
+ }
}
setLoading(false);
}
@@ -51,7 +61,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
return () => {
subscription.unsubscribe();
};
- }, []);
+ }, [navigate, location.pathname]);
const fetchProfile = async (userId: string) => {
try {
@@ -83,6 +93,9 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
title: "Success!",
description: "You are now signed in.",
});
+
+ // Redirect to dashboard on successful sign in
+ navigate('/dashboard');
} catch (error: any) {
toast({
title: "Error signing in",
@@ -137,6 +150,9 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
title: "Signed out",
description: "You have been successfully signed out.",
});
+
+ // Always redirect to home page after sign out
+ navigate('/');
} catch (error: any) {
toast({
title: "Error signing out",
@@ -159,6 +175,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
signIn,
signUp,
signOut,
+ isAuthenticated,
}}
>
{children}
diff --git a/src/pages/Auth.tsx b/src/pages/Auth.tsx
index 9831d28..a5309dc 100644
--- a/src/pages/Auth.tsx
+++ b/src/pages/Auth.tsx
@@ -1,6 +1,6 @@
import { useState } from 'react';
-import { Navigate } from 'react-router-dom';
+import { useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from '@/contexts/AuthContext';
import { ShieldCheck, Mail, Lock, User, Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
@@ -10,23 +10,25 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
const Auth = () => {
- const { user, signIn, signUp, loading } = useAuth();
+ const { signIn, signUp, loading } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [fullName, setFullName] = useState('');
const [authError, setAuthError] = useState(null);
const [activeTab, setActiveTab] = useState('login');
-
- // If user is already logged in, redirect to dashboard
- if (user) {
- return ;
- }
+
+ const location = useLocation();
+ const navigate = useNavigate();
+
+ // Get the intended destination from the location state
+ const from = (location.state as any)?.from?.pathname || '/dashboard';
const handleSignIn = async (e: React.FormEvent) => {
e.preventDefault();
setAuthError(null);
try {
await signIn(email, password);
+ // Redirect will be handled in the AuthContext after successful sign in
} catch (error: any) {
console.error('Sign in error:', error);
// Error is already handled by the toast in AuthContext