Correction evalblanche et exemples complémentaires

master
Juan 3 years ago
parent b9f574b3e6
commit c52298dda8

@ -0,0 +1,83 @@
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mysql = require('mysql');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// connection configurations
var dbConn = mysql.createConnection({
host: 'localhost',
port: 3306,
user: 'nodeapiuser',
password: 'RDSGF435FG',
database: 'nodeapi'
});
// connect to database
dbConn.connect();
// Retrieve all users
app.get('/users', function (req, res) {
dbConn.query('SELECT * FROM users', function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results });
});
});
// Retrieve user with id
app.get('/user/:id', function (req, res) {
let user_id = req.params.id;
if (!user_id) {
return res.status(400).send({ error: true, message: 'Please provide user_id' });
}
dbConn.query('SELECT * FROM users where id=?', user_id, function (error, results) {
if (error) throw error;
return res.send({ error: false, data: results[0] });
});
});
// Add a new user
app.post('/user', function (req, res) {
let nom = req.body.nom;
let prenom = req.body.prenom;
let email = req.body.email;
console.log(nom, prenom, email);
dbConn.query("INSERT INTO users (nom, prenom, email) VALUES (?,?,?);", [nom, prenom, email], function (error, results) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'New user has been created successfully.' });
});
});
// Delete user
app.delete('/user/:id', function (req, res) {
let user_id = req.params.id;
if (!user_id) {
return res.status(400).send({ error: true, message: 'Please provide user_id' });
}
dbConn.query('DELETE FROM users WHERE id = ?', [user_id], function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'User has been deleted successfully.' });
});
});
// set port
app.listen(8080, function () {
console.log('Node app is running on port 8080');
});
module.exports = app;

@ -0,0 +1,12 @@
CREATE DATABASE IF NOT EXISTS `nodeapi`
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
GRANT USAGE ON *.* TO "nodeapiuser"@"localhost" IDENTIFIED BY "RDSGF435FG"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT USAGE ON *.* TO "nodeapiuser"@"%" IDENTIFIED BY "RDSGF435FG"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT ALL PRIVILEGES ON `nodeapi`.* TO 'nodeapiuser'@'%';
GRANT ALL PRIVILEGES ON `nodeapi`.* TO 'nodeapiuser'@'localhost';

@ -0,0 +1,14 @@
CREATE TABLE nodeapi.users
(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
nom VARCHAR(100),
prenom VARCHAR(100),
email VARCHAR(255)
);
INSERT INTO `users` (`id`, `nom`, `prenom`, `email`) VALUES
(1, 'Brault', 'Benjamin', 'braultr.benjamin@outlook.fr'),
(2, 'Dupont', 'Jean', 'dupont.jean@gmail.com'),
(3, 'Delaporte', 'Camille', 'delaporte.camille@gmail.com'),
(4, 'Dupre', 'Pascal', 'dupre.pascal@gmail.com'),
(5, 'Bourgeon', 'Lucie', 'bourgeon.lucie@gmail.com');

@ -0,0 +1,18 @@
{
"name": "eval",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.0",
"express": "^4.18.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.16",
"saxon-js": "^2.4.0"
}
}

@ -0,0 +1,42 @@
Création de la base de donnée et de l'utilisateur dédié :
database.sql
Création de la table et de son contenu :
database2.sql
Installer les packages :
npm install
Lancer le serveur NodeJS :
nodemon api.js
--------------------------------------
Différents routes :
Afficher la liste des utilisateurs :
http://localhost:8080/users - GET
--------------------------------------
Afficher un utilisateur :
http://localhost:8080/user/2 - GET
--------------------------------------
Supprimer un utilisateur :
http://localhost:8080/user/5 - DELETE
--------------------------------------
Insérer un utilisateur :
http://localhost:8080/user - POST
body :
{
"nom": "Allande",
"prenom": "Alain",
"email": "allande.alain@gmail.com"
}
--------------------------------------

@ -0,0 +1,35 @@
<h1 align="center">Bonjour 👋, Je suis'm Mickaël</h1>
<h3 align="center">API NodeJS, avec SEQUELIZE + MYSQL + EXPRESS</h3>
- DEVOIR NODEJS **Vous trouverez ci-joint toute les informations pour mettre en place l'API**
- 3 - Lancer le serveur Node **Toujours à la racine, utiliser le package nodemon en ligne de commande "nodemon start"**
- 1 - Créer la BDD [Créer votre BDD à partir du fichier.](/app/bdd/bdd.sql)
- 2 - Installer les package [Importer les package npm, grâce à la commande "npm i"](Racine)
- Requête GET **http://localhost:8080/api/voiture/GETOne/:id**
- Requête PUT **http://localhost:8080/api/voiture/PUT/:id**
{
"nom": "Twingo",
"nbrPlace": "5"
}
- Requête POST **http://localhost:8080/api/voiture/POST**
{
"nom": "Twingo",
"nbrPlace": "4"
}
- Requête DROP **http://localhost:8080/api/voiture/DROP/:id**
- 📝 Voici mon adresse mail en cas de problème **Mickaelpoupion@gmail.com**
<h3 align="left">Connect with me:</h3>
<p align="left">
</p>
<h3 align="left">Languages and Tools:</h3>
<p align="left"> <a href="https://expressjs.com" target="_blank" rel="noreferrer"> <img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/express/express-original-wordmark.svg" alt="express" width="40" height="40"/> </a> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noreferrer"> <img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/javascript/javascript-original.svg" alt="javascript" width="40" height="40"/> </a> <a href="https://www.mysql.com/" target="_blank" rel="noreferrer"> <img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/mysql/mysql-original-wordmark.svg" alt="mysql" width="40" height="40"/> </a> <a href="https://nodejs.org" target="_blank" rel="noreferrer"> <img src="https://raw.githubusercontent.com/devicons/devicon/master/icons/nodejs/nodejs-original-wordmark.svg" alt="nodejs" width="40" height="40"/> </a> </p>

@ -0,0 +1,49 @@
const express = require("express");
const cors = require("cors");
const cookieSession = require("cookie-session");
const app = express();
var corsOptions = {
origin: "http://localhost:8080"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json()); /* bodyParser.json() is deprecated */
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true })); /* bodyParser.urlencoded() is deprecated */
app.use(
cookieSession({
name: "MickaelNode-session",
secret: "3Z~gU7p4Lct4+.c|DW2=",
httpOnly: true,
sameSite: 'strict'
})
);
const db = require("./app/models/model");
db.sequelize.sync();
// drop the table if it already exists
// db.sequelize.sync({ force: true }).then(() => {
// console.log("Supprime and re-synchronise, la base de données.");
// });
// simple route
app.get("/", (req, res) => {
res.json({ message: "Bienvenue dans l'application de mickaël Poupion." });
});
// routes
require("./app/route/voiture.route")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Le serveur fonctionne sur le port ${PORT}.`);
});

@ -0,0 +1,8 @@
CREATE DATABASE IF NOT EXISTS `devoirNode`
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
GRANT USAGE ON *.* TO "nodeApiUser"@"localhost" IDENTIFIED BY "Skw{C82,n2x4@QM<2.fN"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT ALL PRIVILEGES ON `devoirNode`.* TO 'nodeApiUser'@'localhost';

@ -0,0 +1,14 @@
module.exports = {
HOST: "localhost",
PORT: 3306,
USER: "nodeApiUser",
PASSWORD: "Skw{C82,n2x4@QM<2.fN",
DB: "devoirNode",
dialect: "mysql",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};

@ -0,0 +1,88 @@
const db = require("../models/model");
const Voiture = db.voiture;
exports.POSTVoiture = async (req, res) => {
// Save User to Database
try {
const voiture = await Voiture.create({
nom: req.body.nom,
nbrPlace: req.body.nbrPlace,
});
res.send(voiture);
} catch (error) {
res.status(500).send({ message: error.message });
}
};
exports.GETOneVoiture = async (req, res) => {
try {
const id = req.params.id;
console.log(id)
const voiture = await Voiture.findOne({
where: {
id: id,
},
});
if (voiture) {
res.send(voiture);
} else {
res.status(404).send({
message: `Impossible de trouver la voiture avec id=${id}.`
});
}
} catch (error) {
return res.status(500).send({ message: error.message });
}
};
exports.PUTVoiture = async (req, res) => {
try {
const voiture = await Voiture.update(req.body,{
where: {
id: req.params.id,
},
});
if (voiture == 1) {
res.send({
message: "La voiture a été mis à jour avec succès."
});
} else {
res.send({
message: `Impossible de mettre à jour la voiture avec id=${id}!`
});
}
} catch (error) {
return res.status(500).send({ message: error.message });
}
};
exports.DROPVoiture = async (req, res) => {
try {
const voiture = await Voiture.destroy({
where: { id: req.params.id }
})
console.log(voiture)
if (voiture == 1) {
res.send({
message: "La voiture a été supprimé avec succès !"
});
} else {
res.send({
message: `Impossible de supprimer la voiture avec id=${id}.`
});
}
} catch (error) {
return res.status(500).send({ message: error.message });
}
};

@ -0,0 +1,29 @@
const dbConfig = require("../config/db.config.js");
const Sequelize = require("sequelize");
const sequelize = new Sequelize(
dbConfig.DB,
dbConfig.USER,
dbConfig.PASSWORD, {
host: dbConfig.HOST,
port: dbConfig.PORT,
dialect: dbConfig.dialect,
operatorsAliases: 0,
pool: {
max: dbConfig.pool.max,
min: dbConfig.pool.min,
acquire: dbConfig.pool.acquire,
idle: dbConfig.pool.idle
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.voiture = require("./voiture/voiture.model")(sequelize, Sequelize);
module.exports = db;

@ -0,0 +1,12 @@
module.exports = (sequelize, Sequelize) => {
const Voiture = sequelize.define("voitures", {
nom: {
type: Sequelize.STRING
},
nbrPlace: {
type: Sequelize.INTEGER
},
});
return Voiture;
};

@ -0,0 +1,35 @@
const voiture = require("../../app/controller/voiture.controller");
module.exports = function(app) {
app.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"Origin, Content-Type, Accept"
);
next();
});
app.get(
"/api/voiture/GETOne/:id",
voiture.GETOneVoiture
);
app.post(
"/api/voiture/POST",
voiture.POSTVoiture
);
// Update a Tutorial with id
app.put(
"/api/voiture/PUT/:id",
voiture.PUTVoiture
);
// Delete a Tutorial with id
app.delete(
"/api/voiture/DROP/:id",
voiture.DROPVoiture
);
};

@ -0,0 +1,21 @@
{
"name": "devoir-node",
"version": "1.0.0",
"description": "",
"main": "api.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.0",
"cookie-session": "^2.0.0",
"cors": "^2.8.5",
"express": "^4.18.1",
"mysql2": "^2.3.3",
"nodemon": "^2.0.16",
"sequelize": "^6.20.1"
}
}

@ -0,0 +1,6 @@
API_PORT=8080
DB_HOST=localhost
DB_USER=node
DB_PASSWORD=nodeNicolas1
DB_PORT=3306
DB_NAME=node

@ -0,0 +1,38 @@
Installation des package:
npm i
Lancement de l'api:
nodemon
L'api dispose de 3 route:
POST : /api/create-client
Donnée en entrée: Body JSON
{
"nom": "",
"prenom": "",
"email": "",
"ville": "",
"date_naissance": "",
"pays": "",
"code_postal": ""
}
Le format de la date de naissance : dd/mm/yyyy
Donnée en sortie: Réussite de l'insertion ou non
----------------------------------------------
GET : /api/get-clients
Donnée en entrée: Aucune donnée
Donnée en sortie: Tout les clients de la base de donnée
----------------------------------------------
DELETE : /api/delete-client
Donnée en entrée: parametre id (récuperable avec la route get)
Donnée en sortie: Réussite de la suppression ou non

@ -0,0 +1,41 @@
import express from 'express';
import dotenv from 'dotenv';
import bodyParser from 'body-parser';
dotenv.config();
import DbManager from './dbManager.js';
const database = new DbManager(process.env.DB_HOST, process.env.DB_USER, process.env.DB_PASSWORD, process.env.DB_PORT, process.env.DB_NAME)
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/api/get-clients', async function (req, res) {
const results = await database.getClients();
res.send(results);
});
app.post('/api/create-client', async function (req, res) {
if (!req.body.nom || !req.body.prenom || !req.body.email || !req.body.ville || !req.body.date_naissance || !req.body.code_postal || !req.body.pays) {
return res.status(400).send({ message: 'Veuillez remplir tout les champs' });
}
const result = await database.insertClient(req.body)
res.status(result ? 200 : 400).send({ message: result ? 'Le client à été ajouté.' : 'Impossible d\'ajouter ce client.' })
});
app.delete('/api/delete-client', async function (req, res) {
if (!req.query.id) {
return res.status(400).send({ message: 'Veuillez indiquer l\'id du client à supprimer' });
}
const result = await database.deleteClient(req.query.id)
res.status(result?.affectedRows === 1 ? 200 : 400).send({ message: result?.affectedRows === 1 ? 'Le client à été supprimé.' : 'Le client n\'existe pas.' })
});
const port = process.env.API_PORT || 8080
app.listen(port, async function () {
console.log(`server listening on ${port}`);
});

@ -0,0 +1,12 @@
CREATE DATABASE IF NOT EXISTS node
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
GRANT USAGE ON *.* TO "node"@"localhost" IDENTIFIED BY "nodeNicolas1"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT USAGE ON *.* TO "node"@"%" IDENTIFIED BY "nodeNicolas1"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT ALL PRIVILEGES ON node.* TO 'node'@'%';
GRANT ALL PRIVILEGES ON node.* TO 'node'@'localhost';

@ -0,0 +1,55 @@
import mariadb from 'mariadb';
import moment from 'moment';
export default class DbManager {
constructor(host, user, password, port, name) {
this.pool = mariadb.createPool({
host: host,
port: port,
user: user,
password: password,
database: name,
connectionLimit: 5,
});
}
async conn() {
return await this.pool.getConnection();
}
async getClients() {
let conn = await this.conn();
try {
const rows = await conn.query('SELECT * FROM client');
rows.map(x => x.date_naissance = moment(x.date_naissance, 'YYYY-MM-DD HH:mm:ss').format('DD/MM/YYYY'));
return rows;
} catch (e) {
console.log(e)
return null;
}
}
async insertClient(client) {
let conn = await this.conn();
try {
const rows = await conn.query('INSERT INTO CLIENT(nom, prenom, email, date_naissance, pays, ville, code_postal) VALUES(?,?,?,?,?,?,?)',
[client.nom, client.prenom, client.email, moment(client.date_naissance, 'DD/MM/YYYY').format('YYYY-MM-DD HH:mm:ss'), client.pays, client.ville, client.code_postal]);
return rows;
} catch (e) {
console.log(e)
return null;
}
}
async deleteClient(id) {
let conn = await this.conn();
try {
const rows = await conn.query('DELETE FROM client WHERE id = ?', id);
return rows;
} catch (e) {
console.log(e)
return null;
}
}
}

@ -0,0 +1,20 @@
{
"name": "nodejs-bergeault-nicolas",
"version": "1.0.0",
"description": "",
"main": "api.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"mariadb": "^3.0.0",
"moment": "^2.29.3",
"nodemon": "^2.0.16"
},
"type": "module"
}

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS Client (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
nom VARCHAR(100),
prenom VARCHAR(100),
email VARCHAR(255),
date_naissance DATE,
pays VARCHAR(255),
ville VARCHAR(255),
code_postal CHAR(5)
);
INSERT INTO client(nom, prenom, email, date_naissance, pays, ville, code_postal) VALUES ('Nicolas','Bergeault','nico@gmail.com','2000-04-02','France','Saint Jacques de la lande', '35136'),('Mathieu','Chisqd','math@gmail.com','2009-06-02','France','Rennes', '35000'),('Léa','Larose','lea@gmail.com','2000-08-06','Luxembourg','Grevenmacher', 'L6720')

@ -0,0 +1,12 @@
CREATE DATABASE IF NOT EXISTS `database_tp_blanc_node`
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
GRANT USAGE ON *.* TO "JUSTE"@"localhost" IDENTIFIED BY "Leblanc"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT USAGE ON *.* TO "JUSTE"@"%" IDENTIFIED BY "Leblanc"
WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT ALL PRIVILEGES ON `database_tp_blanc_node`.* TO 'JUSTE'@'%';
GRANT ALL PRIVILEGES ON `database_tp_blanc_node`.* TO 'JUSTE'@'localhost';

@ -0,0 +1,35 @@
# SETUP
## DEPENDENCIES
- install dependencies with
```
npm install
npm install --only=dev
```
## DATABASE
Create the database using the .sql file
Run the migrations with:
```
npx sequelize-cli db:migrate
```
Run the seeders with:
```
npx sequelize-cli db:seed:all
```
## CONFIGURATION
**Configure the server port in the .env file.**
**Database configuration is in config/config.json file.**
# API
## START THE SERVER
You can start the server with the following command :
```
npm run dev
```
## SWAGGER
You should use the swagger available at **`http://localhost:<port>/api-docs`.**

@ -0,0 +1,44 @@
const createError = require('http-errors');
const express = require('express');
const cors = require('cors');
const documentationRouter = require('./helpers/documentation');
const { fishRouter } = require('./router/fishRouter');
const app = express();
app.use(cors({
credentials: true
}));
app.use(async (req, res, next) => {
express.json({
type: function () {
return true;
}
})(req, res, next);
});
app.use('', documentationRouter);
app.use('/fish',
fishRouter()
);
app.use(async (req, res, next) => {
next(createError.NotFound());
})
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.send({
err: {
status: err.status || 500,
message: err.message,
}
})
})
module.exports = app;

@ -0,0 +1,9 @@
{
"development": {
"username": "JUSTE",
"password": "Leblanc",
"database": "database_tp_blanc_node",
"host": "127.0.0.1",
"dialect": "mariadb"
}
}

@ -0,0 +1,94 @@
const createError = require('http-errors');
const { Fish, sequelize } = require('../models');
exports.addFish = (opts) => {
return async function (req, res, next) {
try {
const { fish } = req.body;
const result = await sequelize.transaction(async (t) => {
const newFish = await Fish.create({
name: fish.name,
color: fish.color,
length: fish.length,
speed: fish.speed,
});
return { newFish }
});
res.status(200).json({ msg: `Added fish to the database.` });
}
catch (error) {
return next(createError.InternalServerError(error));
}
}
}
exports.updateFish = (opts) => {
return async function (req, res, next) {
try {
const { id: fishId } = req.params;
const { fish } = req.body;
const result = await sequelize.transaction(async (t) => {
const updatedFish = Fish.update({
name: fish.name,
color: fish.color,
length: fish.length,
speed: fish.speed,
}, {
where: { id: fishId }
});
return { updatedFish }
});
res.status(200).json({ msg: `Updated fish.` });
}
catch (error) {
return next(createError.InternalServerError(error));
}
}
}
exports.deleteFish = (opts) => {
return async function (req, res, next) {
try {
const { id: fishId } = req.params;
const result = await sequelize.transaction(async (t) => {
const deletedFish = await Fish.destroy({ where: { id: fishId } });
return { deletedFish };
});
return res.status(200).json({ msg: "Deleted fish." });
}
catch (error) {
return next(createError.InternalServerError(error));
}
}
}
exports.getAllFish = (opts) => {
return async function (req, res, next) {
try {
const fishes = await Fish.findAll();
if (!fishes) {
return next(createError.NotFound("No fishes in the database."));
}
return res.status(200).json(fishes);
}
catch (error) {
return next(createError.InternalServerError(error));
}
}
}
exports.getFish = (opts) => {
return async function (req, res, next) {
try {
const { id: fishId } = req.params;
const fish = await Fish.findOne({ where: { id: fishId } });
if (!fish) {
return next(createError.NotFound());
}
return res.status(200).json(fish);
}
catch (error) {
return next(createError.InternalServerError(error));
}
}
}

@ -0,0 +1,25 @@
const router = require('express').Router();
const swaggerUi = require('swagger-ui-express');
const swaggerJsDoc = require('swagger-jsdoc');
const options = {
definition: {
openapi: "3.0.0",
info: {
title: "",
version: "",
description: "",
},
servers: [
{
url: `http://localhost:${process.env.PORT}`
}
]
},
apis: ["./router/*.js"]
}
const specs = swaggerJsDoc(options);
router.use('/api-docs', swaggerUi.serve);
router.get('/api-docs', swaggerUi.setup(specs));
module.exports = router;

@ -0,0 +1,70 @@
"use strict"
require('dotenv').config();
const http = require('http');
const fs = require('fs');
const db = require('./models/index');
const app = require('./app');
const normalizePort = val => {
const port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
};
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
const errorHandler = error => {
if (error.syscall !== 'listen') {
throw error;
}
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port: ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges.');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use.');
process.exit(1);
break;
default:
throw error;
}
};
const server = http.createServer(app);
server.on('error', errorHandler);
server.on('listening', async () => {
try {
await db.sequelize.authenticate();
console.log('Connection to the database has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
process.exit();
}
try {
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port ' + port;
console.log(`Listening on http://localhost:${port}`);
console.log(`Swagger available on http://localhost:${port}/api-docs`);
}
catch (error) {
console.error(`Unable start the server : ${error}`);
process.exit();
}
});
server.listen(port);

@ -0,0 +1,36 @@
'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Fishes', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
color: {
type: Sequelize.STRING
},
length: {
type: Sequelize.STRING
},
speed: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Fishes');
}
};

@ -0,0 +1,26 @@
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Fish extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
Fish.init({
name: DataTypes.STRING,
color: DataTypes.STRING,
length: DataTypes.STRING,
speed: DataTypes.STRING
}, {
sequelize,
modelName: 'Fish',
});
return Fish;
};

@ -0,0 +1,37 @@
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;

@ -0,0 +1,26 @@
{
"devDependencies": {
"sequelize-cli": "^6.4.1"
},
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"http-errors": "^2.0.0",
"mariadb": "^3.0.0",
"nodemon": "^2.0.16",
"sequelize": "^6.20.1",
"swagger-jsdoc": "^6.2.1",
"swagger-ui-express": "^4.4.0"
},
"name": "tp-blanc",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}

@ -0,0 +1,139 @@
const express = require('express');
const fishCtrl = require('../controller/fishController');
/**
* @swagger
* tags:
* name: Fish
* description: Fish managing api
*/
/**
* @swagger
* components:
* schemas:
* fish:
* type: object
* required:
* - name
* - color
* - length
* - speed
* properties:
* name:
* type: string
* description: fish name
* color:
* type: string
* description: fish color
* length:
* type: string
* description: fish length
* speed:
* type: string
* description: fish speed
* example:
* fish:
* name: 'toto'
* color: 'red'
* length: 'very smoll'
* speed: 'fasted in the jar'
*/
exports.fishRouter = (opts) => {
const router = express.Router();
/**
* @swagger
* /fish/{id}:
* get:
* summary: route to get a fish by id
* tags: [Fish]
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the fish to get
* responses:
* 200:
* description: Success adding a fish
*/
router.get('/:id([0-9]+)', fishCtrl.getFish(opts));
/**
* @swagger
* /fish/:
* get:
* summary: route to get all the fishes
* tags: [Fish]
* responses:
* 200:
* description: Got all the fishes
*/
router.get('/', fishCtrl.getAllFish(opts));
/**
* @swagger
* /fish/add:
* post:
* summary: route to add a fish
* tags: [Fish]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/fish'
* responses:
* 200:
* description: Success adding a fish
*/
router.post('/add', fishCtrl.addFish(opts));
/**
* @swagger
* /fish/{id}:
* put:
* summary: route to update a fish
* tags: [Fish]
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the fish to get
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/fish'
* responses:
* 200:
* description: Success updating the fish
*/
router.put('/:id([0-9]+)', fishCtrl.updateFish(opts));
/**
* @swagger
* /fish/{id}:
* delete:
* summary: route to delete a fish
* tags: [Fish]
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the fish to update
* responses:
* 200:
* description: Success deleting a fish
*/
router.delete('/:id([0-9]+)', fishCtrl.deleteFish(opts));
return router
}

@ -0,0 +1,37 @@
'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.bulkInsert('Fishes', [
{
name: 'Toto',
color: 'Red',
length: 'Very smoll, averaging 1cm on good days',
speed: 'Fastest in the aquarius, it is rumored that he used to compete in racing tournament in his younger days',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'The fish who is not an alien',
color: 'Green',
length: 'Buffed af, at least 10 cm',
speed: 'Abysmally slow, some says he is an alien due to his color and his buffeness',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'Nyan Fish',
color: 'Rainbow',
length: 'The rainbow being part of his body, is length is immeasurable',
speed: 'Distant cousin of nyancat and one of the racing star under the tutelage of Toto, thanks to the rainbow he was born with he is one of the fastest of his generation.',
createdAt: new Date(),
updatedAt: new Date()
}], {});
},
async down(queryInterface, Sequelize) {
await queryInterface.bulkDelete('Fish', null, {});
}
};

@ -0,0 +1,240 @@
// **********************************************************
// minimal restful api with mariadb connection
// extended from basic
// references
// https://mariadb.com/kb/en/nodejs-connector/
// uses mariadb
// **********************************************************
// sur base l'exemple de cours :
// https://git.polux.studio/Juan/cours-MDS/src/branch/master/b3-dev/node/session2/mariadb/server.js
// Reqs and defines
const http = require ('http'); // to create server
const url = require('url'); // to parse url
const BASIC_API_PORT = 3998;
//user database and password
const MARIADB_PSWD = "ov62p67t7PId9N3",
MARIADB_USER = "eval_db_user",
MARIADB_HOST = "127.0.0.1",
MARIADB_PORT = "3306",
MARIADB_NAME = "eval_db";
//require mariadb module
const mariadb = require('mariadb');
//create a pool
const pool = mariadb.createPool({
host: MARIADB_HOST,
user: MARIADB_USER,
password: MARIADB_PSWD,
port: MARIADB_PORT, // optional
database: MARIADB_NAME, // optional
connectionLimit: 5
});
// *************************************************************
// create basic server and implement handling different requests
const app = http.createServer
(
async (req, res) =>
{
// parse the incoming url
const parsedURL = url.parse(req.url, true);
//prepare global response
var response_text = "";
//a bit of followup of client requests
console.log('called with path : '+parsedURL.pathname);
console.log('called with method : '+req.method);
// ------------------------------------------------------------------------
// list tables
if(parsedURL.pathname.startsWith('/api/tables') && req.method === 'GET')
{
//create a temp local scope connection
let cnx;
// use try catch to get errors
try
{
cnx = await pool.getConnection();
const tables = await cnx.query("SHOW TABLES;");
response_text += tables.length+" table"+(tables.length===1?"":"s");
console.log(' found '+response_text+' to list');
if(tables.length > 0)
{
Object.keys(tables).forEach(function(key) {
var row = tables[key];
// meta holds the global response info...
// we don't really need it ... for now.
if(key !== 'meta')
{
response_text += "\n - "+row['Tables_in_'+MARIADB_NAME];
}
});
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// ------------------------------------------------------------------------
// if we want to list data of a specific table
if(parsedURL.pathname.startsWith('/api/table/') && req.method === 'GET')
{
table_name = extractLastItem(parsedURL.pathname);
console.log('listing '+table_name);
//create a temp local scope connection
let cnx;
try
{
cnx = await pool.getConnection();
const table_rows = await cnx.query("SELECT * FROM "+table_name+";");
response_text += table_rows.length+" row"+(table_rows.length===1?"":"s");
console.log(' found '+response_text+' to list');
header_done=false;
if(table_rows.length > 0)
{
dashline = "";
Object.keys(table_rows).forEach(function(key) {
var row = table_rows[key];
console.log(key);
// meta holds the global response info...
// we don't really need it ... for now.
if(key !== 'meta')
{
response_text += "\n ";
//response_text += JSON.stringify(row);
if(!header_done) {
dashline = "\n +"+'-'.repeat(Object.keys(row).length * 23 -2)+'-+ ';
response_text += dashline +"\n ";
Object.keys(row).forEach(function(fieldkey) {
response_text += ' + ' + fieldkey.substring(0,20).padEnd(20,' ');
});
response_text += ' + '
response_text += dashline;
response_text += "\n ";
header_done=true;
}
Object.keys(row).forEach(function(fieldkey) {
console.log(fieldkey);
response_text += ' | '+ row[fieldkey].toString().substring(0,20).padEnd(20,' ');
});
response_text += ' | ';
}
});
response_text += dashline;
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// ------------------------------------------------------------------------
if(parsedURL.pathname.startsWith('/api/table') && req.method === 'DELETE')
{
table_name = extractLastItem(parsedURL.pathname);
console.log('deleting in '+table_name);
//get the get param
row_to_del = parseInt(parsedURL.query.row);
console.log('deleting row '+row_to_del);
let cnx;
try
{
cnx = await pool.getConnection();
queryresult= await cnx.query("DELETE FROM "+table_name+" WHERE id_"+table_name+"='"+row_to_del+"';");
console.log('query result : '+JSON.stringify(queryresult));
if(parseInt(queryresult.affectedRows) === 0) {
response_text="No matching row found. Does it exist ?";
}
else {
response_text= queryresult.affectedRows+" row(s) deleted";
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// else if this is a simple get
if (parsedURL.pathname.startsWith('/api') && req.method === 'GET')
{
res.statusCode = 200;
res.end("You got me !");
}
// if url doent match any send error
else
{
res.statusCode = 400;
res.end("API Endpoint Not Supported");
}
}
);
// EOF create server.
// call server specifying on wich port to listen
app.listen(BASIC_API_PORT);
console.log('Mariadb RESTful API server started on: ' + BASIC_API_PORT);
// *************************************************
// define internal functions
// -------------------------------------------------
// get last item of path used as param of request
function extractLastItem(path)
{
return path.substring(path.lastIndexOf("/")+1,path.length);
}
// EOF extractIPAddress

@ -0,0 +1,12 @@
CREATE DATABASE IF NOT EXISTS `eval_db`
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
GRANT USAGE ON *.* TO "eval_db_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_db_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_db`.* TO 'eval_db_user'@'%';
GRANT ALL PRIVILEGES ON `eval_db`.* TO 'eval_db_user'@'localhost';

@ -0,0 +1,166 @@
-- phpMyAdmin SQL Dump
-- version 5.1.1
-- https://www.phpmyadmin.net/
--
-- Hôte : 127.0.0.1
-- Généré le : mer. 01 juin 2022 à 11:36
-- Version du serveur : 10.4.19-MariaDB
-- Version de PHP : 7.4.20
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de données : `eval_db`
--
-- --------------------------------------------------------
--
-- Structure de la table `option`
--
DROP TABLE IF EXISTS `option`;
CREATE TABLE `option` (
`id_option` bigint(20) UNSIGNED NOT NULL,
`option_name` varchar(191) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
`option_value` longtext COLLATE utf8mb4_unicode_520_ci NOT NULL,
`autoload` varchar(20) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT 'yes'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
--
-- Déchargement des données de la table `option`
--
INSERT INTO `option` (`id_option`, `option_name`, `option_value`, `autoload`) VALUES
(7, 'start_of_week', '1', 'yes'),
(8, 'use_balanceTags', '0', 'yes'),
(11, 'comments_notify', '1', 'yes'),
(12, 'posts_per_rss', '10', 'yes'),
(13, 'rss_use_excerpt', '0', 'yes'),
(14, 'mailserver_url', 'mail.example.com', 'yes'),
(15, 'mailserver_login', 'login@example.com', 'yes'),
(16, 'mailserver_pass', 'password', 'yes'),
(17, 'mailserver_port', '110', 'yes'),
(18, 'default_category', '1', 'yes'),
(19, 'default_comment_status', 'open', 'yes'),
(20, 'default_ping_status', 'open', 'yes'),
(21, 'default_pingback_flag', '1', 'yes'),
(22, 'posts_per_page', '10', 'yes'),
(23, 'date_format', 'j F Y', 'yes'),
(24, 'time_format', 'G\\hi', 'yes'),
(25, 'links_updated_date_format', 'd F Y G\\hi', 'yes'),
(26, 'comment_moderation', '0', 'yes'),
(27, 'moderation_notify', '1', 'yes'),
(28, 'permalink_structure', '/%postname%/', 'yes'),
(30, 'hack_file', '0', 'yes'),
(31, 'blog_charset', 'UTF-8', 'yes'),
(32, 'moderation_keys', '', 'no'),
(34, 'category_base', '', 'yes'),
(6159, '_transient_timeout_as-post-store-dependencies-met', '1646145794', 'no'),
(6160, '_transient_as-post-store-dependencies-met', 'yes', 'no'),
(6163, 'action_scheduler_migration_status', 'complete', 'yes');
-- --------------------------------------------------------
--
-- Structure de la table `passager`
--
DROP TABLE IF EXISTS `passager`;
CREATE TABLE `passager` (
`id_passager` int(11) NOT NULL,
`nom` varchar(255) NOT NULL,
`prenom` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
`siege` varchar(4) NOT NULL,
`vol_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Déchargement des données de la table `passager`
--
INSERT INTO `passager` (`id_passager`, `nom`, `prenom`, `age`, `siege`, `vol_id`) VALUES
(1, 'Welma', 'Roucier', 68, 'b047', 1);
-- --------------------------------------------------------
--
-- Structure de la table `vol`
--
DROP TABLE IF EXISTS `vol`;
CREATE TABLE `vol` (
`id_vol` int(11) NOT NULL,
`de` varchar(255) NOT NULL,
`a` varchar(255) NOT NULL,
`via` varchar(255) NOT NULL,
`places` int(11) NOT NULL,
`reservations` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Déchargement des données de la table `vol`
--
INSERT INTO `vol` (`id_vol`, `de`, `a`, `via`, `places`, `reservations`) VALUES
(1, 'Prague', 'Cork', 'Rennes', 25, 11);
--
-- Index pour les tables déchargées
--
--
-- Index pour la table `option`
--
ALTER TABLE `option`
ADD PRIMARY KEY (`id_option`),
ADD UNIQUE KEY `option_name` (`option_name`),
ADD KEY `autoload` (`autoload`);
--
-- Index pour la table `passager`
--
ALTER TABLE `passager`
ADD PRIMARY KEY (`id_passager`);
--
-- Index pour la table `vol`
--
ALTER TABLE `vol`
ADD PRIMARY KEY (`id_vol`);
--
-- AUTO_INCREMENT pour les tables déchargées
--
--
-- AUTO_INCREMENT pour la table `option`
--
ALTER TABLE `option`
MODIFY `id_option` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6164;
--
-- AUTO_INCREMENT pour la table `passager`
--
ALTER TABLE `passager`
MODIFY `id_passager` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT pour la table `vol`
--
ALTER TABLE `vol`
MODIFY `id_vol` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

@ -0,0 +1,33 @@
{
"name": "sandbox-mariadb",
"version": "1.0.1",
"description": "Basic API with mariadb connection",
"main": "server.js",
"repository": {
"type": "git",
"url": "git+https://git.polux.studio/Juan/node-sandbox.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bugs": {
"email": "juan@agence-polux.fr"
},
"keywords": [
"test",
"sandbox",
"tutorials",
"mariadb"
],
"author": {
"name": "Juan from Polux",
"url": "https://agence-polux.fr",
"email": "juan@agence-polux.fr"
},
"license": "ISC",
"homepage": "https://git.polux.studio/Juan/node-sandbox/src/branch/master/README.md",
"dependencies": {
"mariadb": "^2.5.4",
"nodemon": "^2.0.16"
}
}
Loading…
Cancel
Save