Implemented component version of authentication guard.
This commit is contained in:
		@@ -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 = (
 | 
			
		||||
        <Nav>
 | 
			
		||||
            <li className="nav-item">
 | 
			
		||||
                <NavLink className="nav-link" to="/login" >Login</NavLink>
 | 
			
		||||
@@ -43,8 +27,8 @@ export default function layout() {
 | 
			
		||||
        </Nav>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (state.user) {
 | 
			
		||||
        indentityDisplay = (
 | 
			
		||||
    if (context.user) {
 | 
			
		||||
        identityDisplay = (
 | 
			
		||||
            <Nav>
 | 
			
		||||
                <li className="nav-item">
 | 
			
		||||
                    <NavLink className="nav-link" to="/" >Hi, {this.state.user.firstName}</NavLink>
 | 
			
		||||
@@ -58,7 +42,7 @@ export default function layout() {
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div id="app">
 | 
			
		||||
            <globalContext.Provider value={{ navigate: navigate }}>
 | 
			
		||||
            <globalContext.Provider value={{ navigate: navigate, user: null }}>
 | 
			
		||||
                <header>
 | 
			
		||||
                    <Navbar bg="light" expand="md">
 | 
			
		||||
                        <Container>
 | 
			
		||||
@@ -70,7 +54,7 @@ export default function layout() {
 | 
			
		||||
                                        <NavLink className="nav-link" to="/" >Home</NavLink>
 | 
			
		||||
                                    </li>
 | 
			
		||||
                                </Nav>
 | 
			
		||||
                                {indentityDisplay}
 | 
			
		||||
                                {identityDisplay}
 | 
			
		||||
                            </NavbarCollapse>
 | 
			
		||||
                        </Container>
 | 
			
		||||
                    </Navbar>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								sports-matcher/client/src/components/AuthenticationGuard.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								sports-matcher/client/src/components/AuthenticationGuard.js
									
									
									
									
									
										Normal file
									
								
							@@ -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 (
 | 
			
		||||
                <Navigate to="/signup" replace="true" />
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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,6 +41,8 @@ export default class Dashboard extends React.Component {
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="page-root">
 | 
			
		||||
                <AuthenticationGuard />
 | 
			
		||||
                <React.Fragment>
 | 
			
		||||
                    <h1></h1>
 | 
			
		||||
                    <InputGroup className="w-50">
 | 
			
		||||
@@ -64,6 +66,7 @@ export default class Dashboard extends React.Component {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                </React.Fragment>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user