diff --git a/src/auth/Logout.tsx b/src/auth/Logout.tsx index 08b71716..62e5440f 100644 --- a/src/auth/Logout.tsx +++ b/src/auth/Logout.tsx @@ -14,11 +14,7 @@ export default function LogoutRedirection() { const response = await fetch( `${process.env.REACT_APP_BACKEND_SERVER}/logout`, { - method: "GET", - credentials: "include", // to send cookies or session data - headers: { - Authorization: `Bearer ${auth.token}`, - }, + credentials: "include", } ); if (response.ok) { @@ -32,7 +28,7 @@ export default function LogoutRedirection() { } } logoutUser(); - }, [logout, auth.token]); + }, [logout]); return null; // Since this component doesn't need to render anything }; \ No newline at end of file diff --git a/src/auth/Token.tsx b/src/auth/Token.tsx index 411cf617..20b769c5 100644 --- a/src/auth/Token.tsx +++ b/src/auth/Token.tsx @@ -3,7 +3,11 @@ import { useEffect } from "react"; export default function Token() { - const { login } = useAuth(); + const { auth, login } = useAuth(); + + if (auth.isAuthenticated) { + window.location.href = "/"; + } const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get("code"); @@ -16,15 +20,18 @@ export default function Token() { "Content-Type": "application/json", }, body: JSON.stringify({ code }), + credentials: "include", }) .then((response) => response.json()) .then((data) => { - const token = data.token; - if (token) { - login(token); - window.location.href = "/"; - return null; - } + const registered = data.registered; + console.log("registered", registered); + login(); + // if (registered) { + window.location.href = "/"; + return null; + // } + // TODO: Redirect to registration page }) .catch((error) => console.error("Error fetching token:", error)); } @@ -34,4 +41,4 @@ export default function Token() { }, [code, login]); return null; -} \ No newline at end of file +} diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx index 83c6660a..d9402572 100644 --- a/src/context/AuthContext.tsx +++ b/src/context/AuthContext.tsx @@ -1,53 +1,62 @@ -import React, { createContext, useState, useContext, useEffect } from 'react'; -import { ReactNode } from 'react'; +import React, { createContext, useState, useContext } from 'react'; +import { ReactNode, useEffect } from 'react'; const AuthContext = createContext<{ - auth: { isAuthenticated: boolean; token: string | null }; - login: (token: string) => void; + auth: { isAuthenticated: boolean }; + login: () => void; logout: () => void; - loadToken: () => void; }>({ - auth: { isAuthenticated: false, token: null }, + auth: { isAuthenticated: false }, login: () => { }, logout: () => { }, - loadToken: () => { } }); interface AuthProviderProps { children: ReactNode; } export const AuthProvider = ({ children }: AuthProviderProps) => { - const [auth, setAuth] = useState<{ isAuthenticated: boolean; token: string | null }>({ + const [auth, setAuth] = useState<{ isAuthenticated: boolean }>({ isAuthenticated: false, - token: null, }); - const login = (token: string) => { - setAuth({ isAuthenticated: true, token }); - // Save token to localStorage for persistence - localStorage.setItem('jwt', token); - }; - - const logout = () => { - setAuth({ isAuthenticated: false, token: null }); - // Clear token from localStorage - localStorage.removeItem('jwt'); - }; - - const loadToken = () => { - const savedToken = localStorage.getItem('jwt'); - if (savedToken) { - setAuth({ isAuthenticated: true, token: savedToken }); + const checkAuth = async () => { + try { + const response = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/authcheck`, { + credentials: "include", + }); + if (response.ok) { + setAuth({ isAuthenticated: true }); + } else { + const refreshResponse = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/token/refresh`, { + credentials: "include", + }); + if (refreshResponse.ok) { + setAuth({ isAuthenticated: true }); + } else { + setAuth({ isAuthenticated: false }); + } + } + } catch (error) { + console.error("Auth check failed:", error); + setAuth({ isAuthenticated: false }); } }; useEffect(() => { - loadToken(); + checkAuth(); // Run this on mount to persist session state }, []); + const login = () => { + setAuth({ isAuthenticated: true }); + }; + + const logout = () => { + setAuth({ isAuthenticated: false }); + }; + return ( - + {children} ); diff --git a/src/shared/components/Profile/ProfileComponents.tsx b/src/shared/components/Profile/ProfileComponents.tsx index d09c1e1a..a346f4bb 100644 --- a/src/shared/components/Profile/ProfileComponents.tsx +++ b/src/shared/components/Profile/ProfileComponents.tsx @@ -4,14 +4,7 @@ import ProfileDescription from "./ProfileDescription.tsx"; import ProfileOpportunities from "./ProfileOpportunities.tsx"; import SEO from "..//SEO.tsx"; import Breadcrumb from "../UIElements/Breadcrumb.tsx"; - -interface Profile { - name: string; - image: string; - department: string; - description: string; - website?: string; -} +import { Profile } from "../../../types/profile.ts"; const ProfileComponents = ({ profile, id, staff }: { profile: Profile, id: string, staff: boolean }) => { return ( @@ -36,7 +29,6 @@ const ProfileComponents = ({ profile, id, staff }: { profile: Profile, id: strin
diff --git a/src/shared/components/Profile/ProfileDescription.tsx b/src/shared/components/Profile/ProfileDescription.tsx index fa25d1ad..5f408872 100644 --- a/src/shared/components/Profile/ProfileDescription.tsx +++ b/src/shared/components/Profile/ProfileDescription.tsx @@ -1,12 +1,15 @@ import React from "react"; -import PropTypes from "prop-types"; import { Link } from "react-router-dom"; +import { Profile } from "../../../types/profile.ts"; -const ProfileDescription = ({ name, department, description, website }) => { +export default function ProfileDescription({ + name, department, description, website, pronouns +}: Profile) { return (

{name}

{department}
+ {pronouns &&
{pronouns}
}

{description}

{website && website.length && ( @@ -15,13 +18,4 @@ const ProfileDescription = ({ name, department, description, website }) => { )}
); -}; - -ProfileDescription.propTypes = { - name: PropTypes.string.isRequired, - department: PropTypes.string, - description: PropTypes.string.isRequired, - website: PropTypes.string, -}; - -export default ProfileDescription; +}; \ No newline at end of file diff --git a/src/shared/components/Profile/ProfileOpportunities.tsx b/src/shared/components/Profile/ProfileOpportunities.tsx index cc659444..881bca2b 100644 --- a/src/shared/components/Profile/ProfileOpportunities.tsx +++ b/src/shared/components/Profile/ProfileOpportunities.tsx @@ -1,19 +1,15 @@ import React from "react"; import LargeTextCard from "../UIElements/LargeTextCard.tsx"; import { useState, useEffect } from "react"; -import { useAuth } from "../../../context/AuthContext.tsx"; export default function ProfileOpportunities({ id, staff }: { id: string, staff: boolean }) { - const { auth } = useAuth(); const [opportunities, setOpportunities] = useState | null | "no response">(null); useEffect(() => { async function setData() { const response = await fetch( `${process.env.REACT_APP_BACKEND_SERVER}/${staff ? "staff" : "profile"}/opportunities/${id}`, { - headers: { - Authorization: `Bearer ${auth.token}`, - }, + credentials: "include", } ); @@ -26,7 +22,7 @@ export default function ProfileOpportunities({ id, staff }: { id: string, staff: } setData(); - }, [auth.token, id, staff]); + }, [id, staff]); const opportunityList = (
diff --git a/src/shared/pages/404.tsx b/src/shared/pages/404.tsx index 45ad2e0e..fda689c2 100644 --- a/src/shared/pages/404.tsx +++ b/src/shared/pages/404.tsx @@ -7,7 +7,7 @@ const PageNotFound = () => { <>

Whoops!

-

It looks like that page couldn't be reached. Please click the link below to return to LabConnect or try refreshing the page

+

It looks like that page couldn't be reached. Please click the link below to return to LabConnect or try refreshing the page

Home
diff --git a/src/shared/pages/LoginRedirect.tsx b/src/shared/pages/LoginRedirect.tsx deleted file mode 100644 index 29e33a83..00000000 --- a/src/shared/pages/LoginRedirect.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import SEO from "../components/SEO.tsx"; -import { Link } from "react-router-dom"; -const LoginRedirect = () => { - return ( - <> -

Whoops!

-

It looks like you're not logged in. Click the button below and log in to see this page

-
- Log In -
- - ); -}; -export default LoginRedirect; \ No newline at end of file diff --git a/src/shared/pages/Profile.tsx b/src/shared/pages/Profile.tsx index 5859efaf..5b91fc15 100644 --- a/src/shared/pages/Profile.tsx +++ b/src/shared/pages/Profile.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from "react"; import { useState } from "react"; import ProfileComponents from "../components/Profile/ProfileComponents.tsx"; import { useAuth } from "../../context/AuthContext.tsx"; +import { Profile } from "../../types/profile.ts"; // import EditProfile from "./EditProfile"; export default function ProfilePage() { @@ -12,14 +13,6 @@ export default function ProfilePage() { } // const [editMode, setEditMode] = useState(false); - interface Profile { - id: string; - name: string; - image: string; - department: string; - description: string; - website?: string; - } const [profile, setProfile] = useState(null); @@ -31,9 +24,7 @@ export default function ProfilePage() { const fetchProfile = async () => { const response = await fetch( `${process.env.REACT_APP_BACKEND_SERVER}/profile`, { - headers: { - Authorization: `Bearer ${auth.token}`, - }, + credentials: "include", } ); @@ -48,7 +39,7 @@ export default function ProfilePage() { } }; fetchProfile(); - }, [auth.token]); + }, []); // const editButton = ( //