diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 612b1a17..551cb7ef 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -21,7 +21,7 @@ "react-responsive": "^9.0.2", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", - "react-toastify": "^8.0.2", + "react-toastify": "^8.2.0", "web-vitals": "^3.5.1" }, "devDependencies": { diff --git a/webapp/package.json b/webapp/package.json index 956a9a01..c8e06232 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -16,8 +16,8 @@ "react-responsive": "^9.0.2", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", - "web-vitals": "^3.5.1", - "react-toastify": "^8.0.2" + "react-toastify": "^8.2.0", + "web-vitals": "^3.5.1" }, "scripts": { "start": "react-scripts start", diff --git a/webapp/src/App.js b/webapp/src/App.js index 92a81f29..190159fc 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -1,25 +1,17 @@ import React from 'react'; -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import { BrowserRouter as Router, Route } from "react-router-dom"; import Navbar from "./components/Navbar"; -import Home from "./components/Home"; -import Inicio from './components/Inicio'; -import Primera from './components/Primera'; -import Game from './components/QuizGame'; +import AuthProvider from './components/login/AuthProvider'; +import Routes from './components/Routes'; function App() { return ( - -
- - } /> - } /> - } /> - } /> - -
-
+ + + + ); } diff --git a/webapp/src/components/ProtectedRoute.js b/webapp/src/components/ProtectedRoute.js new file mode 100644 index 00000000..12148098 --- /dev/null +++ b/webapp/src/components/ProtectedRoute.js @@ -0,0 +1,16 @@ +import { Navigate, Outlet } from "react-router-dom"; +import { useAuth } from "./login/AuthProvider"; +import Navbar from "./Navbar"; + +export const ProtectedRoute = () => { + const { token } = useAuth(); + + // Check if the user is authenticated + if (!token) { + // If not authenticated, redirect to the login page + return ; + } + + // If authenticated, render the child routes + return
; + }; \ No newline at end of file diff --git a/webapp/src/components/Routes.js b/webapp/src/components/Routes.js new file mode 100644 index 00000000..c92a54dc --- /dev/null +++ b/webapp/src/components/Routes.js @@ -0,0 +1,64 @@ +import { RouterProvider, createBrowserRouter } from "react-router-dom"; +import { useAuth } from "./login/AuthProvider"; +import { ProtectedRoute } from "./ProtectedRoute"; +import Home from "./Home"; +import Inicio from './Inicio'; +import Primera from './Primera'; +import Game from './QuizGame'; +import Navbar from "./Navbar"; + +const Routes = () => { + const { token } = useAuth(); + + // Define public routes accessible to all users + const routesForPublic = [ + { + path: "/", + element: , + }, + { + path: "/login", + element: , + }, + ]; + + // Define routes accessible only to authenticated users + const routesForAuthenticatedOnly = [ + { + path: "/", + element: , // Wrap the component in ProtectedRoute + children: [ + { + path: "/", + element: , + }, + { + path: "/game", + element: , + }, + { + path: "/home", + element: , + }, + ], + }, + ]; + + // Define routes accessible only to non-authenticated users + const routesForNotAuthenticatedOnly = [ + + ]; + + // Combine and conditionally include routes based on authentication status + const router = createBrowserRouter([ + ...routesForPublic, + ...(!token ? routesForNotAuthenticatedOnly : []), + ...routesForAuthenticatedOnly, + ]); + + // Provide the router configuration using RouterProvider + return + ; +}; + +export default Routes; \ No newline at end of file diff --git a/webapp/src/components/login/AuthProvider.js b/webapp/src/components/login/AuthProvider.js new file mode 100644 index 00000000..8a38c38c --- /dev/null +++ b/webapp/src/components/login/AuthProvider.js @@ -0,0 +1,44 @@ +import axios from "axios"; +import { createContext, useContext, useEffect, useMemo, useState } from "react"; + +const AuthContext = createContext(); + +const AuthProvider = ({ children }) => { + // State to hold the authentication token + const [token, setToken_] = useState(localStorage.getItem("token")); + + // Function to set the authentication token + const setToken = (newToken) => { + setToken_(newToken); + }; + + useEffect(() => { + if (token) { + axios.defaults.headers.common["Authorization"] = "Bearer " + token; + localStorage.setItem('token',token); + } else { + delete axios.defaults.headers.common["Authorization"]; + localStorage.removeItem('token') + } + }, [token]); + + // Memoized value of the authentication context + const contextValue = useMemo( + () => ({ + token, + setToken, + }), + [token] + ); + + // Provide the authentication context to the children components + return ( + {children} + ); +}; + +export const useAuth = () => { + return useContext(AuthContext); +}; + +export default AuthProvider; \ No newline at end of file diff --git a/webapp/src/components/login/Login.js b/webapp/src/components/login/Login.js index 89f77154..517301b1 100644 --- a/webapp/src/components/login/Login.js +++ b/webapp/src/components/login/Login.js @@ -4,6 +4,8 @@ import axios from 'axios'; import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; import './Login.css'; import logo from '../logo.png' +import { useAuth } from "./AuthProvider"; + const Login = () => { const [username, setUsername] = useState(''); @@ -15,11 +17,16 @@ const Login = () => { const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + const { setToken } = useAuth(); + + const loginUser = async () => { try { - await axios.post(`${apiEndpoint}/login`, { username, password }); + let res= await axios.post(`${apiEndpoint}/login`, { username, password }); // Extract data from the response + setToken(res.data.token); + console.log(res); setLoginSuccess(true);