TechBook #2 : Création du web service Node.js avec une base de données MongoDB

Avant de commencer, nous rappelons que dans le premier article nous avons installé l’environnement de travail de notre application ainsi nous avons créé un projet Node.js (TechBook #1).

Le but de cet article est de structurer le projet, créer les web services du module authentification (sign up/sign in) et les tester avec un client HTTP comme Postman.

Structure du projet 

Afin d’utiliser les bonnes pratiques, on doit ajouter 3 dossiers dans le projet backend :

  • modules : contient les modèles utilisés dans la base de données 
  • routes : on peut déclarer pour chaque modèle un fichier contenant le code du web service lui correspondant.
  • uploads : ce dossier contient les fichier téléchargés (images ou vidéos). Il est structuré comme ceci : uploads/images/users

Création du modèle de l’utilisateur 

Après la création des dossiers ci-dessous, on doit ajouter le fichier « user.js » pour définir le modèle de l’utilisateur dans le dossier « modules ».  Voici ci-dessous le code permettant de réaliser cela :

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var pathFolder = 'uploads/images/users/';
const config = require('../config');
const userSchema = new Schema({
email: {
        type: String,
        required: true   
    },     
    password: {
        type: String
    },
    firstName: {
        type: String
    },
    lastName: {
        type: String
    },
    gender:  {
        type: String
    },
    age:  {
        type: String
    },
    photo: {
        type: String
    },
    createdAt : {
        type: Date,
        default: Date.now()
    },
    },
    {
    toJSON:{virtuals:true}
});
userSchema.methods.getUser=function () {
    return({
        _id: this._id,
        email: this.email,
        firstName: this.firstName,
        lastName: this.lastName,
        gender: this.gender,
        age: this.age,
        photo: this.photo,
        pictureProfile:this.pictureProfile,
        createdAt: this.createdAt
    })
};
userSchema.virtual('pictureProfile').get(function () {
    if (this.photo !== undefined) {
    return config.host+pathFolder + this.photo;
    }else{
        return config.host+pathFolder +'avatar.png';
    }
});
userSchema.pre('save', function (next) {
    var user = this;
    if (this.isModified('password') || this.isNew) {
        bcrypt.genSalt(10, function (err, salt) {
            if (err) {
                return next(err);
            }
            bcrypt.hash(user.password, salt, null, function (err, hash) {
                if (err) {
                    return next(err);
                }
                if (user.password){
                user.password = hash;
                }
                next();
            });
        });
    } else {
        return next();
    }
});
userSchema.methods.comparePassword = function (passw, cb) {
    bcrypt.compare(passw, this.password, function (err, isMatch) {
        if (err) {
            return cb(err);
        }
        cb(null, isMatch);
    });
};
const User = module.exports = mongoose.model('User', userSchema);

On a crypté le mot de passe avec bcrypt-nodejs. Aussi nous avons ajouté une image de profile par défaut nommé «avatar.png». Elle est téléchargée sous le dossier /uploads/images/users

Quelle est la différence entre les deux champs : photo et pictureProfile ? photo est le nom de l’image avec extension mais pictureProfile retourne l’url de l’image qu’on peut lire mais on doit ajouter dans le fichier app.js ces lignes pour autoriser la lecture des fichiers.

// allow to read files in folder uploads

var publicDir = require('path').join(__dirname,'/Uploads');
app.use('/Uploads', express.static(publicDir));

Développement des web services

SignUp

Commençons maintenant le développement du premier web service, celui qui nous rendra possible la création de comptes utilisateurs.

On doit créer un fichier « users.js » et on doit l’appeler dans le fameux fichier « app.js » pour permettre la lecture les url des web services développé dans le fichier « users.js ».

const usersRoutes = require('./routes/users');
// allow to excutes url of web services in such route
app.use('/users', usersRoutes);

Dans ce cas on peut exécuter les web services sous l’url suivant : http://localhost:2500/users/ws_name

Revenons au fichier « users.js » pour développer le web service inscription.

const express = require('express');
const router = express.Router();
const User = require('../models/user');
var jwt = require('jsonwebtoken');
// signup
router.post('/signUp', function (req, res) {
    try {
        User.findOne({'email': req.body.email}, function (err, user) {
            if (err) {
                res.json({
                    status: 0,
                    message: ('Error while saving') + err
                });
}
            if (user) {
                res.json({
                    status: 0,
                    message: ('Email already used')
                });
            } else {
                    var newUser = new User({
                        firstName: req.body.firstName,
                        lastName: req.body.lastName,
                        email: req.body.email,
                        password: req.body.password,
                        gender: req.body.gender,
                        age: req.body.age,
                        photo: "avatar.png",
                        createdAt: Date.now(),
                    });
                    //save the user
                    newUser.save(function (err, savedUser) {
                        if (err) {
                            res.json({
                                status: 0,
                                message: err
                            });
                        } else {
                            var token = jwt.sign(savedUser.getUser(), 'MySecret', {expiresIn: 3600});
                            res.json({
                                status: 1,
                                message: 'signUp successfully',
                                data: {
                                    user: savedUser.getUser(),
                                    token: token                                }
                            })
                        }
                    });
            }
        });
    } catch (err) {
        console.log(err);
        res.json({
            status: 0,
            message: '500 Internal Server Error',
            data: {}
        })
    }
});

Il ne faut jamais oublier d’exporter le router à la fin de chaque fichier du dossier routes :

module.exports = router;

Maintenant on peut tester notre premier service à travers Postman mais à condition de lancer la commande «mongod» dans le terminal de votre PC et bien sûr lancer notre serveur via la commande «node app.js» . Le résultat sera affiché comme ceci :                                                

  • le champ status retourne 1 s’il y un succès ou 0 si il y a une erreur ou l’email existe déjà
  • le champ message retourne un message
  • enfin le champ data contient l’utilisateur sauvegardé et code JWT contient les données codées. 

3-1 : SignIn

Dans la même veine voici le code du login :

//signin  user
router.post('/signIn', function (req, res) {
    try {
        User.findOne({email: req.body.email}, function (err, user) {
            if (err) {
                res.json({
                    status: 0,
                    message: ('erreur auth SignIn') + err
                });
            }
            if (!user) {
                res.json({
                    status: 0,
                    message: 'Authentication failed. User not found.'
                });
            } else {
                // check if password matches
                user.comparePassword(req.body.password, function (err, isMatch) {
                    if (isMatch && !err) {
                        // if user is found and password is right create a token
                        var token = jwt.sign(user.getUser(), 'MySecret', {expiresIn: 3600});
                        res.json({
                            status: 1,
                            message: 'Login successfully ',
                            data: {
                                user: user.getUser(),
                                token: token
                            }
                        });
                    } else {
                        res.json({
                            status: 0,
                            message: 'Authentication failed. Wrong password.'
                        });
                    }
                });
            }
        });
    } catch (err) {
        console.log(err);
        res.json({
            status: 0,
            message: '500 Internal Server Error',
            data: {}
        })
    }
});

Le résultat du login web service est comme ceci :

Finalement je vous conseille de télécharger le code source de notre projet qui contient les fonctionnalités nécessaires pour apprendre le développement avec Node.js sous le ce lien https://github.com/moben-technology/TechBook.

Perspective : Dans l’article suivant nous vous montrons comment consommer les web services dans l’application iOS à travers le pod Alamofire .

A bientôt.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *