From d5e83556eab5f6aef54f5a425cd9164dc7661b64 Mon Sep 17 00:00:00 2001 From: AlexiaGu <150676364+AlexiaGu@users.noreply.github.com> Date: Mon, 1 Apr 2024 09:46:50 +0200 Subject: [PATCH] =?UTF-8?q?hashage=20du=20password,=20register=20et=20d?= =?UTF-8?q?=C3=A9but=20login?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package-lock.json | 35 ++++++++++++ backend/package.json | 1 + backend/src/app.js | 4 +- backend/src/controllers/readerControllers.js | 2 +- backend/src/models/ReaderManager.js | 2 + backend/src/router.js | 3 +- backend/src/services/auth.js | 24 ++++++++ frontend/src/App.jsx | 20 +++---- frontend/src/components/Books.jsx | 31 ++++++++++ frontend/src/components/Counter.jsx | 16 ------ frontend/src/components/Navbar.jsx | 21 +++++++ frontend/src/main.jsx | 59 ++++++++++++++------ frontend/src/pages/Books.jsx | 21 +++++++ frontend/src/pages/CreateBook.jsx | 44 +++++++++++++++ frontend/src/pages/Forbidden.jsx | 3 + frontend/src/pages/Home.jsx | 3 + frontend/src/pages/Login.jsx | 3 + frontend/src/pages/Register.jsx | 48 ++++++++++++++++ frontend/src/services/UserContext.jsx | 28 ++++++++++ frontend/src/styles/navbar.css | 10 ++++ package-lock.json | 35 ++++++++++++ 21 files changed, 362 insertions(+), 51 deletions(-) create mode 100644 backend/src/services/auth.js create mode 100644 frontend/src/components/Books.jsx delete mode 100644 frontend/src/components/Counter.jsx create mode 100644 frontend/src/components/Navbar.jsx create mode 100644 frontend/src/pages/Books.jsx create mode 100644 frontend/src/pages/CreateBook.jsx create mode 100644 frontend/src/pages/Forbidden.jsx create mode 100644 frontend/src/pages/Login.jsx create mode 100644 frontend/src/pages/Register.jsx create mode 100644 frontend/src/services/UserContext.jsx create mode 100644 frontend/src/styles/navbar.css diff --git a/backend/package-lock.json b/backend/package-lock.json index 03728ce1..91fdbf33 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -6,6 +6,7 @@ "": { "dependencies": { "argon2": "^0.40.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "joi": "^17.12.2", @@ -2258,6 +2259,18 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -5460,6 +5473,14 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -8916,6 +8937,15 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -11273,6 +11303,11 @@ "path-key": "^3.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/backend/package.json b/backend/package.json index 89b76d0c..4a354f63 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "argon2": "^0.40.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "joi": "^17.12.2", diff --git a/backend/src/app.js b/backend/src/app.js index f55fb187..acbdd02e 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -25,7 +25,6 @@ const app = express(); // 4. Be sure to only have URLs in the array with domains from which you want to allow requests. // For example: ["http://mysite.com", "http://another-domain.com"] -/* const cors = require("cors"); app.use( @@ -34,10 +33,9 @@ app.use( process.env.FRONTEND_URL, // keep this one, after checking the value in `backend/.env` "http://mysite.com", "http://another-domain.com", - ] + ], }) ); -*/ /* ************************************************************************* */ diff --git a/backend/src/controllers/readerControllers.js b/backend/src/controllers/readerControllers.js index 066e60fb..c87ffcea 100644 --- a/backend/src/controllers/readerControllers.js +++ b/backend/src/controllers/readerControllers.js @@ -24,7 +24,7 @@ const add = async (req, res, next) => { const readerInfos = { // ce que l'on retourne du manager email: req.body.email, - password: req.body.password, + password: req.body.hashedPassword, username: req.body.username, }; try { diff --git a/backend/src/models/ReaderManager.js b/backend/src/models/ReaderManager.js index 16355ef8..ecd55406 100644 --- a/backend/src/models/ReaderManager.js +++ b/backend/src/models/ReaderManager.js @@ -16,6 +16,8 @@ class ReaderManager extends AbstractManager { return rows; } + // /!\ select * from user est interdit car l'on ne souahite pas voir le mdp même en hashé apparaître + async readAll() { const [rows] = await this.database.query(`select * from ${this.table}`); return rows; diff --git a/backend/src/router.js b/backend/src/router.js index 65fd0cdb..4672bdb9 100644 --- a/backend/src/router.js +++ b/backend/src/router.js @@ -13,6 +13,7 @@ const readerControllers = require("./controllers/readerControllers"); // Import pagesMiddleware const bookMiddlewares = require("./middlewares/bookMiddlewares"); +const authMiddlewares = require("./services/auth"); // Items routes @@ -52,7 +53,7 @@ router.delete("/books/:id", bookControllers.destroy); router.get("/readers", readerControllers.browse); // Route to add a new reader -router.post("/readers", readerControllers.add); +router.post("/readers", authMiddlewares.hashPassword, readerControllers.add); router.get("/readers/:id", readerControllers.read); module.exports = router; diff --git a/backend/src/services/auth.js b/backend/src/services/auth.js new file mode 100644 index 00000000..0ac24343 --- /dev/null +++ b/backend/src/services/auth.js @@ -0,0 +1,24 @@ +const argon2 = require("argon2"); + +const hashingOptions = { + type: argon2.argon2id, + memoryCost: 19 * 2 ** 10, + timeCost: 2, + parallelism: 1, +}; + +const hashPassword = async (req, res, next) => { + try { + const { password } = req.body; + const hashedPassword = await argon2.hash(password, hashingOptions); + req.body.hashedPassword = hashedPassword; + // pour supprimer le password en clair une fois celui-ci hashé + delete req.body.password; + console.info("HASHED PASSWORD", req.body); + next(); + } catch (error) { + next(error); + } +}; + +module.exports = { hashPassword }; diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 92c8818e..38c8c8a5 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,21 +1,15 @@ import { Outlet } from "react-router-dom"; -// import Footer from "./components/Footer"; -import "./App.css"; - -// import Navbar from "./components/Navbar"; +import Navbar from "./components/Navbar"; function App() { return ( -
- {/* */} -
-
- -
- {/*
-
+ <> + +
+ +
+ ); } diff --git a/frontend/src/components/Books.jsx b/frontend/src/components/Books.jsx new file mode 100644 index 00000000..50965eaa --- /dev/null +++ b/frontend/src/components/Books.jsx @@ -0,0 +1,31 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import axios from "axios"; +import PropTypes from "prop-types"; + +export default function Book({ book, refreshPage }) { + const deleteBook = () => { + axios + .delete(`${import.meta.env.VITE_BACKEND_URL}/api/books/${book.id}`) + .then(() => refreshPage()) + .catch((error) => console.error(error)); + }; + + return ( +
+

{book.title}

+

{book.summary}

+ +
+ ); +} + +Book.propTypes = { + book: PropTypes.shape({ + id: PropTypes.number.isRequired, + title: PropTypes.string.isRequired, + summary: PropTypes.string.isRequired, + }).isRequired, + refreshPage: PropTypes.func.isRequired, +}; diff --git a/frontend/src/components/Counter.jsx b/frontend/src/components/Counter.jsx deleted file mode 100644 index d4ef7cbb..00000000 --- a/frontend/src/components/Counter.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useState } from "react"; - -export default function Counter() { - const [count, setCount] = useState(0); - - return ( -

- -

- ); -} diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx new file mode 100644 index 00000000..2a764b7f --- /dev/null +++ b/frontend/src/components/Navbar.jsx @@ -0,0 +1,21 @@ +// import { useContext } from "react"; +import { Link } from "react-router-dom"; +// import UserContext from "../services/UserContext"; + +export default function Navbar() { + // const { user } = useContext(UserContext); + + // const isConnected = user.id && user.id !== "null"; + + // console.info("isConnected", isConnected); + + return ( + + ); +} diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 50bd64db..b501c34c 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,22 +1,23 @@ +/* eslint-disable import/no-extraneous-dependencies */ import React from "react"; import ReactDOM from "react-dom/client"; - import { createBrowserRouter, RouterProvider } from "react-router-dom"; -// import { UserProvider } from "./services/UserContext"; +import axios from "axios"; import App from "./App"; + import Home from "./pages/Home"; -// import Store from "./pages/Store"; -// import GameDetails from "./pages/GameDetails"; -// import MyGames from "./pages/MyGames"; -// import AddGame from "./pages/AddGame"; -// import Trades from "./pages/Trades"; -// import Register from "./pages/Register"; -// import Login from "./pages/Login"; -// import Match from "./components/ViewAvaibility/Match"; -// import SearchResult from "./components/SearchResult"; -// import Settings from "./pages/Settings"; -// import Forbidden from "./pages/Forbidden"; +import Books from "./pages/Books"; +import CreateBook from "./pages/CreateBook"; +import Register from "./pages/Register"; +import Login from "./pages/Login"; +import Forbidden from "./pages/Forbidden"; + +import { UserProvider } from "./services/UserContext"; + +// import "./styles/app.css"; +import "./styles/navbar.css"; +// import "./styles/articles.css"; const router = createBrowserRouter([ { @@ -26,14 +27,38 @@ const router = createBrowserRouter([ path: "/", element: , }, + { + path: "/books", + element: , + errorElement: , + loader: () => + axios + .get(`${import.meta.env.VITE_BACKEND_URL}/api/books`, { + withCredentials: true, + }) + .then((response) => response.data) + .catch((error) => console.error("ERROR", error)), + }, + { + path: "/create", + element: , + }, + { + path: "/register", + element: , + }, + { + path: "/login", + element: , + }, ], }, ]); -const root = ReactDOM.createRoot(document.getElementById("root")); - -root.render( +ReactDOM.createRoot(document.getElementById("root")).render( - + + + ); diff --git a/frontend/src/pages/Books.jsx b/frontend/src/pages/Books.jsx new file mode 100644 index 00000000..a747d418 --- /dev/null +++ b/frontend/src/pages/Books.jsx @@ -0,0 +1,21 @@ +import { useLoaderData, useNavigate } from "react-router-dom"; +import Book from "../components/Books"; + +export default function Books() { + const books = useLoaderData(); + + const navigate = useNavigate(); + + const refreshPage = () => { + navigate("/books", { replace: true }); + }; + + return ( + <> +

Liste des livres lus :

+ {books.map((book) => ( + + ))} + + ); +} diff --git a/frontend/src/pages/CreateBook.jsx b/frontend/src/pages/CreateBook.jsx new file mode 100644 index 00000000..284c6cda --- /dev/null +++ b/frontend/src/pages/CreateBook.jsx @@ -0,0 +1,44 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { useState } from "react"; +import axios from "axios"; + +export default function CreateBook() { + const [form, setForm] = useState({ + title: "", + summary: "", + userId: 1, + }); + + const handleChangeForm = (event) => { + setForm({ + ...form, + [event.target.name]: event.target.value, + }); + }; + + const submitBook = (event) => { + event.preventDefault(); + axios + .post(`${import.meta.env.VITE_BACKEND_URL}/api/books/`, form) + .then((response) => console.info(response)) + .catch((err) => console.error(err)); + }; + + return ( + <> +

Créer une fiche de livre

+
+ + + +