CRUD de usuarios en NodeJS: Parte 3
Tags: node, javascript, users, severjs
Published: 2020-05-16 08:52:44

Ahora que ya tenemos el servidor de Node levantado y la base de datos en MongoDB operativa, hay que diseñar la entidad de usuario y sus acciones. Para ello vamos a empezar por crear el modelo, pero antes vamos a añadir extensiones que necesitaremos más adelante, empezando por *mongoose-unique-validator*, que agrega validación previa al guardado para campos únicos dentro de un esquema Mongoose:
```
   $ npm install --save mongoose-unique-validator
```
Vamos a instalar también la extensión *bcrypt*, con ella vamos a cifrar la contraseña para "hashearla". Esto quiere decir que vamos a usar contraseñas con un método de cifrado del tipo hash.
```
   $ npm install --save bcrypt
```
Otra librería que nos vendrá muy bien para recuperar los campos de un formulario para actualizar nuestro usuario será *underscore* y para instalarla lanzamos:
```
   $ npm install --save underscore
```
Para acabar, vamos a añadir la librería *body-parser* que nos permitirá coger cualquier dato (de usuario, paginación, limite para mostrar. etc) que enviemos al servidor al consumir los servicios API Rest, directamente desde el objeto body dentro de req, así **req.body.foo**. A parte, podemos añadir validaciones de tipo de dato de una manera sencilla. Por ejemplo: **req.body.foo.toString()**
```
   $ npm install --save body-parser
```
Cuando hayamos terminado de instalar las librerías, creamos una carpeta nueva llamada **models** dentro de la carpeta **server**:
```
   $ mkdir server/models
```
Dentro de la carpeta creamos un fichero llamado User.js, este fichero contendrá el esquema de nuestra entidad usuario y será el encargado de crear este esquema en la base de datos:
```javascript
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');

let Schema = mongoose.Schema;

let userSchema = new Schema({
    name: {
        type: String,
        required: [true, 'El nombre es requerido']
    },
    email:{
        type: String,
        unique: true,
        required: [true, 'El correo electrónico es requerido']
    },
    password: {
        type: String,
        required: [true, 'La contraseña es requerido']
    },
    img: {
        type: String,
        required: false
    },
    status: {
        type: Boolean,
        default: true
    }
});

userSchema.methods.toJSON = function(){
    let user = this;
    let userObject = user.toObject();
    delete userObject.password;
    return userObject;
}

userSchema.plugin(uniqueValidator, {
    message: '{PATH} debe de ser único'
});

module.exports = mongoose.model('User', userSchema);
```
Una vez hayamos creado el modelo volemos a crear una carpeta nueva llamada **routes**, dentro de **server** y al mismo nivel que models.
```
   $ mkdir server/routes
```
Dentro de ella vamos a crear un fichero llamado **users.js**, y será el fichero que contendrá las acciones que se pueden hacer sobre nuestros usuarios. Es el fichero que contiene las acciones del CRUD. Los servicios serán del tipo: 
* POST para crear.
* PUT para editar.
* GET para listar.
* DELETE para borrar o desactivar un usuario.

Este fichero user.js contiene lo siguiente:
```javascript
const express = require('express');
const bcrypt = require('bcrypt');
const _ = require('underscore');
const User = require('../models/User');
const app = express();

// Listado de usuarios
app.get('/usuario', (req, res) => {

    let from = req.query.from || 0;
    from = Number(from);

    let limit = req.query.limit || 5;
    limit = Number(limit);

    let conditions = {
        status: true
    }

    User.find(conditions, 'name email status')
        .skip(from)
        .limit(limit)
        .exec((err, users) => {
        if(err){
            return res.status(400).json({
               ok: false,
               err  
            });
        }
    
        User.countDocuments(conditions,(err, sumUsers) => {
            res.json({
                ok: true,
                users,
                sumUsers
            });
        });
    });
});

// Crear usuario
app.post('/usuario', (req, res) => {
    let body = req.body;

    let user = new User({
        name: body.name,
        email: body.email,
        password: bcrypt.hashSync(body.password, 10)
    });

    user.save((err, userDB) => {
        if(err){
            return res.status(400).json({
               ok: false,
               err  
            });
        }

        res.json({
            ok: true,
            usuario: userDB
        });
    });
});

// Actualizar usuario
app.put('/usuario/:id', (req, res) => {
    let id = req.params.id;
    let body = _.pick(req.body, ['name', 'email', 'img', 'status']);

    User.findByIdAndUpdate(id, body, {new: true, runValidators: true}, (err, userBD) => {
        if(err){
            return res.status(400).json({
               ok: false,
               err  
            });
        }

        res.json({
            ok: true,
            usuario: userBD
        });
    });
});

// Eliminar/Desactivar usuario
app.delete('/usuario/:id', (req, res) => {
    let id = req.params.id;
    User.findByIdAndUpdate(id, {status: false}, {new: true}, (err, userBD) => {
        if(err){
            return res.status(400).json({
               ok: false,
               err  
            });
        }

        if(!userBD){
            return res.status(400).json({
                ok: false,
                err:{
                    message: 'Usuario no encontrado'
                } 
             });
        }
        
        res.json({
            ok: true,
            userBD
        });
    });
});

module.exports = app;
```
En mi caso, no quiero eliminar ningún usuario, así que el DELETE es para desactivar cambiando el estado del usuario por false.
Ahora, para poder usar este controlador que tiene las funciones de nuestro CRUD, hay que importarlo en nuestro fichero server.js con la siguiente línea de código:
```javascript
app.use(require('./routes/users'));
```
Además hay que importar la librería que hemos instalado antes, llamada body-parser, que nos permitirá acceder a los datos de una manera más sencilla:
```javascript
const bodyParser = require('body-parser');
```
De este modo, nuestro fichero server.js quedará así:
```javascript
    const express = require('express');
    const mongoose = require('mongoose');
    const bodyParser = require('body-parser');

    // Parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: false }));
    // Parse application/json
    app.use(bodyParser.json());
    // Include controller of the entity
    app.use(require('./routes/users'));

    const run = async () => {
        await mongoose.connect(SERVER_BBDD, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
            useCreateIndex: true,
        });
    };

    run().catch(error => console.error(error));

    app.listen(process.env.PORT, () => {
         console.log(`Escuchando en el puerto 3000`);
    });
```
Una vez tengamos nuestro servidor levantado, podemos hacer las peticiones para crear, editar, desactivar o listar los usuarios registrados en nuestra base de datos de mangodb. En mi caso, uso Postman y [aquí](https://documenter.getpostman.com/view/3846138/SWTK3YsQ?version=latest#5671a6c7-0fc3-4aa4-9aeb-0487ea862ca1) puedes encontrar una breve documentación de los comandos que uso para ejecutar las apis que acabamos de hacer. Esto es lo básico funcional para tener un CRUD completo de usuarios.