defined protect function for access control on front end
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||
import { IUser } from './schemas';
|
||||
import { checkCredientials } from './util/apiUtils';
|
||||
import { AuthContext, defaultValue, IAuthContext } from './context/AuthContext';
|
||||
import Browser from './components/pages/Browser';
|
||||
import Collection from './components/pages/Collection';
|
||||
import Login from './components/pages/Login';
|
||||
@@ -7,18 +10,16 @@ import Profile from './components/pages/Profile';
|
||||
import Recipe from './components/pages/Recipe';
|
||||
import Register from './components/pages/Register';
|
||||
import Welcome from './components/pages/Welcome';
|
||||
import { useAuthContext } from './context/AuthContext';
|
||||
import './sass/App.scss'
|
||||
import { IUser } from './schemas';
|
||||
import { checkCredientials } from './util/apiUtils';
|
||||
|
||||
function App() {
|
||||
const authContext = useAuthContext();
|
||||
const [user, setUser] = useState<IAuthContext>({ user: undefined });
|
||||
|
||||
useEffect(() => {
|
||||
const wrapper = async () => {
|
||||
const result = await checkCredientials();
|
||||
authContext.user = result;
|
||||
const result: IAuthContext | undefined = await checkCredientials();
|
||||
if (result == undefined) setUser({ user: undefined });
|
||||
setUser(result!);
|
||||
}
|
||||
|
||||
wrapper();
|
||||
@@ -26,17 +27,19 @@ function App() {
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Welcome />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
<Route path="/collection" element={<Collection />} />
|
||||
<Route path="/explore" element={<Browser />} />
|
||||
<Route path="/recipe/:id" element={<Recipe />} />
|
||||
</Routes>
|
||||
</div>
|
||||
<AuthContext.Provider value={ user }>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Welcome />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
<Route path="/collection" element={<Collection />} />
|
||||
<Route path="/explore" element={<Browser />} />
|
||||
<Route path="/recipe/:id" element={<Recipe />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</AuthContext.Provider>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import { Page } from "../ui";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { IUser } from "../../schemas";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AuthContext, useAuthContext } from "../../context/AuthContext";
|
||||
import { Button, Page } from "../ui";
|
||||
import Protect from "../../util/Protect";
|
||||
|
||||
export default function Profile() {
|
||||
const [message, setMessage] = useState<JSX.Element>();
|
||||
const { user } = useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<h1>Mikayla Dobson</h1>
|
||||
</Page>
|
||||
<Protect>
|
||||
<div className="profile-authenticated">
|
||||
<h1>{user!.firstname}'s Profile</h1>
|
||||
<p>Things and stuff!</p>
|
||||
</div>
|
||||
</Protect>
|
||||
)
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAuthContext } from "../../context/AuthContext";
|
||||
import { AuthContext } from "../../context/AuthContext";
|
||||
import { IUser } from "../../schemas";
|
||||
import { attemptLogout } from "../../util/apiUtils";
|
||||
import Button from "./Button";
|
||||
import "/src/sass/components/Navbar.scss";
|
||||
|
||||
const Navbar = () => {
|
||||
const authContext = useAuthContext();
|
||||
const { user } = useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
const [user, setUser] = useState('Mikayla');
|
||||
|
||||
const navbarLoggedIn = (
|
||||
<div id="navbar">
|
||||
@@ -16,8 +16,10 @@ const Navbar = () => {
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {authContext.user?.firstname}</p>
|
||||
<p>Hi, {user?.firstname}</p>
|
||||
<span id="search-icon"></span>
|
||||
<Button onClick={() => console.log(user)}>Auth Context?</Button>
|
||||
<Button onClick={() => navigate('/profile')}>Profile</Button>
|
||||
<Button onClick={attemptLogout}>Log Out</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,16 +42,12 @@ const Navbar = () => {
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {authContext.user?.firstname}</p>
|
||||
<p>Hi, {user?.firstname}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (authContext.user) {
|
||||
return navbarLoggedIn;
|
||||
} else {
|
||||
return navbarNotLoggedIn;
|
||||
}
|
||||
return user ? navbarLoggedIn : navbarNotLoggedIn;
|
||||
}
|
||||
|
||||
export default Navbar;
|
||||
@@ -2,11 +2,11 @@ import { createContext, useContext } from "react";
|
||||
import { IUser } from "../schemas";
|
||||
|
||||
|
||||
interface IAuthContext {
|
||||
export interface IAuthContext {
|
||||
user?: IUser
|
||||
}
|
||||
|
||||
const defaultValue: IAuthContext = {
|
||||
export const defaultValue: IAuthContext = {
|
||||
user: undefined,
|
||||
}
|
||||
|
||||
|
||||
29
client/src/util/Protect.tsx
Normal file
29
client/src/util/Protect.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useContext } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button, Page } from "../components/ui";
|
||||
import Divider from "../components/ui/Divider";
|
||||
import { AuthContext } from "../context/AuthContext";
|
||||
|
||||
export default function Protect({ children = <></> }) {
|
||||
const { user } = useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<Page>
|
||||
<div className="content-unauthorized">
|
||||
<h1>Hi there! You don't look too familiar.</h1>
|
||||
<p>To view the content on this page, please log in below:</p>
|
||||
<Divider />
|
||||
<Button onClick={() => navigate('/login')}>Log In</Button>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Page>
|
||||
{ children }
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,9 @@
|
||||
import { NextFunction, Request, Response } from "express"
|
||||
|
||||
export function restrictAccess(req: Request, res: Response, next: NextFunction) {
|
||||
if (!req.isAuthenticated()) {
|
||||
res.status(403).send({ message: "Access forbidden" });
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
export function checkAccess(req: Request, res: Response, next: NextFunction) {
|
||||
if (req.isAuthenticated()) {
|
||||
next();
|
||||
} else {
|
||||
res.status(403).send({ message: "Access forbidden" });
|
||||
res.send({ ok: false, user: undefined })
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { IUser, IUserAuth } from "../schemas";
|
||||
import AuthService from "../auth";
|
||||
import { UserCtl } from "../controllers";
|
||||
import now from "../util/now";
|
||||
import { checkAccess, restrictAccess } from "../auth/middlewares";
|
||||
import { restrictAccess } from "../auth/middlewares";
|
||||
import { Session } from "express-session";
|
||||
const AuthInstance = new AuthService();
|
||||
const UserControl = new UserCtl();
|
||||
@@ -14,20 +14,17 @@ const router = Router();
|
||||
export const authRoute = (app: Express, passport: PassportStatic) => {
|
||||
app.use('/auth', router);
|
||||
|
||||
router.get('/', checkAccess, (req, res, next) => {
|
||||
if (req.isAuthenticated()) {
|
||||
// @ts-ignore: does not recognize structure of req.user
|
||||
const user = req.user?.user;
|
||||
const userData: IUser = {
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
handle: user.handle,
|
||||
email: user.email
|
||||
}
|
||||
res.send({ user: userData });
|
||||
} else {
|
||||
res.status(403).send({ message: "Access forbidden" });
|
||||
router.get('/', restrictAccess, (req, res, next) => {
|
||||
// @ts-ignore: does not recognize structure of req.user
|
||||
const user = req.user?.user;
|
||||
const userData: IUser = {
|
||||
id: user.id,
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
handle: user.handle,
|
||||
email: user.email
|
||||
}
|
||||
res.send({ user: userData });
|
||||
})
|
||||
|
||||
router.get('/protected', restrictAccess, (req, res, next) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
interface HasHistory {
|
||||
interface HasHistory extends DBEntity {
|
||||
datecreated?: string
|
||||
datemodified?: string
|
||||
}
|
||||
|
||||
interface CanDeactivate {
|
||||
interface CanDeactivate extends DBEntity {
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ interface DBEntity {
|
||||
id?: number
|
||||
}
|
||||
|
||||
export interface IUser extends DBEntity, HasHistory, CanDeactivate {
|
||||
export interface IUser extends HasHistory, CanDeactivate {
|
||||
firstname: string
|
||||
lastname: string
|
||||
handle: string
|
||||
@@ -24,25 +24,25 @@ export interface IUserAuth {
|
||||
password: string
|
||||
}
|
||||
|
||||
export interface IRecipe extends DBEntity, HasHistory, CanDeactivate {
|
||||
export interface IRecipe extends HasHistory, CanDeactivate {
|
||||
name: string
|
||||
description?: string
|
||||
preptime: string
|
||||
authoruserid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IIngredient extends DBEntity, HasHistory {
|
||||
export interface IIngredient extends HasHistory {
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface ICollection extends DBEntity, HasHistory, CanDeactivate {
|
||||
export interface ICollection extends HasHistory, CanDeactivate {
|
||||
name: string
|
||||
ismaincollection: boolean
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IGroceryList extends DBEntity, HasHistory, CanDeactivate {
|
||||
export interface IGroceryList extends HasHistory, CanDeactivate {
|
||||
name: string
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
Reference in New Issue
Block a user