Implemented component version of authentication guard.
This commit is contained in:
parent
6856cd3b71
commit
f98b003808
@ -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,29 +41,32 @@ export default class Dashboard extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h1></h1>
|
||||
<InputGroup className="w-50">
|
||||
<FormControl
|
||||
placeholder="Search for Matches"
|
||||
aria-label="Search Bar"
|
||||
aria-describedby="basic-addon2"
|
||||
/>
|
||||
<Button variant="outline-secondary" id="button-addon2">
|
||||
Search
|
||||
</Button>
|
||||
</InputGroup>
|
||||
<div className="p-4">
|
||||
<h2>Available Matches</h2>
|
||||
<MatchInfoCardDisplay recommendedmatches={this.state.displayedMatches} />
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h2>Available Sports</h2>
|
||||
<SportInfoCardDisplay recommendedsports={this.state.displayedSports} />
|
||||
</div>
|
||||
<div className="page-root">
|
||||
<AuthenticationGuard />
|
||||
<React.Fragment>
|
||||
<h1></h1>
|
||||
<InputGroup className="w-50">
|
||||
<FormControl
|
||||
placeholder="Search for Matches"
|
||||
aria-label="Search Bar"
|
||||
aria-describedby="basic-addon2"
|
||||
/>
|
||||
<Button variant="outline-secondary" id="button-addon2">
|
||||
Search
|
||||
</Button>
|
||||
</InputGroup>
|
||||
<div className="p-4">
|
||||
<h2>Available Matches</h2>
|
||||
<MatchInfoCardDisplay recommendedmatches={this.state.displayedMatches} />
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h2>Available Sports</h2>
|
||||
<SportInfoCardDisplay recommendedsports={this.state.displayedSports} />
|
||||
</div>
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
</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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user