diff --git a/b3-dev/node/eval/api.js b/b3-dev/node/eval/api.js new file mode 100644 index 0000000..4acef75 --- /dev/null +++ b/b3-dev/node/eval/api.js @@ -0,0 +1,167 @@ +/* + Ecrire une API en node, tournant sur le port 8088, + permettant de vérifier qu'un utilisateur est existant dans une + base de donnée "sécurisée" dans laquelle le mot de passe est + stocké en MD5. + Les informations de connexion seront stockées en json. + + Votre réponse sera sous forme d'un zip. + Elle contiendra au minimum : + - un fichier SQL pour la création de la base avec un utilisateur dédié + - un deuxième fichier SQL pour la création de la table et ajoutant un au moins un utilisateur à la table + - un fichier README indiquant comment installer votre projet et les routes disponibles + - un fichier package.json + - un fichier api.js contenant votre code Node +*/ + + // testing : + // https://mariadb.com/kb/en/nodejs-connector/ + + import http from 'http'; // to create server + import url from 'url'; // to parse url + import fs from 'fs'; // to load config + + // https://www.npmjs.com/package/email-validator + // pour vérifier que le mail est un mail valid : + import validator from 'email-validator'; + + // pour valider le mot de passe + import md5 from 'md5'; + + // on ajoute la possibilité de require du json en objet + import { createRequire } from 'module'; + const require = createRequire(import.meta.url); + + const BASIC_API_PORT = 8088; + + var config=null; + if(fs.existsSync(process.cwd() + '/config.json')){ + config = require(process.cwd() + '/config.json'); + } + else { + console.log('no config'); + exit(0); + } + + const mariadb = require('mariadb'); + const { exit } = require('process'); + const pool = mariadb.createPool({ + host: config.DB_HOST, + port: config.DB_PORT, + user: config.DB_USR, + password:config.DB_PWD, + database: config.DB_NAME, + connectionLimit: 5, + }); + + //const server = http.createServer(function (req, resp) { + const app = http.createServer + ( + async (req, res) => + { + const parsedURL = url.parse(req.url, true); + let response_json = JSON.stringify({"up":false}); + if(req.method === 'GET' && parsedURL.pathname.startsWith('/up')) + { + var cnx = null; + try + { + cnx=await pool.getConnection(); + const tables_res = await cnx.query("SHOW TABLES"); + if(tables_res.length > 0) + { + response_json = JSON.stringify({'up':true}); + } + } + catch(err) + { + console.log(err); + res.statusCode = 400; + res.end(response_json); + if(cnx) + { + return cnx.end(); + } + throw(err); + } + finally + { + res.statusCode = 200; + res.end(response_json); + if(cnx) + { + return cnx.end(); + } + } + } + else if(req.method === 'POST' && parsedURL.pathname.startsWith('/check')) + { + console.log("checking :"); + let responseString = ""; + req.on('data', function (varposted) { + responseString += varposted; + }).on('end', async function () { + if(responseString.indexOf('?')<0) { + responseString = '?'+responseString; + } + let parsedData = url.parse(responseString, true); + console.log("ParsedData", parsedData); + let response_content = {'up':false,'emailtocheck':''}; + if(parsedData.query['email'] && parsedData.query['password']) { + response_content.emailtocheck = parsedData.query['email']; + response_content.hashedpassword = md5(parsedData.query['password']); + if(validator.validate(response_content.emailtocheck)) + { + cnx=await pool.getConnection(); + //let query="SELECT * FROM users WHERE courriel = '" + response_content.emailtocheck +"'"; + let query="SELECT * FROM users WHERE courriel = ? AND mot_de_passe = ?"; + console.log('query : ',query,' with ? = ', response_content.emailtocheck); + const email_res = await cnx.query(query, [response_content.emailtocheck, response_content.hashedpassword]); + if(email_res.length > 0) + { + response_content.up=true; + response_content.emailValid=true; + } + else + { + response_content.up=true; + response_content.emailValid=false; + response_content.error='Not Found'; + response_content.error_code=404; + } + res.statusCode = 200; + res.end(JSON.stringify(response_content)); + if(cnx) + { + return cnx.end(); + } + } + else { + response_content.up=true; + response_content.emailValid=false; + response_content.error='I\'m a teapot'; + response_content.error_code=418; + res.statusCode = 200; + res.end(JSON.stringify(response_content)); + } + } + else { + response_content.up=true; + response_content.emailValid=false; + response_content.emailtocheck=parsedData.query['email']; + response_content.error='Invalid query mail or password do match requirements'; + response_content.error_code=400; + res.statusCode = 200; + res.end(JSON.stringify(response_content)); + } + }); + } + else + { + res.statusCode = 400; + res.end("API Endpoint Not Supported"); + } + } + ); + app.listen(BASIC_API_PORT); + console.log('mariadb test api started'); diff --git a/b3-dev/node/eval/config.json b/b3-dev/node/eval/config.json new file mode 100644 index 0000000..92b8a40 --- /dev/null +++ b/b3-dev/node/eval/config.json @@ -0,0 +1,7 @@ +{ + "DB_HOST" : "127.0.0.1", + "DB_PORT" : "3306", + "DB_USR" : "eval_user", + "DB_PWD" : "ov62p67t7PId9N3", + "DB_NAME" : "eval_bdd" +} \ No newline at end of file diff --git a/b3-dev/node/eval/create-et-grant.sql b/b3-dev/node/eval/create-et-grant.sql new file mode 100644 index 0000000..7961c79 --- /dev/null +++ b/b3-dev/node/eval/create-et-grant.sql @@ -0,0 +1,12 @@ +CREATE DATABASE IF NOT EXISTS `eval_bdd` + DEFAULT CHARACTER SET utf8 + DEFAULT COLLATE utf8_general_ci; + +GRANT USAGE ON *.* TO "eval_user"@"localhost" IDENTIFIED BY "ov62p67t7PId9N3" + WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; + +GRANT USAGE ON *.* TO "eval_user"@"%" IDENTIFIED BY "ov62p67t7PId9N3" + WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; + +GRANT ALL PRIVILEGES ON `eval_bdd`.* TO 'eval_user'@'%'; +GRANT ALL PRIVILEGES ON `eval_bdd`.* TO 'eval_user'@'localhost'; \ No newline at end of file diff --git a/b3-dev/node/eval/eval.api/api.js b/b3-dev/node/eval/eval.api/api.js new file mode 100644 index 0000000..39253b8 --- /dev/null +++ b/b3-dev/node/eval/eval.api/api.js @@ -0,0 +1,129 @@ +/* + Ecrire une API en node, tournant sur le port 8088, + permettant de vérifier qu'un utilisateur est existant dans une + base de donnée "sécurisée" dans laquelle le mot de passe est + stocké en MD5. + Les informations de connexion seront stockées en json. + + Votre réponse sera sous forme d'un zip. + Elle contiendra au minimum : + - un fichier SQL pour la création de la base avec un utilisateur dédié + - un deuxième fichier SQL pour la création de la table et ajoutant un au moins un utilisateur à la table + - un fichier README indiquant comment installer votre projet et les routes disponibles + - un fichier package.json + - un fichier api.js contenant votre code Node +*/ + + // testing : + // https://mariadb.com/kb/en/nodejs-connector/ + + + const http = require ('http'); // to create server + const url = require('url'); // to parse url + const fs = require('fs'); // to load config + const BASIC_API_PORT = 8088; + + var config=null; + if(fs.existsSync(process.cwd() + '/config.json')){ + config = require(process.cwd() + '/config.json'); + } + else { + console.log('no config'); + } + + + const mariadb = require('mariadb'); + const { exit } = require('process'); + const pool = mariadb.createPool({ + host: config.DB_HOST, + port: config.DB_PORT, + user: config.DB_USR, + password:config.DB_PWD, + database: config.DB_NAME, + connectionLimit: 5, + }); + + //const server = http.createServer(function (req, resp) { + const app = http.createServer + ( + async (req, res) => + { + const parsedURL = url.parse(req.url, true); + var response_json = JSON.stringify({"up":false}); + if(req.method === 'GET' && parsedURL.pathname.startsWith('/up')) + { + var cnx = null; + try + { + cnx=await pool.getConnection(); + const tables_res = await cnx.query("SHOW TABLES"); + if(tables_res.length > 0) + { + response_json = JSON.stringify({'up':true}); + } + } + catch(err) + { + console.log(err); + res.statusCode = 400; + res.end(response_json); + if(cnx) + { + return cnx.end(); + } + throw(err); + } + finally + { + res.statusCode = 200; + res.end(response_json); + if(cnx) + { + return cnx.end(); + } + } + } + else if(req.method === 'POST' && parsedURL.pathname.startsWith('/check')) + { + console.log("checking :"); + responseString = "?"; + req.on('data', function (varposted) { + responseString += varposted; + }).on('end', async function () { + parsedData = url.parse(responseString, true); + console.log("ParsedData", parsedData); + let response_content = {'up':false,'emailtocheck':''}; + if(parsedData.query['email']) { + response_content.emailtocheck = parsedData.query['email']; + cnx=await pool.getConnection(); + let query="SELECT * FROM users WHERE courriel = '"+ response_content.emailtocheck +"'"; + console.log(query); + const email_res = await cnx.query(query); + if(email_res.length > 0) + { + response_content.up=true; + response_content.emailValid=true; + } + else + { + response_content.up=true; + response_content.emailValid=false; + } + res.statusCode = 200; + res.end(JSON.stringify(response_content)); + if(cnx) + { + return cnx.end(); + } + } + }); + } + else + { + res.statusCode = 400; + res.end("API Endpoint Not Supported"); + } + } + ); + app.listen(BASIC_API_PORT); + console.log('mariadb test api started'); diff --git a/b3-dev/node/eval/eval.api/config.json b/b3-dev/node/eval/eval.api/config.json new file mode 100644 index 0000000..92b8a40 --- /dev/null +++ b/b3-dev/node/eval/eval.api/config.json @@ -0,0 +1,7 @@ +{ + "DB_HOST" : "127.0.0.1", + "DB_PORT" : "3306", + "DB_USR" : "eval_user", + "DB_PWD" : "ov62p67t7PId9N3", + "DB_NAME" : "eval_bdd" +} \ No newline at end of file diff --git a/b3-dev/node/eval/eval.api/package.json b/b3-dev/node/eval/eval.api/package.json new file mode 100644 index 0000000..8ec3701 --- /dev/null +++ b/b3-dev/node/eval/eval.api/package.json @@ -0,0 +1,16 @@ +{ + "name": "eval", + "version": "1.0.0", + "description": "", + "main": "front.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "mariadb": "^3.0.0", + "md5": "^2.3.0", + "node-fetch": "^3.2.6" + } +} diff --git a/b3-dev/node/eval/front.js b/b3-dev/node/eval/front.js new file mode 100644 index 0000000..210e7d4 --- /dev/null +++ b/b3-dev/node/eval/front.js @@ -0,0 +1,74 @@ +/* + Faire un site en node, tourant sur le port 80. + Le site permet de saisir un email et un mot de passe dans un formulaire. + En retour de soumission du formulaire le site affichera l'email, la chaine MD5 du mot de passe, et l'heure+date de la tentative connexion. +*/ + +/* +Votre réponse sera sous forme d'un zip. +Elle contiendra au minimum : +- un fichier README indiquant comment installer votre projet et les routes disponibles +- un fichier package.json +- un fichier front.js contenant votre code Node +*/ +import http from 'http'; +import * as url from 'url'; + +// npm i md5 +// https://www.npmjs.com/package/md5 +import md5 from 'md5'; + +function outputHTML5(status, response, content, title) +{ + response.writeHead(status, { 'Content-Type': 'text/html; charset=utf-8' }); + response.write( + ` + + +
+ +