From 43de9c98eff8a780c9b7628f947cc21bc6e3265d Mon Sep 17 00:00:00 2001 From: Flavien G <44913995+fgaujard@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:56:20 +0100 Subject: [PATCH] Keep Session logged and block access if denied --- backend/src/controllers/authControllers.js | 29 +++++++++++++++++- backend/src/middleware/authMiddleware.js | 12 ++++---- backend/src/router.js | 14 ++++++--- frontend/src/main.jsx | 35 ++++++++++++++++++---- frontend/src/pages/Connexion.jsx | 2 ++ frontend/src/pages/Recipe.jsx | 22 +++++++++----- frontend/src/pages/RecipeList.jsx | 13 ++++---- frontend/src/pages/style/RecipeList.scss | 22 +++++++++----- 8 files changed, 111 insertions(+), 38 deletions(-) diff --git a/backend/src/controllers/authControllers.js b/backend/src/controllers/authControllers.js index 3261d57..3049a90 100644 --- a/backend/src/controllers/authControllers.js +++ b/backend/src/controllers/authControllers.js @@ -42,6 +42,7 @@ const login = async (req, res, next) => { try { // Verify if the username exist in the database const user = await tables.user.readByUsername(req.body.username); + console.info(user); if (user) { // Verify if the password match with the hashed in the database @@ -50,7 +51,7 @@ const login = async (req, res, next) => { if (verified) { // Create a token for open & keep the user session as logged const token = jwt.sign( - { username: user.username, is_admin: user.is_admin }, + { id: user.id, username: user.username, is_admin: user.is_admin }, process.env.APP_SECRET, { expiresIn: "1h" } ); @@ -72,11 +73,37 @@ const login = async (req, res, next) => { } }; +const verifyToken = async (req, res, next) => { + try { + const { token } = req.cookies; + + if (!token) { + res.status(401).json({ error: "No token founded" }); + } else { + const decoded = jwt.verify(token, process.env.APP_SECRET); + const user = await tables.user.read(decoded.id); + if (user) + res.status(200).json({ + success: "User is valid", + is_loggin: true, + is_admin: decoded.is_admin, + }); + else + res + .status(401) + .json({ error: "The token is invalid", is_loggin: false }); + } + } catch (err) { + next(err); + } +}; + module.exports = { // browse, readByUsername, readByEmail, login, + verifyToken, // edit, // add, // destroy, diff --git a/backend/src/middleware/authMiddleware.js b/backend/src/middleware/authMiddleware.js index cd05213..6bae066 100644 --- a/backend/src/middleware/authMiddleware.js +++ b/backend/src/middleware/authMiddleware.js @@ -24,20 +24,18 @@ const verifyToken = async (req, res, next) => { try { const { token } = req.cookies; - console.info(req.cookies); - - console.info(token); - if (!token) { res.status(401).json({ error: "No token founded" }); } else { const decoded = jwt.verify(token, process.env.APP_SECRET); + console.info(decoded); const user = await tables.user.read(decoded.id); - console.info({ user }); - next(); + console.info(user); + if (user) next(); + else res.status(401).json({ error: "The token is invalid" }); } } catch (err) { - res.status(401).json({ error: "The token is invalid" }); + res.status(401).json({ error: "Internal error" }); } }; diff --git a/backend/src/router.js b/backend/src/router.js index 1136bb1..206f1a6 100644 --- a/backend/src/router.js +++ b/backend/src/router.js @@ -24,15 +24,22 @@ const AuthControllers = require("./controllers/authControllers"); // Import the middleware for hash password in DB when a new user register const AuthMiddleware = require("./middleware/authMiddleware"); +router.post("/login", AuthControllers.login); +router.post("/users", AuthMiddleware.hashPwd, UserControllers.add); +router.get("/verify-token", AuthControllers.verifyToken); + +router.use(AuthMiddleware.verifyToken); + router.get("/users", UserControllers.browse); // Route to get a list of items router.get("/users/:id", UserControllers.read); // Route to get a specific item by ID -router.post("/users", AuthMiddleware.hashPwd, UserControllers.add); router.put( "/users/:id", uploadUsersAvatars.single("avatar"), UserControllers.edit -); // Route to update user +); + +// Route to update user router.post( "/users", AuthMiddleware.hashPwd, @@ -43,7 +50,6 @@ router.post( // Route to get specific items and block the register if they exists router.get("/username/:username", AuthControllers.readByUsername); router.get("/email/:email", AuthControllers.readByEmail); -router.post("/login", AuthControllers.login); /* ************************************************************************* */ // RECIPE @@ -52,7 +58,7 @@ router.post("/login", AuthControllers.login); // Import recipeControllers module for handling item-related operations const RecipeControllers = require("./controllers/recipeControllers"); -router.get("/recipes", AuthMiddleware.verifyToken, RecipeControllers.browse); // Route to get a list of items +router.get("/recipes", RecipeControllers.browse); // Route to get a list of items router.get("/recipes/:id", RecipeControllers.read); // Route to get a specific item by ID router.get("/recipebyuser/:id", RecipeControllers.readByUser); router.post( diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 727576d..ed4c576 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -20,17 +20,40 @@ const router = createBrowserRouter([ { path: "/recipes", element: , + loader: () => { + return Promise.all([ + axios.get(`${import.meta.env.VITE_BACKEND_URL}/api/recipes`, { + withCredentials: true, + }), + axios.get(`${import.meta.env.VITE_BACKEND_URL}/api/tags`, { + withCredentials: true, + }), + ]) + .then(([recipeResponse, tagsResponse]) => { + const recipe = recipeResponse.data; // Accédez aux données de la réponse + const tags = tagsResponse.data; // Accédez aux données de la réponse + return Promise.all([{ recipe }, { tags }]); + }) + .catch(() => { + // Gérez l'erreur ici (redirection vers "/connexion" par exemple) + window.location.href = "/connexion"; + }); + }, }, { path: "/recipes/:id", element: , loader: ({ params }) => { - return axios.get( - `${import.meta.env.VITE_BACKEND_URL}/api/recipes/${params.id}`, - { - withCredentials: true, - } - ); + return axios + .get( + `${import.meta.env.VITE_BACKEND_URL}/api/recipes/${params.id}`, + { + withCredentials: true, + } + ) + .catch(() => { + window.location.href = "/connexion"; + }); }, }, { diff --git a/frontend/src/pages/Connexion.jsx b/frontend/src/pages/Connexion.jsx index 204d7a6..98e5ede 100644 --- a/frontend/src/pages/Connexion.jsx +++ b/frontend/src/pages/Connexion.jsx @@ -2,6 +2,7 @@ import { useState } from "react"; import PropTypes from "prop-types"; import { ToastContainer, toast } from "react-toastify"; import axios from "axios"; + import { isValidUsername, isValidEmail, @@ -13,6 +14,7 @@ import { resetErrMsgPassConfSign, resetAllErrMsgSign, } from "./services/postUserValid"; + import "react-toastify/dist/ReactToastify.css"; import "./style/Connexion.scss"; diff --git a/frontend/src/pages/Recipe.jsx b/frontend/src/pages/Recipe.jsx index 6c11b38..d3dea71 100644 --- a/frontend/src/pages/Recipe.jsx +++ b/frontend/src/pages/Recipe.jsx @@ -13,14 +13,20 @@ function Recipe({ name, title, difficulty, id, image, tag1, tag2, tag3 }) {

{name}

{title}

-

{difficulty}

-

{tag1}

-

{tag2}

-

{tag3}

-
- -

En savoir plus

- +
+

{difficulty}

+
+
+

{tag1}

+

{tag2}

+

{tag3}

+
+
+ +

En savoir plus

+ +
+
diff --git a/frontend/src/pages/RecipeList.jsx b/frontend/src/pages/RecipeList.jsx index 9b1ef4e..6f776df 100644 --- a/frontend/src/pages/RecipeList.jsx +++ b/frontend/src/pages/RecipeList.jsx @@ -1,13 +1,14 @@ -import axios from "axios"; -import { useState, useEffect } from "react"; +import { useState } from "react"; +import { useLoaderData } from "react-router-dom"; import Recipe from "./Recipe"; import "./style/RecipeList.scss"; function RecipeList() { - const [allRecipe, setAllRecipe] = useState([]); - const [filters, setFilters] = useState([]); + const allRecipe = useLoaderData()[0].recipe; + const filters = useLoaderData()[1].tags; const [filtersRecipe, setFiltersRecipe] = useState(""); + /* useEffect(() => { const endpoints = [ "http://localhost:3310/api/recipes", @@ -26,10 +27,12 @@ function RecipeList() { console.info(recipe, tag); }) .catch(() => { - window.location.href = "/"; + window.location.href = "/connexion"; }); }, []); + */ + return (
diff --git a/frontend/src/pages/style/RecipeList.scss b/frontend/src/pages/style/RecipeList.scss index 98f835a..df5b6ad 100644 --- a/frontend/src/pages/style/RecipeList.scss +++ b/frontend/src/pages/style/RecipeList.scss @@ -29,9 +29,9 @@ list-style: none; background-color: $white-color; border-radius: 1.5rem; - height: 200px; - min-width: 300px; - max-width: 400px; + min-height: 200px; + min-width: 380px; + max-width: 420px; box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.1); display: flex; @@ -53,10 +53,18 @@ } .desc-recipe { + padding: 0.25rem; margin: 0.5rem; width: 55%; display: flex; flex-direction: column; + justify-content: space-between; + + .recipe-bottom { + display: flex; + justify-content: space-between; + align-items: last baseline; + } h2 { font-size: medium; @@ -65,20 +73,20 @@ } p { font-size: small; - margin: 0.25rem 0.5rem 0.25rem 0; } .level-recipe { - margin: auto 0.25rem 0.25rem auto; + text-align: right; } .link-to { display: flex; - margin: 0.25rem 0.25rem 0.25rem auto; background-color: $orange-color; - padding-left: 0.5rem; + padding: 0.5rem; + margin: 0.25rem; border-radius: 1rem; text-align: right; + align-items: center; &:hover { background-color: #db9146; cursor: pointer;