Skip to content

Commit 1574503

Browse files
add auth context (#83)
2 parents d831475 + a636162 commit 1574503

File tree

16 files changed

+296
-386
lines changed

16 files changed

+296
-386
lines changed

src/App.tsx

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,49 @@ import ProfilePage from "./shared/pages/Profile.js";
1414
import LoginRedirection from "./auth/Login.tsx";
1515
import LogoutRedirection from "./auth/Logout.tsx";
1616
import StickyFooter from "./shared/components/Navigation/StickyFooter.tsx";
17-
import IsAuthenticated from "./auth/Auth.tsx";
1817
import Token from "./auth/Token.tsx";
1918
import { HelmetProvider } from 'react-helmet-async';
19+
import { AuthProvider } from './context/AuthContext.tsx';
2020

2121
function App() {
2222

23-
const authenticated = IsAuthenticated();
24-
2523
return (
26-
<HelmetProvider>
27-
<section>
28-
<MainNavigation authenticated={authenticated} />
29-
<main className="container-xl p-8">
30-
<Routes>
31-
<Route path="/" element={<Home />} />
32-
<Route path="/health" element={<p>App is Healthy</p>} />
33-
<Route path="/callback" element={<Token />} />
34-
<Route path="/signin" element={<LoginRedirection />} />
35-
<Route path="/login" element={<LoginRedirection />} />
36-
<Route path="/signout" element={<LogoutRedirection authenticated={authenticated} />} />
37-
<Route path="/logout" element={<LogoutRedirection authenticated={authenticated} />} />
24+
<AuthProvider>
25+
<HelmetProvider>
26+
<section>
27+
<MainNavigation />
28+
<main className="container-xl p-8">
29+
<Routes>
30+
<Route path="/" element={<Home />} />
31+
<Route path="/health" element={<p>App is Healthy</p>} />
32+
<Route path="/callback" element={<Token />} />
33+
<Route path="/signin" element={<LoginRedirection />} />
34+
<Route path="/login" element={<LoginRedirection />} />
35+
<Route path="/signout" element={<LogoutRedirection />} />
36+
<Route path="/logout" element={<LogoutRedirection />} />
3837

39-
<Route path="/jobs" element={<Jobs />} />
40-
<Route path="/profile" element={<ProfilePage />} />
41-
<Route
42-
path="/staff/department/:department"
43-
element={<Department authenticated={authenticated} />}
44-
/>
45-
<Route path="/staff" element={<Departments authenticated={authenticated} />} />
46-
<Route path="/staff/:staffId" element={<StaffPage authenticated={authenticated} />} />
47-
<Route path="/create" element={<CreatePost edit={false} authenticated={authenticated} />} />
48-
<Route
49-
path="/edit/:postID"
50-
element={<CreatePost edit={true} authenticated={authenticated} />}
51-
/>
52-
<Route path="/post/:postID" element={<IndividualPost />} />
38+
<Route path="/jobs" element={<Jobs />} />
39+
<Route path="/profile" element={<ProfilePage />} />
40+
<Route
41+
path="/staff/department/:department"
42+
element={<Department />}
43+
/>
44+
<Route path="/staff" element={<Departments />} />
45+
<Route path="/staff/:staffId" element={<StaffPage />} />
46+
<Route path="/create" element={<CreatePost edit={false} />} />
47+
<Route
48+
path="/edit/:postID"
49+
element={<CreatePost edit={true} />}
50+
/>
51+
<Route path="/post/:postID" element={<IndividualPost />} />
5352

54-
<Route path="/*" element={<PageNotFound />} />
55-
</Routes>
56-
</main>
57-
<StickyFooter authenticated={authenticated} />
58-
</section>
59-
</HelmetProvider>
53+
<Route path="/*" element={<PageNotFound />} />
54+
</Routes>
55+
</main>
56+
<StickyFooter />
57+
</section>
58+
</HelmetProvider>
59+
</AuthProvider>
6060
);
6161
}
6262

src/auth/Auth.tsx

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/auth/Login.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
const LoginRedirection = () => {
2-
window.location.href = `${process.env.REACT_APP_BACKEND_SERVER}/login`;
3-
return null; // No need to render anything, as the redirection happens immediately
4-
};
1+
import { useAuth } from "../context/AuthContext.tsx";
52

6-
export default LoginRedirection;
3+
export default function LoginRedirection() {
4+
const { auth } = useAuth();
5+
if (auth.isAuthenticated) {
6+
window.location.href = "/";
7+
}
8+
window.location.href = `${process.env.REACT_APP_BACKEND_SERVER}/login`;
9+
return null;
10+
};

src/auth/Logout.tsx

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,38 @@
11
import { useEffect } from "react";
2+
import { useAuth } from "../context/AuthContext.tsx";
23

3-
const logout = async (token: string) => {
4-
try {
5-
const response = await fetch(
6-
`${process.env.REACT_APP_BACKEND_SERVER}/logout`,
7-
{
8-
method: "GET",
9-
credentials: "include", // to send cookies or session data
10-
headers: {
11-
Authorization: `Bearer ${token}`,
12-
},
13-
}
14-
);
15-
if (response.ok) {
16-
// Clear local storage or tokens
17-
localStorage.removeItem("jwt");
18-
19-
// Redirect to the homepage or login page
20-
const intervalId = setInterval(() => {
21-
if (!localStorage.getItem("jwt")) {
22-
clearInterval(intervalId); // Clear the interval once condition is met
23-
window.location.href = "/";
24-
}
25-
}, 5); // Check every 5ms (adjust as needed)
26-
} else {
27-
console.error("Failed to logout");
28-
}
29-
} catch (error) {
30-
console.error("Error logging out:", error);
31-
window.location.href = "/";
32-
}
33-
};
4+
export default function LogoutRedirection() {
5+
const { auth, logout } = useAuth();
346

35-
const LogoutRedirection = (authenticated) => {
36-
if (!authenticated.authenticated[1]) {
7+
if (!auth.isAuthenticated) {
378
window.location.href = "/";
389
}
3910
console.log("Logging out...");
4011
useEffect(() => {
41-
logout(authenticated.authenticated[0]);
42-
}, []); // Run only on component mount
12+
async function logoutUser() {
13+
try {
14+
const response = await fetch(
15+
`${process.env.REACT_APP_BACKEND_SERVER}/logout`,
16+
{
17+
method: "GET",
18+
credentials: "include", // to send cookies or session data
19+
headers: {
20+
Authorization: `Bearer ${auth.token}`,
21+
},
22+
}
23+
);
24+
if (response.ok) {
25+
logout();
26+
} else {
27+
console.error("Failed to logout");
28+
}
29+
} catch (error) {
30+
console.error("Error logging out:", error);
31+
window.location.href = "/";
32+
}
33+
}
34+
logoutUser();
35+
}, [auth, logout]);
4336

4437
return null; // Since this component doesn't need to render anything
45-
};
46-
47-
export default LogoutRedirection;
38+
};

src/auth/Token.tsx

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
const Token = () => {
1+
import { useAuth } from "../context/AuthContext.tsx";
2+
3+
export default function Token() {
4+
5+
const { login } = useAuth();
26

37
const urlParams = new URLSearchParams(window.location.search);
48
const code = urlParams.get("code");
59

6-
console.log("Code:", code);
710
if (code) {
811
fetch(`${process.env.REACT_APP_BACKEND_SERVER}/token`, {
912
method: "POST",
@@ -14,26 +17,16 @@ const Token = () => {
1417
})
1518
.then((response) => response.json())
1619
.then((data) => {
17-
console.log("Data:", data);
1820
const token = data.token;
19-
console.log("Token:", token);
2021
if (token) {
21-
localStorage.setItem("jwt", token);
22-
23-
// Periodically check if both jwt and jwt-time are set
24-
const intervalId = setInterval(() => {
25-
if (localStorage.getItem("jwt")) {
26-
clearInterval(intervalId); // Clear the interval once condition is met
27-
window.location.href = "/";
28-
}
29-
}, 5); // Check every 5ms (adjust as needed)
22+
login(token);
3023
return null;
3124
}
3225
})
3326
.catch((error) => console.error("Error fetching token:", error));
27+
} else {
28+
window.location.href = "/";
3429
}
3530

3631
return null;
37-
}
38-
39-
export default Token;
32+
}

src/context/AuthContext.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React, { createContext, useState, useContext } from 'react';
2+
3+
const AuthContext = createContext<{
4+
auth: { isAuthenticated: boolean; token: string | null };
5+
login: (token: string) => void;
6+
logout: () => void;
7+
loadToken: () => void;
8+
}>({
9+
auth: { isAuthenticated: false, token: null },
10+
login: () => { },
11+
logout: () => { },
12+
loadToken: () => { }
13+
});
14+
15+
import { ReactNode } from 'react';
16+
17+
interface AuthProviderProps {
18+
children: ReactNode;
19+
}
20+
21+
export const AuthProvider = ({ children }: AuthProviderProps) => {
22+
const [auth, setAuth] = useState<{ isAuthenticated: boolean; token: string | null }>({
23+
isAuthenticated: false,
24+
token: null,
25+
});
26+
27+
const login = (token: string) => {
28+
setAuth({ isAuthenticated: true, token });
29+
// Save token to localStorage for persistence
30+
localStorage.setItem('jwt', token);
31+
};
32+
33+
const logout = () => {
34+
setAuth({ isAuthenticated: false, token: null });
35+
// Clear token from localStorage
36+
localStorage.removeItem('jwt');
37+
};
38+
39+
const loadToken = () => {
40+
const savedToken = localStorage.getItem('jwt');
41+
if (savedToken) {
42+
setAuth({ isAuthenticated: true, token: savedToken });
43+
}
44+
};
45+
46+
return (
47+
<AuthContext.Provider value={{ auth, login, logout, loadToken }}>
48+
{children}
49+
</AuthContext.Provider>
50+
);
51+
};
52+
53+
export const useAuth = () => useContext(AuthContext);

src/context/global/GlobalContext.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/context/global/GlobalContextProvider.js

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)