Tutorial de Programación Android – Login con NodeJS, Express y Json Web Token – Añadiendo rutas

Login con NodeJS, Express y Json Web Token – Añadiendo rutas

Continuamos con la segunda parte del tutorial de Programación Android sobre como crear una aplicación móvil para Android que nos permita hacer login y autentificar usuarios, manteniendo la sesión de los mismos abierta. En la entrada anterior habíamos llegado hasta la creación de las tablas en mysql haciendo uso de sequelize, una vez definido el modelo de usuario que íbamos a utilizar.

Toca ahora ponerse con las rutas y parte de la lógica de la API, en concreto con la parte de registro y login de usuarios. Para ello, vamos a empezar esta parte del tutorial de Programación Android creando en la raiz del proyecto un fichero que se llame rutas.js, que se encargará de gestionar las peticiones que lleguen a nuestra API, con el siguiente contenido:

var auth = require('basic-auth');
var jwt = require('jsonwebtoken');
var express = require('express');
var rutas =express.Router();
var registro = require('./funciones/registro');
var login = require('./funciones/login');
  rutas.get('/', function(req,res){
    res.end('Bienvenido a la raiz de la api');
  });

exports.rutas = rutas;

Lo que hacemos es utilizar un objeto rutas del tipo router de Express y posteriormente exportarlo para hacer uso de él desde otras partes de la aplicación. Además hemos importado con require dos funciones que veremos más adelante, pero que por su nombre, ya podéis ver que se encargaran del login y del registro de usuarios. De momento solo respondemos a las peticiones a la raiz de la api, es decir a «tu-ip:1515/api/v1».

Ahora se hace necesario modificar nuestro index.js de la raíz del proyecto, que quedaría de la siguiente manera:

var modelos = require("./modelos");
var express = require('express');
var app = express();
var bodyparser = require('body-parser');
var logger = require('morgan');
var puerto = process.env.PORT || 1515;
var rutas = require('./rutas.js').rutas;

app.use(bodyparser.json());
app.use(logger('dev'));
app.use('/api/v1',rutas);
app.listen(puerto);
console.log('Escuchando en '+puerto);

Como veréis hemos añadido el módulo de Express, Morgan para que se encargue de hacer el log elegante por consola de las peticiones recibidas y hemos fijado el puerto de escucha de nuestra API. Además hemos importado nuestro fichero de rutas, le hemos dicho a Express que responda a las peticiones a ‘/api/v1’ haciendo uso de ese fichero de rutas y que haga uso de bodyparser.json a la hora de analizar el cuerpo de las peticiones recibidas, ya que solo vamos a realizar peticiones en formato JSON.

Como ya hemos dicho hemos creado dos ficheros nuevos en el directorio funciones: login.js y registro.js. El contenido de login.js es el siguiente:

var modelos = require('../modelos');
var bcrypt = require('bcryptjs');

exports.Login = function(email, password) {
  var promesa = new Promise (function(resolve,reject){
    modelos.Usuarios.findOne({
            where: {
                email: email
            }
        })
        .then(function(usuario) {
            if (!usuario) {
                reject({ status: 404, mensaje: 'No existe el usuario' });
            } else {
              console.log('Usuario encontrado. Seguimos procesando');
              var hashed_password= usuario.password;
              if (bcrypt.compareSync(password, hashed_password)) {
                    console.log('login coorrecto');
                    resolve({ status: 200, mensaje: email });

                } else {
                    console.log('Login incorrecto');
                    reject({ status: 401, mensaje: 'Invalid Credentials !' });
                }
            }

        })
        .catch(function(err){
          console.log(err);
          reject({ status: 500, mensaje: 'Error interno' });
        })

  })
  return promesa;

}

Por motivos didácticos, hasta ahora las había usado muy poco, vamos a trabajar con promesas. Las promesas son una herramienta que nos permite manejar la asincronía de Javascript y evitar el uso excesivo de callbacks. Nuestro código continúa ejecutándose mientras se resuelve la promesa. Si la promesa se resuelve correctamente (resolve) se ejecuta la parte del .then. Si la promesa se resuelve con un error (reject), se ejecuta la segunda parte. Así que nuestra función de login va a recibir dos parámetros, el email y el password. Mediante sequelize va a buscar un usuario cuyo email coincida con el que hemos pasado. Si no lo encuentra devolverá un error 404 (reject) de recurso no encontrado.

En caso de que el usuario exista, comprueba que coincide el password, si coincide devolverá un estado 200 OK y el email del usuario y si no coincide devolverá un error 401 de no autorizado.

Ahora vamos a ver el contenido del archivo registro.js:

var Sequelize = require('Sequelize');
var modelos = require('../modelos');
var bcrypt = require('bcryptjs');

exports.RegistrarUsuario = function(nombre, email, password,isadmin) {
  var promesa = new Promise (function(resolve,reject){
    var salt = bcrypt.genSaltSync(10);
    var hash = bcrypt.hashSync(password, salt);
    var nuevoUsuario = modelos.Usuarios.build({
        username: nombre,
        password: hash,
        email: email,
        isAdmin:isadmin
    });
    nuevoUsuario.save()
        .then(function(nuevoUsuario) {
            console.log('Usuario ' + nuevoUsuario.username + ' creado con éxito');
            resolve({ status: 200, mensaje: "Usuario creado con éxito" });
        })
        .catch(Sequelize.ValidationError, function(error) {
            console.log("Errores de validación:", error);
            for (var i in error.errors) {
                console.log('Error en el campo:', error.errors[i].value);
            };
            reject({ status: 400, mensaje: "Errores de validación " ,error});
        })
        .catch(function(error) {
            console.log("Error:", error);
            reject({ status: 500, mensaje: "Error interno" });
        });
  });
  return promesa;

}

Se trata de una función a la que le pasaremos los parámetros del usuario que queremos registrar (nombre, email, password y si se trata de un administrador), tratará  de guardarlo en la base de datos. Si todo es correcto devolverá un status 200 (OK) y si alguno de los campos no se ajusta a los criterios o falta, nuestra función devolverá un «Bad Request» o error 400.

Para probar que todo funciona, hemos ensuciado un poco el index.js de la carpeta modelos:

var path = require('path');
var Sequelize = require('sequelize');
var registro = require('../funciones/registro');
var login = require('../funciones/login');
// Configurar Sequelize para usar mysql

var sequelize = new Sequelize('node-login-android', 'root', '', {
  host: 'localhost',
  dialect: 'mysql',

  pool: {
    max: 5,
    min: 0,
    idle: 10000
  }

});
// Importar modelos.

var Usuarios = sequelize.import(path.join(__dirname,'usuarios'));

// Crear tablas pendientes:
sequelize.sync({force:true})
.then(function() {

    console.log('Tablas y modelos creados');
    // Creamos un usaurio admin de prueba
    registro.RegistrarUsuario('Pepe','pedro@prueba.com','prueba',true)
    .then(function(){
      //Se ha creado el usuario tiramos tres logins de prueba
      login.Login('pedro@prueba.com','prueba')
      .then (function(a){
        console.log(a);
      }, function (err){
        console.log('Reject');
        console.log(err);
      })

      login.Login('pedro@prueba.com','prueba1')
      .then (function(a){
        console.log(a);
      }, function (err){
        console.log('Reject');
        console.log(err);
      })

      login.Login('pedro2@prueba.com','prueba')
      .then (function(a){
        console.log(a);
      }, function (err){
        console.log('Reject');
        console.log(err);
      })

    },function(err){
      console.log("Reject")
      console.log(err);
    });



  }, function (err) {
    console.log('Algo no fue bien: ', err);
  });
// Exportar modelos:

exports.Usuarios = Usuarios;

Hemos añadido un código que se ejecuta una vez que la tabla se ha creado. En ese bloque de código, creamos un usuario y, una vez creado, le lanzamos tres peticiones de login para comprobar que todo funciona como debería. El resultado es el siguiente, como podéis ver en la imagen, el usuario se crea correctamente:

Y cuando ejecutamos nuestro código deberíamos ver una salida como esta:

Se crea el usuario y el sistema responde correctamente a las peticiones de login. En próximos artículos continuaremos viendo como, una vez autorizado el usuario le devolveremos un token que se utilizará para validar las peticiones que haga a nuestra API.

[wphtmlblock id=»517″]

 

5/5 - (1 voto)

Pedro Pablo Moral

Licenciado en ADE. Experto Universitario en Gestión de RRHH por competencias-

Esta entrada tiene 2 comentarios

  1. Carl

    Que tal, la tercera parte del tutoria no se encuentra disponible, la podrías resubir por favor

    1. pedropablomoral

      Corregido. Muchas gracias por el aviso

Deja una respuesta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.