Développer avec NodeJS, Express, MongoDB, PugJS et Socket.IO

Cher visiteur,

Dans cet article, nous allons voir comment concevoir une application web plutôt robuste avec NodeJS et Mongodb de façon très simple et minimaliste.

Pour les plus néophytes d’entre vous qui n’ont aucunes connaissances des routes nodejs, dépendances et j’en passe, le mieux est de commencer par la base de NodeJS via le tutoriel de mateo21 sur :

https://openclassrooms.com/courses/des-applications-ultra-rapides-avec-node-js

Tout d’abord, il vous faudra installer NodeJS ainsi que MongoDB

Sous Windows (Windows Server ou 10) :

Il suffit d’installer NodeJS en version LTS pour Windows x64 et MongoDB en version Windows Server, l’outil étant compatible aussi pour Windows 10.

Sous Linux :

apt-get install nodejs && apt-get install mongodb

Une fois l’environnement installé, il vous suffit d’ouvrir un terminal ou une console Windows et taper cette commande pour vérifier l’installation (ceci vous retournera la version de nodejs installé sur votre post) :

node -v

Pour commencer votre application, il vous faudra créer un répertoire et naviguer dedans via le terminal et la console et taper :

npm init

Cette commande aura pour objectif de vous poser des questions sur votre application, quelle est sa version, son auteur et j’en passe, elle finira ensuite par créer un fichier package.json qui contiendra toutes ces informations ainsi que les packages npm utilisés par votre application, les packages npm étant des extensions proposées par la communauté NodeJS.

Votre package.json devrait maintenant ressembler à ceci :

{
  "name": "application",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

La partie main avec “index.js” sera votre point d’entrée de l’application, du coup, le main de votre application sera “index.js” que vous devez créer en plaçant un code minimal dedans :

var express = require('express');
var app = express();
var pug = require('pug');
var io = require('socket.io').listen(app.listen(80));

conf = {
	lang: "fr",
	title: "Mon application",
	urlsocketio: "http://127.0.0.1:80/"
}

app.set('view engine', 'pug');

app.get('/', function(req, res) {
    res.render('index', { conf:conf } );
});

Il existe une autre façon de coder avec NodeJS si vous voulez réellement de l’objet avec “TypeScript”, je ne l’aborderais pas ici mais libre à vous de l’utiliser.

Pour faire fonctionner votre application, il vous faudra aussi installer les packages npm dont votre application a besoin, lancer cette commande dans le répertoire de votre application :

npm install express pug socket.io –save

Le –save permettant d’insérer vos packages dans le package.json ce qui permettra de déployer votre application à l’avenir avec un simple “npm install” sans avoir besoin de vous souvenir des noms de chaque package.

Maintenant vous devez créer un template Pug, Pug étant un langage simplifié du HTML qui a un gros avantage, c’est qu’on ne ferme aucune balise du coup le code est allégé, prenons l’exemple d’une page HTML classique avec Bootstrap :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Mon Application</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
    <h1>Hello, world!</h1>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    </body>
</html>

Celle-ci s’écrira de cette façon avec Pug (faites un répertoire views dans votre application avec un index.pug et copiez ce code dedans) :

doctype
html(lang="en")
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title Mon Application
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 Hello, world!
		script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js")
		script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous")

Plus sympathique du coup pour de grandes pages html vous vous en doutez.

Si tout se passe bien, vous pouvez dès maintenant lancer votre application nodejs en faisant un “node index.js”, si vous naviguez avec votre navigateur sur le port 80 comme définit dans le code, vous verrez votre hello world.

Que faire maintenant ? on va bien entendu pousser la chose en codant un exemple de login avec un code de sécurité captcha et ainsi vous serez capable de coder vos propres applications.

Tout d’abord, il faut faudra modifier un peu votre index.js :

var express = require('express');
var app = express();
var pug = require('pug');
var io = require('socket.io').listen(app.listen(80));
var session = require('cookie-session');
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
var sha256 = require('sha256');
var svgCaptcha = require('svg-captcha');

var MongoClient = require('mongodb').MongoClient;
var MongoClientURL = "mongodb://127.0.0.1:27017/mydatabase";

conf = {
	lang: "fr",
	title: "Mon application",
	urlsocketio: "http://127.0.0.1:80/"
}

app.use("/styles", express.static(__dirname + '/styles'));
app.set('view engine', 'pug');

app.use(session({secret: 'mysessionsecretpassphrase'}));
app.use(function(req, res, next){
    if (typeof(req.session.user) === 'undefined') {
        req.session.user = {};
    }
    next();
});

app.get('/', function(req, res) {
	if (Object.keys(req.session.user).length > 0) {
		username = req.session.user.username;
		res.render('panel', { conf:conf, user:req.session.user }  );
    } else {
        var captcha = svgCaptcha.create();
    	req.session.captcha = captcha.text;
        res.render('index', { conf:conf, "captcha":captcha });
    }
});

app.post('/login', urlencodedParser, function(req, res) {
	if(req.body.captcha === req.session.captcha) {
		MongoClient.connect(MongoClientURL, function(err, db) {
			db.collection('users').findOne({ 'username':req.body.username, 'password':sha256(req.body.password) }, function(err, result) {
				if(result !== null) {
	                req.session.user = result;
	            }
	            db.close();
	            res.redirect('/');
			});
		});
	} else {
		var captcha = svgCaptcha.create();
    	req.session.captcha = captcha.text;
    	res.render('index', { "captcha":captcha, "error":"The security code entered is not correct." });
	}
});

app.get('/logout', function (req, res) {
    delete req.session.user;
    res.redirect('/');
});

Comme vous pouvez le voir dans cette exemple, on a rajouté tout ce qui est nécessaire pour gérer une page de login avec captcha en se connectant au serveur mongodb local sur la base de données “mydatabase”, vu que nous avons rajouté des packages npm il va falloir les installer un à un :

npm install cookie-session body-parser sha256 svg-captcha mongodb –save

À noter qu’il est possible d’avoir du sha512 ou d’autres algos pour chiffrer ses mots de passes, référez vous aux différents packages npm.

Connectons nous à notre base de données mongodb, de base sur Windows, il vous faudra lancer l’exécutable se trouvant dans :

C:\Program Files\MongoDB\Server\3.4\bin\

Vous aurez à ce moment là deux exécutables :

– mongo.exe : Le client CLI permettant de se connecter à notre serveur mongodb.
– mongod.exe : Le serveur en lui même.

Exécutons mongod.exe pour lancer notre serveur et connectons nous à l’aide de mongo.exe, vous devriez pouvoir exécuter des commandes dans celui-ci, voici un récapitulatif des différentes commandes importantes :

show dbs : Permet de voir les base de données disponibles.
use namedb : Permet d’utiliser une base de données, namedb étant le nom de la base de données que vous souhaitez utiliser (donc mydatabase)
show collections : Permet de voir les tables de la base de données sélectionnée.
db.nametable.insert() : Permet d’insérer des données dans une table, nametable étant notre nom de table.
db.nametable.find() : Permet de chercher des données dans une table.
db.nametable.remove() : Permet de supprimer des données dans une table.
db.nametable.update() : Permet de mettre à jour des données dans une table.
db.nametable.drop() : Permet de drop totalement la table.

Il existe une multitude de commandes, je vous conseille de vous rendre sur la documentation officielle pour plus de détails.

Nous allons donc créer notre utilisateur admin avec le mot de passe admin1234 :

use mydatabase
db.users.insert( { username:"admin", password:"ac9689e2272427085e35b9d3e3e8bed88cb3434828b43b86fc0596cad4c6e270" } );

Le hash étant notre sha256 de “admin1234”, si tout se passe bien, vous devriez avoir comme résultat :


WriteResult({ "nInserted" : 1 })

Nous pouvons donc maintenant nous connecter à notre panel, pour cela il va aussi falloir modifier votre index.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
		link(rel="stylesheet" href="styles/login.css")
	body
		section#section0.section
			div.container
				div.row
					div.col-md-12
						form.form-signin(action="login" method="post")
							h2.form-signin-heading Please sign in
							input.form-control(name="username" type="text" placeholder="Username..." required autofocus)
							input.form-control(name="password" type="password" placeholder="Password..." required)
							div#captcha !{captcha.data}
							input.form-control(style="margin-bottom: 0.5em;" name="captcha" type="text" placeholder="Security code..." required)
							button.btn.btn-lg.btn-primary.btn-block(type="submit") Sign in
							if error
								p#error #{error}
		script(src="https://code.jquery.com/jquery-3.2.1.min.js")
		script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous")

Et créer un fichier styles/login.css :

* {
    margin: 0;
    padding: 0;
}
body {
    padding-top: 40px;
    padding-bottom: 40px;
    background-color: #eee;
}
.form-signin {
    max-width: 330px;
    padding: 15px;
    margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
    margin-bottom: 10px;
}
.form-signin .checkbox {
    font-weight: normal;
}
.form-signin .form-control {
    position: relative;
    height: auto;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
    padding: 10px;
    font-size: 16px;
}
.form-signin .form-control:focus {
    z-index: 2;
}
.form-signin input[type="text"] {
    margin-bottom: -1px;
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
    margin-bottom: 10px;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

#captcha {
    text-align: center;
}

#error {
    color: #ff0000;
    text-align: center;
}

Ainsi que notre panel.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 hello #{user.username}

Vous avez maintenant un code avec un formulaire de login fonctionnel sous nodejs, express, mongodb et pugjs, qu’en est il de socket.io ?

Pour communiquer avec socket.io il nous suffit de modifier notre index.js en rajoutant :

io.sockets.on('connection', function (socket) {
	socket.emit('logged', "Le serveur vous salue !");

	socket.on('message', function (message) {
		console.log(message);
	});
});

socket.emit se chargera d’envoyer un message au client, socket.on attendra la réponse du client, il est aussi possible d’utiliser socket.broadcast.emit() pour envoyer un message à tous les clients en même temps.

Pour réceptionner le message côté client, il vous suffira de rajouter ce javascript dans panel.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 hello #{user.username}
		script(src="/socket.io/socket.io.js")
		script.
			var socket = io.connect('#{conf.urlsocketio}');
			socket.on('logged', function(message) {
				alert(message);
				socket.emit('message', "Salut serveur, je suis connecté !");
			});

Voilà, en espérant que cet article vous a permis d’avoir une bonne approche sur nodejs, mongodb, pugjs et express, vous êtes maintenant capable de développer en real time et de façon sécurisé (n’oubliez tout de même pas que mongodb est certes du NoSQL mais NoSQL ne veut pas dire qu’il n’y a plus d’injections possibles, il vous faudra faire attention si vous utilisez les variables $where, $set et autres dans mongodb).

Une autre chose importante à savoir, de base mongodb autorise les connexions invités, vérifiez bien que votre serveur utilise son fichier de configuration pour ne pas autoriser de connexions distantes.

Voici les sources complètes de mon article légèrement améliorées :

Sources

Pour déployer la source, npm install 😉

One thought on “Développer avec NodeJS, Express, MongoDB, PugJS et Socket.IO

  1. Bonjour !
    Super tuto : https://sh0ckfr.com/2017/10/developper-avec-nodejs-express-mongodb-pugjs-et-socket-io/
    J’ai juste un problème sur la fin, quand je clique sur “Sign in” rien ne se passe, le fichier panel.pug dois bien être dans le dossier View ?
    je test le capcha en mettant n’importe quoi mais il ne repond pas non plus, je dois avoir ratter quelque chose mais je ne sais pas quoi… Ce dois provenir du panel.pug … mais je ne sais pas comment regler ça.

    Encore une fois super tuto bien détaillé, je vous remercie d’avance !

Leave a Reply

Your email address will not be published. Required fields are marked *