diff --git a/webapp/package-lock.json b/webapp/package-lock.json index fe3ba95d..50a79984 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -20,7 +20,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 61997253..c8e06232 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -16,7 +16,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" }, "scripts": { diff --git a/webapp/src/App.js b/webapp/src/App.js index 0e2dc17d..1cee417b 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 45d14d6a..229bab48 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,6 +17,9 @@ const Login = () => { const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + const { setToken } = useAuth(); + + const loginUser = async () => { try { if(username.trim().length ===0 || password.trim().length===0) @@ -23,9 +28,12 @@ const Login = () => { return; } - 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);