Skip to content

Commit

Permalink
Set student view and updated role permissions (#47)
Browse files Browse the repository at this point in the history
Co-authored-by: Ethan Ho <[email protected]>
Co-authored-by: ThatMegamind <[email protected]>
  • Loading branch information
3 people authored Mar 5, 2024
1 parent 035081f commit 2a1a57f
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 40 deletions.
34 changes: 22 additions & 12 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@ import PublishedSchedule from './pages/PublishedSchedule/PublishedSchedule';
import Playground from './pages/Playground/Playground';
import Planner from './pages/Planner/Planner';
import Navbar from './components/Navbar/Navbar';
import { auth, getCurrentUser } from './utils/auth_utils';
import NotificationSandbox from './pages/NotificationSandbox/NotificationSandbox';
import { AuthContextProvider, useAuthContext } from './common/AuthContext';

const { ADMIN_ROLE, USER_ROLE } = AUTH_ROLES.AUTH_ROLES;
const currentUser = getCurrentUser(auth);
console.log(currentUser);

const App = () => {
const NavBarWrapper = () => (
<>
<Navbar />
<Outlet />
</>
);
const NavBarWrapper = () => {
const { currentUser } = useAuthContext();
return (
<>
<Navbar hasLoaded={currentUser != null} isAdmin={currentUser?.type === ADMIN_ROLE}/>
<Outlet />
</>
);
};

return (
<ChakraProvider>
<CookiesProvider>
<AuthContextProvider>
<Router>
<Routes>
<Route element={currentUser ? <NavBarWrapper /> : null}>
<Route element={<NavBarWrapper />}>
<Route
exact
path="/"
Expand Down Expand Up @@ -66,7 +69,7 @@ const App = () => {
<ProtectedRoute
Component={Catalog}
redirectPath="/login"
roles={[ADMIN_ROLE, USER_ROLE]}
roles={[ADMIN_ROLE]}
/>
}
/>
Expand All @@ -82,10 +85,17 @@ const App = () => {
}
/>
<Route exact path="/playground" element={<Playground />} />
<Route exact path="/planner" element={<Planner />} />
<Route exact path="/planner" element={
<ProtectedRoute
Component={Planner}
redirectPath="/login"
roles={[ADMIN_ROLE]}
/>
} />
</Route>
</Routes>
</Router>
</AuthContextProvider>
</CookiesProvider>
</ChakraProvider>
);
Expand Down
25 changes: 25 additions & 0 deletions src/common/AuthContext.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable react/jsx-no-constructed-context-values */
import { createContext, useState, useContext } from 'react';
import PropTypes from 'prop-types';

const AuthContext = createContext({
currentUser: null,
setCurrentUser: () => {},
});

const useAuthContext = () => {
return useContext(AuthContext);
};

const AuthContextProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
return (
<AuthContext.Provider value={{ currentUser, setCurrentUser }}>{children}</AuthContext.Provider>
);
};

AuthContextProvider.propTypes = {
children: PropTypes.node.isRequired,
};

export { useAuthContext, AuthContextProvider };
61 changes: 51 additions & 10 deletions src/components/Navbar/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { NavLink } from 'react-router-dom';
import { Flex, HStack, Link, Text, Image } from '@chakra-ui/react';
import { BellIcon } from '@chakra-ui/icons';
import PropTypes from 'prop-types';

import Logout from '../Authentication/Logout';

const Navbar = () => {
const Navbar = ({ hasLoaded, isAdmin }) => {
// console.log(hasLoaded, isAdmin);
const makeNavTabs = (page, path) => {
const selectedTab = location.pathname == path;
return (
Expand All @@ -28,7 +31,42 @@ const Navbar = () => {
</Link>
);
};
return (

if (!hasLoaded) {
return null;
}

if (isAdmin) {
return (
<Flex
style={{ backgroundColor: '#243268', padding: '0 100px 0 100px' }}
justify={'space-between'}
width={'100%'}
align="center"
position={'sticky'}
as={'nav'}
>
<HStack>
<Flex align={'center'}>
<Image src="../../../aiss-logo.png" marginRight={'48px'}></Image>
{makeNavTabs('Schedule', '/publishedSchedule')}
{makeNavTabs('Catalog', '/catalog')}
</Flex>
</HStack>
<Flex alignSelf={'right'} marginLeft={'auto'}>
<BellIcon
color="white"
alignSelf={'right'}
width={'24px'}
height={'24px'}
marginRight={'48px'}
/>
<Logout alignSelf={'right'} />
</Flex>
</Flex>
)
}
return (
<Flex
style={{ backgroundColor: '#243268', padding: '0 100px 0 100px' }}
justify={'space-between'}
Expand All @@ -41,21 +79,24 @@ const Navbar = () => {
<Flex align={'center'}>
<Image src="../../../aiss-logo.png" marginRight={'48px'}></Image>
{makeNavTabs('Schedule', '/publishedSchedule')}
{makeNavTabs('Catalog', '/catalog')}
</Flex>
</HStack>
<Flex alignSelf={'right'} marginLeft={'auto'}>
<BellIcon
color="white"
alignSelf={'right'}
width={'24px'}
height={'24px'}
marginRight={'48px'}
/>
<Logout alignSelf={'right'} />
</Flex>

</Flex>
);
};

Navbar.propTypes = {
hasLoaded: PropTypes.bool,
isAdmin: PropTypes.bool,
};

Navbar.defaultProps = {
hasLoaded: false,
isAdmin: false,
};

export default Navbar;
22 changes: 15 additions & 7 deletions src/pages/PublishedSchedule/PublishedSchedule.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { NPOBackend } from '../../utils/auth_utils.js';
import PublishedScheduleTable from '../../components/Events/PublishedScheduleTable.jsx';
import AUTH_ROLES from '../../utils/auth_config.js';
import { useAuthContext } from '../../common/AuthContext.jsx';

import { useEffect, useState } from 'react';
const { ADMIN_ROLE, USER_ROLE } = AUTH_ROLES.AUTH_ROLES;
import { Box, Select, Text } from '@chakra-ui/react';

const PublishedSchedule = () => {
// get data from database
const {currentUser} = useAuthContext();
const [allSeasons, setAllSeasons] = useState([]);
const [selectedSeason, setSelectedSeason] = useState('');

Expand All @@ -30,6 +34,9 @@ const PublishedSchedule = () => {
useEffect(() => {
const renderTable = async () => {
const { data } = await NPOBackend.get('/published-schedule/all-seasons');

setSelectedSeason(currentUser.type === USER_ROLE ? data[0] : ''); // We assume the current season is the first one in the list

const index = data.indexOf(curSeason);
if (index !== -1) {
data.splice(index, 1);
Expand All @@ -44,10 +51,12 @@ const PublishedSchedule = () => {
return seasonOrder.indexOf(a.split(' ')[0]) - seasonOrder.indexOf(b.split(' ')[0]);
}
});

setAllSeasons(data);

};
renderTable();
}, []);
renderTable();
}, [currentUser]);

const curSeason = getTodaySeason();

Expand All @@ -71,11 +80,10 @@ const PublishedSchedule = () => {
onChange={() => setSelectedSeason(event.target.value)}
width="23%"
>
{allSeasons.map(item => (
<option key={item} value={item}>
{item}
</option>
))}
{ currentUser.type === ADMIN_ROLE ?
allSeasons.map(item => (
<option key={item} value={item}>{item}</option>
)) : null }
</Select>

{/* tables for each season */}
Expand Down
16 changes: 11 additions & 5 deletions src/utils/ProtectedRoute.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import { Navigate } from 'react-router-dom';
import { PropTypes, instanceOf } from 'prop-types';
import { withCookies, cookieKeys, Cookies, clearCookies } from './cookie_utils';
import { NPOBackend, refreshToken } from './auth_utils';
import { useAuthContext } from '../common/AuthContext';

const userIsAuthenticated = async (roles, cookies) => {
try {
const accessToken = await refreshToken(cookies);
const { accessToken, currentUser } = await refreshToken(cookies);
// const accessToken = await refreshToken(cookies);
if (!accessToken) {
return false;
}
const loggedIn = await NPOBackend.get(`/auth/verifyToken/${accessToken}`);

return roles.includes(cookies.get(cookieKeys.ROLE)) && loggedIn.status === 200 && cookies.get(cookieKeys.APPROVED);
// return roles.includes(cookies.get(cookieKeys.ROLE));
return {
authenticated: roles.includes(cookies.get(cookieKeys.ROLE)) && loggedIn.status === 200 && cookies.get(cookieKeys.APPROVED),
currentUser,
};
} catch (err) {
console.log(err);
clearCookies(cookies);
Expand All @@ -32,16 +36,18 @@ const userIsAuthenticated = async (roles, cookies) => {
const ProtectedRoute = ({ Component, redirectPath, roles, cookies }) => {
const [isLoading, setIsLoading] = useState(true);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const { setCurrentUser } = useAuthContext();

useEffect(() => {
const checkAuthentication = async () => {
const authenticated = await userIsAuthenticated(roles, cookies);
const { authenticated, currentUser } = await userIsAuthenticated(roles, cookies);
setIsAuthenticated(authenticated);
setCurrentUser(currentUser);
setIsLoading(false);
};

checkAuthentication();
}, [roles, cookies]);
}, [roles, cookies, setCurrentUser]);
if (isLoading) {
return <h1>LOADING...</h1>;
}
Expand Down
4 changes: 2 additions & 2 deletions src/utils/auth_config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Sample roles, feel free to change
const AUTH_ROLES = {
ADMIN_ROLE: 'superadmin',
USER_ROLE: 'admin',
ADMIN_ROLE: 'admin',
USER_ROLE: 'student',
};

export default { AUTH_ROLES };
7 changes: 3 additions & 4 deletions src/utils/auth_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,9 @@ const refreshToken = async () => {
});
// Sets the appropriate cookies after refreshing access token
setCookie(cookieKeys.ACCESS_TOKEN, idToken, cookieConfig);
// const user = await NPOBackend.get(`/users/${auth.currentUser.uid}`);
// setCookie(cookieKeys.ROLE, user.data.user.role, cookieConfig);
setCookie(cookieKeys.ROLE, 'admin', cookieConfig);
return idToken;
const user = await NPOBackend.get(`/users/${auth.currentUser.uid}`);
setCookie(cookieKeys.ROLE, user.data[0].type, cookieConfig);
return {accessToken: idToken, currentUser: user.data[0]};
}
return null;
};
Expand Down

0 comments on commit 2a1a57f

Please sign in to comment.