From f98b003808b0cac16fe30ea537adf63f82755001 Mon Sep 17 00:00:00 2001 From: Harrison Deng Date: Wed, 6 Apr 2022 21:18:48 -0500 Subject: [PATCH] Implemented component version of authentication guard. --- sports-matcher/client/src/Layout.js | 30 +++--------- .../src/components/AuthenticationGuard.js | 30 ++++++++++++ sports-matcher/client/src/pages/Dashboard.js | 49 ++++++++++--------- sports-matcher/client/src/pages/Login.js | 10 +--- sports-matcher/client/src/utils/routing.js | 22 --------- 5 files changed, 64 insertions(+), 77 deletions(-) create mode 100644 sports-matcher/client/src/components/AuthenticationGuard.js delete mode 100644 sports-matcher/client/src/utils/routing.js diff --git a/sports-matcher/client/src/Layout.js b/sports-matcher/client/src/Layout.js index 9864c39..4ebcfb9 100644 --- a/sports-matcher/client/src/Layout.js +++ b/sports-matcher/client/src/Layout.js @@ -1,6 +1,6 @@ import "./styles/Layout.css"; import "./styles/extra.css"; -import { useEffect, useState } from "react"; +import { useContext } from "react"; import { NavLink, Route, Routes, useNavigate } from "react-router-dom"; import Welcome from "./pages/Welcome"; import Navbar from "react-bootstrap/Navbar"; @@ -9,30 +9,14 @@ import NavbarToggle from "react-bootstrap/esm/NavbarToggle"; import NavbarCollapse from "react-bootstrap/esm/NavbarCollapse"; import Dashboard from "./pages/Dashboard"; import Login from "./pages/Login"; -import { apiClient } from "./utils/httpClients"; import { globalContext } from "./context.js"; export default function layout() { const navigate = useNavigate(); - const [state, setState] = useState({ - user: null, - }); - useEffect(async () => { - await updateAuthStatus(); - }); - - async function updateAuthStatus() { - const getUserResponse = await apiClient.get("/user"); - if (getUserResponse !== 200) { - setState({ user: null }); - } else { - setState({ user: getUserResponse.data }); - } - } - - let indentityDisplay = ( + const context = useContext(globalContext); + let identityDisplay = ( ); - if (state.user) { - indentityDisplay = ( + if (context.user) { + identityDisplay = ( - {indentityDisplay} + {identityDisplay} diff --git a/sports-matcher/client/src/components/AuthenticationGuard.js b/sports-matcher/client/src/components/AuthenticationGuard.js new file mode 100644 index 0000000..84622e4 --- /dev/null +++ b/sports-matcher/client/src/components/AuthenticationGuard.js @@ -0,0 +1,30 @@ +import React from "react"; +import { Navigate } from "react-router-dom"; +import { globalContext } from "../context"; +import { apiClient } from "../utils/httpClients"; + +export default class AuthenticationGuard extends React.Component { + constructor(props) { + super(props); + } + + async componentDidMount() { + if (!this.context.user) { + let userDataResponse = await apiClient.get("/user/"); + if (userDataResponse.status === 200) { + this.context.user = userDataResponse.data; + } + } + } + + static contextType = globalContext; + + render() { + if (!this.context.user) { + return ( + + ); + } + return; + } +} \ No newline at end of file diff --git a/sports-matcher/client/src/pages/Dashboard.js b/sports-matcher/client/src/pages/Dashboard.js index a8370a0..9374e5a 100644 --- a/sports-matcher/client/src/pages/Dashboard.js +++ b/sports-matcher/client/src/pages/Dashboard.js @@ -5,7 +5,7 @@ import { apiClient } from "../utils/httpClients.js"; import MatchInfoCardDisplay from "../components/MatchInfoCardDisplay"; import SportInfoCardDisplay from "../components/SportInfoCardDisplay"; import { globalContext } from "../context"; -import { needUser } from "../utils/routing"; +import AuthenticationGuard from "../components/AuthenticationGuard"; export default class Dashboard extends React.Component { constructor(props) { @@ -21,7 +21,7 @@ export default class Dashboard extends React.Component { static contextType = globalContext; async componentDidMount() { - await needUser(this.context.navigate); + this.setState({ user: this.context.user }); await this.latestMatches(); await this.availableSports(); } @@ -41,29 +41,32 @@ export default class Dashboard extends React.Component { render() { return ( - -

- - - - -
-

Available Matches

- -
-
-

Available Sports

- -
+
+ + +

+ + + + +
+

Available Matches

+ +
+
+

Available Sports

+ +
-
+ +
); } } \ No newline at end of file diff --git a/sports-matcher/client/src/pages/Login.js b/sports-matcher/client/src/pages/Login.js index 526852e..82e99a5 100644 --- a/sports-matcher/client/src/pages/Login.js +++ b/sports-matcher/client/src/pages/Login.js @@ -2,7 +2,7 @@ import React from "react"; import { Alert, Button, Card, Container, Form } from "react-bootstrap"; import { globalContext } from "../context"; import { apiClient } from "../utils/httpClients"; -import { guard } from "../utils/routing"; +import AuthenticationGuard from "../components/AuthenticationGuard"; export default class Login extends React.Component { constructor(props) { @@ -19,14 +19,6 @@ export default class Login extends React.Component { static contextType = globalContext; async componentDidMount() { - try { - const getUserResponse = await apiClient.get("/user"); - guard(this.context.navigate, () => getUserResponse.status === 401, "/dashboard"); // If it's not 401, then we redirect to dashboard. - } catch (error) { - if (error.message !== "Request failed with status code 401") { - throw error; - } - } } async attemptLogin(e) { diff --git a/sports-matcher/client/src/utils/routing.js b/sports-matcher/client/src/utils/routing.js deleted file mode 100644 index 46caad9..0000000 --- a/sports-matcher/client/src/utils/routing.js +++ /dev/null @@ -1,22 +0,0 @@ -import { apiClient } from "./httpClients"; - -export function guard(navigator, evaluator, redirect, navigateOptions, onRedirect) { - if (!evaluator) throw new Error("evaluator required."); - if (!redirect) throw new Error("redirect required."); - if (!navigateOptions) { - navigateOptions = { - replace: true - }; - } - let redirecting = !evaluator(); - if (redirecting) { - if (onRedirect) onRedirect(); - navigator(redirect, navigateOptions); - } -} - -export async function needUser(navigator) { - let userDataResponse = await apiClient.get("/user"); - guard(navigator, () => userDataResponse.status === 200, "/login"); - return userDataResponse.data; -} \ No newline at end of file