ng
Browse files
frontend/src/pages/ResetPassword.jsx
CHANGED
|
@@ -12,7 +12,7 @@ const ResetPassword = () => {
|
|
| 12 |
const { loading, error } = useSelector(state => state.auth);
|
| 13 |
|
| 14 |
const [formData, setFormData] = useState({
|
| 15 |
-
token: '',
|
| 16 |
password: '',
|
| 17 |
confirmPassword: ''
|
| 18 |
});
|
|
@@ -24,11 +24,34 @@ const ResetPassword = () => {
|
|
| 24 |
password: false,
|
| 25 |
confirmPassword: false
|
| 26 |
});
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
useEffect(() => {
|
| 30 |
const token = searchParams.get('token');
|
| 31 |
if (token) {
|
|
|
|
| 32 |
setFormData(prev => ({ ...prev, token }));
|
| 33 |
}
|
| 34 |
}, [searchParams]);
|
|
@@ -98,32 +121,36 @@ const ResetPassword = () => {
|
|
| 98 |
}
|
| 99 |
|
| 100 |
try {
|
|
|
|
|
|
|
| 101 |
// --- Check for existing session (recovery session) ---
|
| 102 |
// It's crucial to verify the session was established by the Supabase client
|
| 103 |
// when it processed the URL fragments on app load.
|
| 104 |
-
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
|
|
|
|
|
|
| 105 |
if (sessionError) {
|
| 106 |
-
console.error('Error getting session:', sessionError);
|
| 107 |
alert('Failed to get session. Please try resetting your password again.');
|
| 108 |
-
// Optionally, redirect to /forgot-password
|
| 109 |
-
// navigate('/forgot-password');
|
| 110 |
return;
|
| 111 |
}
|
| 112 |
|
| 113 |
-
if (!
|
| 114 |
// This is the likely cause of AuthSessionMissingError
|
| 115 |
-
console.warn('No active session found. The URL might not have been processed correctly or the session expired.');
|
|
|
|
| 116 |
alert('Password reset link may be invalid or expired. Please request a new one.');
|
| 117 |
// Optionally, redirect to /forgot-password
|
| 118 |
// navigate('/forgot-password');
|
| 119 |
return;
|
| 120 |
}
|
| 121 |
|
| 122 |
-
console.log('Resetting password with Supabase client for user:',
|
| 123 |
|
| 124 |
const { data, error } = await supabase.auth.updateUser({
|
| 125 |
password: formData.password
|
| 126 |
});
|
|
|
|
| 127 |
|
| 128 |
if (error) {
|
| 129 |
console.error('Supabase password reset error:', error);
|
|
@@ -141,8 +168,7 @@ const ResetPassword = () => {
|
|
| 141 |
|
| 142 |
console.log('Password updated successfully:', data);
|
| 143 |
alert('Password reset successfully! You can now log in with your new password.');
|
| 144 |
-
// After successful reset, the
|
| 145 |
-
// Consider logging the user out of the recovery session.
|
| 146 |
await supabase.auth.signOut();
|
| 147 |
navigate('/login');
|
| 148 |
|
|
@@ -171,6 +197,14 @@ const ResetPassword = () => {
|
|
| 171 |
|
| 172 |
{/* Auth Card */}
|
| 173 |
<div className="bg-white rounded-2xl shadow-xl p-4 sm:p-8 space-y-4 sm:space-y-6 animate-slide-up animate-delay-100">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
{/* Error Message */}
|
| 175 |
{error && (
|
| 176 |
<div className="bg-red-50 border border-red-200 rounded-lg p-3 sm:p-4 animate-slide-up animate-delay-200">
|
|
|
|
| 12 |
const { loading, error } = useSelector(state => state.auth);
|
| 13 |
|
| 14 |
const [formData, setFormData] = useState({
|
| 15 |
+
token: '', // This is likely unused in the v2 flow, but kept for structure
|
| 16 |
password: '',
|
| 17 |
confirmPassword: ''
|
| 18 |
});
|
|
|
|
| 24 |
password: false,
|
| 25 |
confirmPassword: false
|
| 26 |
});
|
| 27 |
+
const [authState, setAuthState] = useState({ event: null, session: null });
|
| 28 |
+
|
| 29 |
+
// --- Listen for auth state changes specifically on this page ---
|
| 30 |
+
// This helps confirm if PASSWORD_RECOVERY was detected
|
| 31 |
+
useEffect(() => {
|
| 32 |
+
console.log("ResetPassword component mounted. Setting up auth listener.");
|
| 33 |
+
const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
|
| 34 |
+
console.log('Auth state changed within ResetPassword component:', event, session ? `User: ${session.user?.id || 'N/A'}` : 'No session');
|
| 35 |
+
setAuthState({ event, session });
|
| 36 |
+
|
| 37 |
+
if (event === 'PASSWORD_RECOVERY') {
|
| 38 |
+
console.log('*** PASSWORD_RECOVERY event confirmed in ResetPassword component. ***');
|
| 39 |
+
// Optional: You could set some state here to indicate the recovery flow is active
|
| 40 |
+
}
|
| 41 |
+
});
|
| 42 |
+
|
| 43 |
+
// Cleanup listener on unmount
|
| 44 |
+
return () => {
|
| 45 |
+
console.log("ResetPassword component unmounting. Removing auth listener.");
|
| 46 |
+
authListener?.subscription.unsubscribe();
|
| 47 |
+
};
|
| 48 |
+
}, []);
|
| 49 |
+
|
| 50 |
+
// Get token from URL params (old v1 flow, kept for reference but likely not used)
|
| 51 |
useEffect(() => {
|
| 52 |
const token = searchParams.get('token');
|
| 53 |
if (token) {
|
| 54 |
+
console.warn("Token found in search params (v1 flow?). This might be unexpected in v2 flow:", token);
|
| 55 |
setFormData(prev => ({ ...prev, token }));
|
| 56 |
}
|
| 57 |
}, [searchParams]);
|
|
|
|
| 121 |
}
|
| 122 |
|
| 123 |
try {
|
| 124 |
+
console.log("Attempting to get current session before password update...");
|
| 125 |
+
|
| 126 |
// --- Check for existing session (recovery session) ---
|
| 127 |
// It's crucial to verify the session was established by the Supabase client
|
| 128 |
// when it processed the URL fragments on app load.
|
| 129 |
+
const { data: { session: currentSession }, error: sessionError } = await supabase.auth.getSession();
|
| 130 |
+
console.log("Current session check result:", currentSession ? `Session for user: ${currentSession.user?.id || 'N/A'}` : 'No session', sessionError);
|
| 131 |
+
|
| 132 |
if (sessionError) {
|
| 133 |
+
console.error('Error getting current session:', sessionError);
|
| 134 |
alert('Failed to get session. Please try resetting your password again.');
|
|
|
|
|
|
|
| 135 |
return;
|
| 136 |
}
|
| 137 |
|
| 138 |
+
if (!currentSession || !currentSession.user) {
|
| 139 |
// This is the likely cause of AuthSessionMissingError
|
| 140 |
+
console.warn('No active session found in handleSubmit. The URL might not have been processed correctly or the session expired.');
|
| 141 |
+
console.log("Auth state at time of submission:", authState);
|
| 142 |
alert('Password reset link may be invalid or expired. Please request a new one.');
|
| 143 |
// Optionally, redirect to /forgot-password
|
| 144 |
// navigate('/forgot-password');
|
| 145 |
return;
|
| 146 |
}
|
| 147 |
|
| 148 |
+
console.log('Resetting password with Supabase client for user:', currentSession.user?.email);
|
| 149 |
|
| 150 |
const { data, error } = await supabase.auth.updateUser({
|
| 151 |
password: formData.password
|
| 152 |
});
|
| 153 |
+
console.log("supabase.auth.updateUser result:", data, error);
|
| 154 |
|
| 155 |
if (error) {
|
| 156 |
console.error('Supabase password reset error:', error);
|
|
|
|
| 168 |
|
| 169 |
console.log('Password updated successfully:', data);
|
| 170 |
alert('Password reset successfully! You can now log in with your new password.');
|
| 171 |
+
// After successful reset, sign the user out of the temporary recovery session.
|
|
|
|
| 172 |
await supabase.auth.signOut();
|
| 173 |
navigate('/login');
|
| 174 |
|
|
|
|
| 197 |
|
| 198 |
{/* Auth Card */}
|
| 199 |
<div className="bg-white rounded-2xl shadow-xl p-4 sm:p-8 space-y-4 sm:space-y-6 animate-slide-up animate-delay-100">
|
| 200 |
+
{/* --- Debug Info Display (Remove in production) --- */}
|
| 201 |
+
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-2 text-xs">
|
| 202 |
+
<strong>Debug Info:</strong>
|
| 203 |
+
<p>Auth Event: {authState.event || 'None'}</p>
|
| 204 |
+
<p>Auth Session User ID: {authState.session?.user?.id || 'None'}</p>
|
| 205 |
+
</div>
|
| 206 |
+
{/* --- End Debug Info --- */}
|
| 207 |
+
|
| 208 |
{/* Error Message */}
|
| 209 |
{error && (
|
| 210 |
<div className="bg-red-50 border border-red-200 rounded-lg p-3 sm:p-4 animate-slide-up animate-delay-200">
|
frontend/src/services/supabaseClient.js
CHANGED
|
@@ -38,17 +38,58 @@ export const supabase = createClient(
|
|
| 38 |
}
|
| 39 |
);
|
| 40 |
|
| 41 |
-
// --- Add logging
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
console.log("Supabase client initialized with URL:", supabaseUrl);
|
|
|
|
|
|
|
| 43 |
supabase.auth.getSession()
|
| 44 |
.then(({ data: { session }, error }) => {
|
|
|
|
| 45 |
if (error) {
|
| 46 |
console.error("Error getting initial session:", error);
|
| 47 |
} else {
|
| 48 |
-
console.log("Initial session
|
| 49 |
-
//
|
| 50 |
-
// If session is null here when coming from a reset link, it means processing failed.
|
| 51 |
}
|
| 52 |
});
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
export default supabase;
|
|
|
|
| 38 |
}
|
| 39 |
);
|
| 40 |
|
| 41 |
+
// --- Add comprehensive logging for auth state changes ---
|
| 42 |
+
let initialSessionCheckDone = false;
|
| 43 |
+
|
| 44 |
+
// Listen for auth state changes
|
| 45 |
+
const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
|
| 46 |
+
console.log('Supabase Auth State Change Event:', event);
|
| 47 |
+
console.log('Supabase Auth State Change Session:', session ? `User: ${session.user?.id || 'N/A'}` : 'No session');
|
| 48 |
+
|
| 49 |
+
// Handle specific events
|
| 50 |
+
if (event === 'PASSWORD_RECOVERY') {
|
| 51 |
+
console.log('*** PASSWORD_RECOVERY event detected. A password reset link was used. ***');
|
| 52 |
+
// The session provided here should be the temporary recovery session.
|
| 53 |
+
// The app should now allow the user to set a new password.
|
| 54 |
+
} else if (event === 'SIGNED_IN') {
|
| 55 |
+
console.log('User signed in.');
|
| 56 |
+
} else if (event === 'SIGNED_OUT') {
|
| 57 |
+
console.log('User signed out.');
|
| 58 |
+
} else if (event === 'TOKEN_REFRESHED') {
|
| 59 |
+
console.log('Session token refreshed.');
|
| 60 |
+
} else if (event === 'USER_UPDATED') {
|
| 61 |
+
console.log('User data updated.');
|
| 62 |
+
}
|
| 63 |
+
});
|
| 64 |
+
|
| 65 |
console.log("Supabase client initialized with URL:", supabaseUrl);
|
| 66 |
+
|
| 67 |
+
// Initial session check on app load
|
| 68 |
supabase.auth.getSession()
|
| 69 |
.then(({ data: { session }, error }) => {
|
| 70 |
+
initialSessionCheckDone = true;
|
| 71 |
if (error) {
|
| 72 |
console.error("Error getting initial session:", error);
|
| 73 |
} else {
|
| 74 |
+
console.log("Initial session check result (on app load):", session ? `Session exists for user: ${session.user?.id || 'N/A'}` : "No active session found");
|
| 75 |
+
// If session is null here when coming from a reset link, it means processing failed or the token was already used/expired.
|
|
|
|
| 76 |
}
|
| 77 |
});
|
| 78 |
|
| 79 |
+
// Fallback check in case the initial check happens too early or misses something
|
| 80 |
+
setTimeout(() => {
|
| 81 |
+
if (!initialSessionCheckDone) {
|
| 82 |
+
console.warn("Initial session check might have been missed or delayed. Checking again...");
|
| 83 |
+
supabase.auth.getSession()
|
| 84 |
+
.then(({ data: { session }, error }) => {
|
| 85 |
+
initialSessionCheckDone = true; // Mark as done even on retry
|
| 86 |
+
if (error) {
|
| 87 |
+
console.error("Fallback - Error getting session:", error);
|
| 88 |
+
} else {
|
| 89 |
+
console.log("Fallback - Session check result:", session ? `Session exists for user: ${session.user?.id || 'N/A'}` : "No active session found (Fallback)");
|
| 90 |
+
}
|
| 91 |
+
});
|
| 92 |
+
}
|
| 93 |
+
}, 1000); // Check again after 1 second
|
| 94 |
+
|
| 95 |
export default supabase;
|