Skip to content
Snippets Groups Projects
Commit d71bbb1e authored by Federico Hurtado's avatar Federico Hurtado
Browse files

Set up user identification from the JWT token.

parent 86152a40
No related branches found
No related tags found
1 merge request!12Merge request with Backend for sprint 3/4
...@@ -35,11 +35,16 @@ const casLogin = async function (req, res, next) { ...@@ -35,11 +35,16 @@ const casLogin = async function (req, res, next) {
// sign the token with secret key // sign the token with secret key
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" }); const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" });
console.log("sending token for use in localhost"); // Set the token as an HTTP-only cookie
res.cookie("auth_token", token, {
maxAge: 3600000, // 1 hour in milliseconds
});
console.log("sent token for use in localhost");
console.log("Frontend: ", process.env.FRONTEND_URL); console.log("Frontend: ", process.env.FRONTEND_URL);
res.redirect(`${process.env.FRONTEND_URL}/home?token=${token}`); res.redirect(`${process.env.FRONTEND_URL}/home`);
return; return;
} }
...@@ -79,6 +84,10 @@ const casLogin = async function (req, res, next) { ...@@ -79,6 +84,10 @@ const casLogin = async function (req, res, next) {
// sign the token with secret key // sign the token with secret key
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" }); const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" });
res.cookie("auth_token", token, {
maxAge: 3600000, // 1 hour in milliseconds
});
// document a successful login // document a successful login
try { try {
const timestamp = new Date(); // Current timestamp const timestamp = new Date(); // Current timestamp
...@@ -89,7 +98,7 @@ const casLogin = async function (req, res, next) { ...@@ -89,7 +98,7 @@ const casLogin = async function (req, res, next) {
// Send the JWT token to the frontend // Send the JWT token to the frontend
console.log("sending JWT To: ", process.env.FRONTEND_URL); console.log("sending JWT To: ", process.env.FRONTEND_URL);
res.redirect(`${process.env.FRONTEND_URL}/home?token=${token}`); res.redirect(`${process.env.FRONTEND_URL}/home`);
console.log("Successfully authenticated and generated token."); console.log("Successfully authenticated and generated token.");
}); });
......
...@@ -77,9 +77,10 @@ class DatabaseInitializer { ...@@ -77,9 +77,10 @@ class DatabaseInitializer {
try { try {
await addRoleIfNotExists(1, "guest", "Guest access"); await addRoleIfNotExists(1, "guest", "Guest access");
await addRoleIfNotExists(2, "admin", "Admin access"); await addRoleIfNotExists(2, "user", "Basic user access");
await addRoleIfNotExists(3, "classChampion", "Class champion access"); await addRoleIfNotExists(3, "admin", "Admin access");
await addRoleIfNotExists(4, "orgLeader", "Org leader access"); await addRoleIfNotExists(4, "classChampion", "Class champion access");
await addRoleIfNotExists(5, "orgLeader", "Org leader access");
console.log("Roles initialized successfully."); console.log("Roles initialized successfully.");
} catch (error) { } catch (error) {
console.log("error initializing roles: ", error); console.log("error initializing roles: ", error);
......
...@@ -131,7 +131,4 @@ CREATE TABLE IF NOT EXISTS changeLog ( ...@@ -131,7 +131,4 @@ CREATE TABLE IF NOT EXISTS changeLog (
oldValues TEXT, -- JSON format for previous values oldValues TEXT, -- JSON format for previous values
newValues TEXT, -- JSON format for new values newValues TEXT, -- JSON format for new values
FOREIGN KEY (userId) REFERENCES users(userID) FOREIGN KEY (userId) REFERENCES users(userID)
); );
\ No newline at end of file
INSERT INTO countryLookup (countryId, name)
VALUES (1, 'United States');
This diff is collapsed.
...@@ -8,56 +8,44 @@ import { jwtDecode } from "jwt-decode"; ...@@ -8,56 +8,44 @@ import { jwtDecode } from "jwt-decode";
Home page where users will be redirected after log in or continuing as a guest Home page where users will be redirected after log in or continuing as a guest
*/ */
function Home() { function Home() {
// username and privilage to be extracted from JWT token // when the page mounts check for auth tokens
const [username, setUsername] = useState(""); useEffect(() => {
const [privilege, setPrivilege] = useState(""); const readLoginCookie = () => {
try {
const extractTokenFromUrl = () => { // find the auth cookie sent from the backend
const params = new URLSearchParams(window.location.search); const cookies = document.cookie;
const token = params.get("token"); const cookieArray = cookies.split("; ");
const authCookie = cookieArray.find((cookie) =>
// no token found cookie.startsWith("auth_token=")
if (!token) { );
// user will be seen as a guest
setUsername("guest");
setPrivilege("guest");
}
// decode the token and set the user info // return early if no cookie found
try { if (!authCookie) {
const decoded = jwtDecode(token); console.log("cannot find auth cookie.");
setUsername(decoded.username); return;
setPrivilege(decoded.role); }
} catch (error) {
console.error("Error decoding token: ", error);
}
};
// useEffect to make the API call // extract the token from the cookie
useEffect(() => { const token = authCookie.split("=")[1];
extractTokenFromUrl(); // extract the username and role from the token
}, []);
return ( // decode the token
// <div> const decoded = jwtDecode(token);
// <h1>Home Page</h1>
// <p> console.log("decoded token: ", decoded);
// Below are the results of calling the backend server. The API URL should
// be localhost in development and be
// http://corpsdirectory.discovery.cs.vt.edu/api in the cluster.
// </p>
// {/* Display data if it exists */} // extract details from token and store them in memory
// <p> localStorage.setItem("userId", decoded.id);
// Data: {data ? <span>{JSON.stringify(data)}</span> : <span>&nbsp;</span>} localStorage.setItem("peopleId", decoded.peopleId);
// </p> localStorage.setItem("role", decoded.role);
} catch (error) {
console.log("error reading cookie: ", error);
}
};
// <p>API URL: {process.env.REACT_APP_API_URL}</p> readLoginCookie();
}, []);
// {/* display error if there is an error*/} return (
// <p>Error: {error ? <span>{error}</span> : <span>&nbsp;</span>}</p>
// </div>
<> <>
<div className="text-center"> <div className="text-center">
<h1 className="thin-veranda">VT Cadet Directory</h1> <h1 className="thin-veranda">VT Cadet Directory</h1>
...@@ -70,16 +58,7 @@ function Home() { ...@@ -70,16 +58,7 @@ function Home() {
Virginia Tech Corps of Cadets Directory Virginia Tech Corps of Cadets Directory
</h1> </h1>
{/*Adding this here so you guys see how to access but feel free to change it*/} {/*Adding this here so you guys see how to access but feel free to change it*/}
{username && (
<div>
<h2>
Welcome, <strong>{username}</strong>!
</h2>
<p>
Your role: <strong>{privilege}</strong>
</p>
</div>
)}
<h1 className="description-font"> <h1 className="description-font">
Lorem ipsum odor amet, consectetuer adipiscing elit. Primis quam Lorem ipsum odor amet, consectetuer adipiscing elit. Primis quam
vel posuere lobortis inceptos. Nostra sociosqu tristique sagittis vel posuere lobortis inceptos. Nostra sociosqu tristique sagittis
...@@ -105,28 +84,6 @@ function Home() { ...@@ -105,28 +84,6 @@ function Home() {
<img src={logo} alt="Corps Logo" className="logo" width={400} /> <img src={logo} alt="Corps Logo" className="logo" width={400} />
</div> </div>
</div> </div>
<div className="selection-section">
<div className="button-container">
{/* <div className="button-wrapper">
<button className="action-button">
<img src={logo} width={70} alt="Browse" className="icon" />
</button>
<span>Browse</span>
</div> */}
{/* <div className="button-wrapper">
<button className="action-button">
<img src={logo} alt="Search" className="icon" />
</button>
<span>Search</span>
</div> */}
{/* <div className="button-wrapper">
<button className="action-button">
<img src={logo} alt="Message" className="icon" />
</button>
<span>Message</span>
</div> */}
</div>
</div>
</> </>
); );
} }
......
...@@ -36,29 +36,67 @@ const Navbar = () => { ...@@ -36,29 +36,67 @@ const Navbar = () => {
<ul className={styles.navList}> <ul className={styles.navList}>
{/* Common Links */} {/* Common Links */}
<li> <li>
<Link to="/home">Home</Link> <Link
to="/home"
className={({ isActive }) => (isActive ? "active" : "")}
>
Home
</Link>
</li> </li>
<li> <li>
<Link to="/browse">Browse</Link> <Link
to="/browse"
className={({ isActive }) => (isActive ? "active" : "")}
>
Browse
</Link>
</li> </li>
<li> <li>
<Link to="/search">Search</Link> <Link
to="/search"
className={({ isActive }) => (isActive ? "active" : "")}
>
Search
</Link>
</li> </li>
{/* Links for logged-out users */} {/* Links for logged-out users */}
{!isLoggedIn && ( {!isLoggedIn && (
<> <li>
<Link
to="/login"
className={({ isActive }) => (isActive ? "active" : "")}
>
Login
</Link>
</li>
)}
{/* Admin-specific Links */}
{isLoggedIn &&
(role === "admin" ||
role === "classChampion" ||
role === "orgLeader") && (
<li> <li>
<Link to="/login">Login</Link> <Link
to="/admin/dashboard"
className={({ isActive }) => (isActive ? "active" : "")}
>
Admin
</Link>
</li> </li>
</> )}
)}
{/* Links for logged-in users */} {/* Links for logged-in users */}
{isLoggedIn && ( {isLoggedIn && (
<> <>
<li> <li>
<Link to="/my-profile">My Profile</Link> <Link
to="/my-profile"
className={({ isActive }) => (isActive ? "active" : "")}
>
My Profile
</Link>
</li> </li>
<li> <li>
<button onClick={handleLogout} className={styles.logoutButton}> <button onClick={handleLogout} className={styles.logoutButton}>
...@@ -67,16 +105,6 @@ const Navbar = () => { ...@@ -67,16 +105,6 @@ const Navbar = () => {
</li> </li>
</> </>
)} )}
{/* Admin-specific Link */}
{isLoggedIn &&
(role === "admin" ||
role === "classChampion" ||
role === "orgLeader") && (
<li>
<Link to="/admin/dashboard">Admin</Link>
</li>
)}
</ul> </ul>
</nav> </nav>
); );
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
/* Navbar links */ /* Navbar links */
.navList li a { .navList li a {
margin: 0 80px; /* Increase margin to space out links */ margin: 0 80px; /* Space out links */
color: white; color: white;
text-decoration: none; text-decoration: none;
font-size: 20px; font-size: 20px;
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
/* Hover effect for navbar links */ /* Hover effect for navbar links */
.navList li a:hover { .navList li a:hover {
color: rgb(13, 28, 84); /* Changes text color on hover */ color: rgb(13, 28, 84); /* Hover color */
} }
/* Underline effect on hover */ /* Underline effect on hover */
...@@ -44,5 +44,29 @@ ...@@ -44,5 +44,29 @@
} }
.navList li a:hover::after { .navList li a:hover::after {
width: 100%; /* Expands underline on hover */ width: 100%; /* Expands underline */
}
/* Active link styling */
.navList li a.activeLink {
font-weight: bold;
color: rgb(0, 47, 255); /* Same as underline color */
}
/* Logout button styles */
.logoutButton {
background-color: white;
color: black;
border: none;
padding: 8px 15px;
font-size: 16px;
font-weight: 500;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease-in-out;
}
.logoutButton:hover {
background-color: rgb(0, 47, 255); /* Matches underline hover */
color: white;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment