diff --git a/cryptide_project/package-lock.json b/cryptide_project/package-lock.json index 4a92a79..91fb5d5 100644 --- a/cryptide_project/package-lock.json +++ b/cryptide_project/package-lock.json @@ -21,6 +21,7 @@ "bootstrap": "^5.3.2", "cors": "^2.8.5", "express": "^4.18.2", + "express-session": "^1.17.3", "lodash": "^4.17.21", "mysql": "^2.18.1", "react": "^18.2.0", @@ -8272,6 +8273,45 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -14798,6 +14838,14 @@ "performance-now": "^2.1.0" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -17133,6 +17181,17 @@ "node": ">=14.17" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/cryptide_project/package.json b/cryptide_project/package.json index e2229b8..97ecc48 100644 --- a/cryptide_project/package.json +++ b/cryptide_project/package.json @@ -15,6 +15,7 @@ "bootstrap": "^5.3.2", "cors": "^2.8.5", "express": "^4.18.2", + "express-session": "^1.17.3", "lodash": "^4.17.21", "mysql": "^2.18.1", "react": "^18.2.0", diff --git a/cryptide_project/src/Pages/LoginForm.tsx b/cryptide_project/src/Pages/LoginForm.tsx index 7d06305..a8b3581 100644 --- a/cryptide_project/src/Pages/LoginForm.tsx +++ b/cryptide_project/src/Pages/LoginForm.tsx @@ -1,18 +1,38 @@ import React, { Component } from 'react'; import { AiOutlineSend } from 'react-icons/ai'; +import AuthService from '../services/AuthService'; import '../Style/Global.css'; export default class Login extends Component { + handleSubmit = async (event: any) => { + event.preventDefault(); + try{ + const data = { + pseudo: event.target.pseudo.value, + password: event.target.password.value, + remember: event.target.remember.value + }; + + const result = await AuthService.signIn(data); + console.log(result); + alert('Connexion réussie !'); + } + catch(error){ + console.error(error); + } + }; + render() { return (
-
+

Log In

@@ -21,6 +41,7 @@ export default class Login extends Component { @@ -29,6 +50,7 @@ export default class Login extends Component {
diff --git a/cryptide_project/src/Pages/SignUpForm.tsx b/cryptide_project/src/Pages/SignUpForm.tsx index 575f37a..2ec2e77 100644 --- a/cryptide_project/src/Pages/SignUpForm.tsx +++ b/cryptide_project/src/Pages/SignUpForm.tsx @@ -1,80 +1,111 @@ -import React, { Component } from 'react'; +import React, { useState, useEffect } from 'react'; import { AiOutlineSend } from 'react-icons/ai'; +import { useNavigate } from 'react-router-dom'; // Use useNavigate instead of useHistory import AuthService from '../services/AuthService'; import '../Style/Global.css'; -export default class SignUp extends Component { - handleSubmit = async (event: any) => { +const SignUp = () => { + const navigate = useNavigate(); // Use useNavigate instead of useHistory + + const [error, setError] = useState(null); + const [showConfirmation, setShowConfirmation] = useState(false); + + const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); - try{ + + try { const data = { - pseudo: event.target.pseudo.value, - password: event.target.password.value, - Cpassword: event.target.Cpassword.value + pseudo: (event.target as any).pseudo.value, + password: (event.target as any).password.value, + Cpassword: (event.target as any).Cpassword.value, }; - const isValid = await AuthService.validateSignUp(data); + const validation = await AuthService.validateSignUp(data); + + if (!validation.valid) { + setError(validation.error); + } else { + setError(null); - if(isValid){ const result = await AuthService.signUp(data); - console.log(result); - alert('Inscription réussie !'); + // console.log(result); + + setShowConfirmation(true); + setTimeout(() => { + navigate('/login'); // 3 secondes avant de rediriger vers la page de connexion + }, 3000); } - } - catch(error){ - console.error(error); + } catch (error: any) { + setError(error.message); } }; - render() { - return ( -
- -
-

Sign Up

-
- - -
-
- - -
-
- - -
-
- -
-

- Vous avez déjà un compte ? -

- -
- ); - } -} + useEffect(() => { + return () => { + setShowConfirmation(false); + }; + }, []); + + return ( +
+
+
+

Sign Up

+
+ + +
+
+ + +
+
+ + +
+
+ +
+

+ Vous avez déjà un compte ? +

+
+ + {error && ( +
+ {error} +
+ )} + + {showConfirmation && ( +
+ Inscription réussie ! Vous serez redirigé vers la page de connexion dans 3 secondes. +
+ )} +
+ ); +}; + +export default SignUp; diff --git a/cryptide_project/src/server/controllers/AuthController.js b/cryptide_project/src/server/controllers/AuthController.js index 3d1ea59..95cf99f 100644 --- a/cryptide_project/src/server/controllers/AuthController.js +++ b/cryptide_project/src/server/controllers/AuthController.js @@ -1,5 +1,6 @@ const UserService = require('../services/UserService'); const DatabaseService = require('../services/DatabaseService'); +const bcrypt = require('bcrypt'); class AuthController { static async signUp(req, res) { @@ -8,8 +9,6 @@ class AuthController { try { await databaseService.connect(); - // Validation côté serveur (vous pouvez utiliser express-validator ici) - // Vérifier que le pseudo n'est pas déjà utilisé const pseudo = req.body.pseudo; const verifUser = await databaseService.getUserByPseudo(pseudo); if (verifUser) { @@ -33,6 +32,46 @@ class AuthController { await databaseService.disconnect(); } } + + static async signIn(req, res) { + const databaseService = new DatabaseService(); + + try{ + await databaseService.connect(); + + // Vérifier que le pseudo existe + const pseudo = req.body.pseudo; + const user = await databaseService.getUserByPseudo(pseudo); + if (!user) { + res.status(400).json({ error: 'Le pseudo n\'existe pas.' }); + return; + } + + // Vérifier que le mot de passe est correct + const password = req.body.password; + const validPassword = await bcrypt.compare(password, user.password); + if (!validPassword) { + res.status(400).json({ error: 'Le mot de passe est incorrect.' }); + return; + } + + // Stocker l'utilisateur dans la session + if(!req.session.user && req.body.remember){ + req.session.user = user; + } + + // Envoyer une réponse réussie + res.status(200).json({ message: 'Connexion réussie', user: user }); + } + catch(error){ + // Gérer les erreurs + console.error(error); + res.status(500).json({ error: 'Erreur lors de la connexion.' }); + } + finally{ + await databaseService.disconnect(); + } + } } module.exports = AuthController; \ No newline at end of file diff --git a/cryptide_project/src/server/routes/AuthRoutes.js b/cryptide_project/src/server/routes/AuthRoutes.js index a249c1d..694910d 100644 --- a/cryptide_project/src/server/routes/AuthRoutes.js +++ b/cryptide_project/src/server/routes/AuthRoutes.js @@ -3,5 +3,6 @@ const router = express.Router(); const AuthController = require('../controllers/AuthController'); router.post('/signup', AuthController.signUp); +router.post('/signin', AuthController.signIn); module.exports = router; diff --git a/cryptide_project/src/server/server.js b/cryptide_project/src/server/server.js index efbdd00..0c1705b 100644 --- a/cryptide_project/src/server/server.js +++ b/cryptide_project/src/server/server.js @@ -1,17 +1,28 @@ const express = require('express'); +const session = require('express-session'); const cors = require('cors'); const bodyParser = require('body-parser'); +const crypto = require('crypto'); const authRoutes = require('./routes/authRoutes'); const DatabaseService = require('./services/DatabaseService'); const app = express(); const port = 3000; -// Middleware CORS -app.use(cors()); +// Middleware +app.use(cors()); // Autoriser les requêtes cross-origin +app.use(bodyParser.json()); // Parser le body des requêtes en JSON -// Middleware pour traiter le corps des requêtes en JSON -app.use(bodyParser.json()); +// Session +const secret = crypto.randomBytes(32).toString('hex'); +app.use(session({ + secret: secret, + resave: false, + saveUninitialized: true, + cookie: { secure: process.env.NODE_ENV === 'production' ? true : false, + maxAge: 60 * 60 * 1000 + } +})); // Middleware pour les routes d'authentification app.use('/auth', authRoutes); diff --git a/cryptide_project/src/services/AuthService.tsx b/cryptide_project/src/services/AuthService.tsx index f05d2d5..0cd3436 100644 --- a/cryptide_project/src/services/AuthService.tsx +++ b/cryptide_project/src/services/AuthService.tsx @@ -1,14 +1,38 @@ +import e from 'express'; import VerificationService from './VerificationService'; class AuthService{ // Méthode pour vérifier les données de connexion - static async validateSignUp(data: any): Promise{ + static async validateSignUp(data: any): Promise<{valid: boolean, error: string}> { return VerificationService.validateSignUpData(data); } static async signUp(data: any) { try { - const response = await fetch('http://localhost:3000/auth/signup', { + const response = await fetch('http://localhost:3000/auth/signup', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (response.ok) { + const result = await response.json(); + return result; + } else { + const errorResponse = await response.json(); + throw new Error(errorResponse.error); + } + } catch (error) { + console.error(error); + throw error; + } + } + + static async signIn(data: any) { + try { + const response = await fetch('http://localhost:3000/auth/signin', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -20,13 +44,13 @@ class AuthService{ const result = await response.json(); return result; } else { - throw new Error('Échec de l\'inscription.'); + throw new Error('Échec de la connexion.'); } } catch (error) { console.error(error); throw error; } - } + } } export default AuthService; \ No newline at end of file diff --git a/cryptide_project/src/services/VerificationService.tsx b/cryptide_project/src/services/VerificationService.tsx index 5f3a61a..7b5393a 100644 --- a/cryptide_project/src/services/VerificationService.tsx +++ b/cryptide_project/src/services/VerificationService.tsx @@ -1,16 +1,18 @@ class ValidationService { - public static validateSignUpData(data: any): boolean { + public static validateSignUpData(data: any): {valid: boolean, error: string} { if(!data.pseudo || !data.password || !data.Cpassword) { - console.error('Veuillez remplir tous les champs.'); - return false; + return {valid: false, error: 'Veuillez remplir tous les champs.'}; } - // if(data.password !== data.Cpassword) { - // console.error('Les mots de passe ne correspondent pas.'); - // return false; - // } + if(data.password.length < 8) { + return {valid: false, error: 'Le mot de passe doit contenir au moins 8 caractères.'}; + } + + if(data.password !== data.Cpassword) { + return {valid: false, error: 'Les mots de passe ne correspondent pas.'}; + } - return true; + return {valid: true, error: ''}; } } diff --git a/cryptide_project/yarn.lock b/cryptide_project/yarn.lock index be31eda..9b98102 100644 --- a/cryptide_project/yarn.lock +++ b/cryptide_project/yarn.lock @@ -3704,6 +3704,11 @@ cookie-signature@1.0.6: resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + cookie@0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" @@ -4109,7 +4114,7 @@ depd@~1.1.2: resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -depd@2.0.0: +depd@~2.0.0, depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -4871,6 +4876,20 @@ expect@^29.0.0: jest-message-util "^29.7.0" jest-util "^29.7.0" +express-session@^1.17.3: + version "1.17.3" + resolved "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz" + integrity sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw== + dependencies: + cookie "0.4.2" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~2.0.0" + on-headers "~1.0.2" + parseurl "~1.3.3" + safe-buffer "5.2.1" + uid-safe "~2.1.5" + express@^4.17.3, express@^4.18.2: version "4.18.2" resolved "https://registry.npmjs.org/express/-/express-4.18.2.tgz" @@ -8236,6 +8255,11 @@ raf@^3.4.1: dependencies: performance-now "^2.1.0" +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" + integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" @@ -9722,6 +9746,13 @@ typedarray-to-buffer@^3.1.5: resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== +uid-safe@~2.1.5: + version "2.1.5" + resolved "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz" + integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== + dependencies: + random-bytes "~1.0.0" + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz"