En este apartado haremos la implementación del MVC, mediante la construcción de un sistema completo de Registro y Login de Usuarios. Un Usuario podrá acceder a una pantalla de registro donde podrá registrarse ingresando Nombre y Contraseña.
El sistema aquí expuesto responde a un sistema tradicional de Login/Registro de Usuarios. La mayoría de las Aplicaciones Express son usadas como SPA, de manera que, para cosntruir estos sistemas, utilizan mecanismos de JWT implementando OAuth o similar.
No explicaremos ese tipo de mecanismos aquí porque es muy popular y ya hay demasiado tutoriales sobre ello. Por esta razón, en este capítulo se expone la forma tradicional de este sistema mediante peticiones y respuestas Http con recarga de vistas.
El punto de entrada siempre son las rutas. Definiremos todas aquellas necesarias para un sistema de login y registro completo, esto es:
Definiremos todas esas rutas en un nuevo archivo llamado auth.js el cual ubicaremos dentro del directorio routes. En él escribiremos:
var express = require('express');
var router = express.Router();
var passport = require('passport');
var authCtrl = require('../controllers/AuthCtrl');
router.get('/login', authCtrl.getLogin);
router.post('/login', authCtrl.login);
router.get('/logout', authCtrl.logout);
router.get('/register', authCtrl.getRegister);
router.post('/register', authCtrl.register);
Con todas las url's ya mapeadas, procederemos a crear el Controlador AuthCtrl.
Crearemos el archivo AuthCtrl dentro de controllers. Este Controlador deberá comunicarse con el modelo User que definiremos con Mongoose para realizar consultas a la BBDD y crear registros (al registrarse un Usuario). En este fichero escribiremos:
'use strict';
const mongoose = require('mongoose');
const User = mongoose.model('User');
const passport = require('passport');
module.exports.getRegister = (req, res) => {
res.render('auth/register', { });
};
module.exports.register = (req, res) => {
let salt = User.getSalt();
User.create({
'name': req.body.name,
'email': req.body.email,
'password': User.hashPassword(req.body.password, salt),
'passwordSalt': salt
}, function(err, user){
if(err) console.log(err);
req.login(user, function(err) {
if (err) console.log(err);
console.log(`User ${req.user.name} registered`);
return res.redirect('/'); //res.redirect('/users/' + req.user.username);
});
});
};
module.exports.getLogin = (req, res) => {
res.render('auth/login', {});
};
module.exports.login = (req, res, next) => {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) {
return res.redirect('/auth/login');
}
req.logIn(user, function(err) {
if (err) { return next(err); }
//return res.redirect('/users/' + user.username);
console.log(`User ${req.user.name} logged in`);
return res.redirect('/');
});
})(req, res, next);
};
module.exports.logout = (req, res) => {
console.log(`User ${req.user.name} logged out`);
req.logout();
res.redirect('/');
};
Con esto ya tendremos la funcionalidad definida para cada una de las rutas de routes/auth.js.
Para lograr que un Usuario se mantenga logado deberemos tratar el tema de las Sesiones. Este no es un tema sencillo y requiere un procesamiento determinado que puede ser complicado. Afortunadamente existen un par de paquetes que nos ayudarán con esta tarea: Express-Session y Passport.
Instalaremos ambos paquetes con:
npm install -S express-session passport
Ahora deberemos integrar todo esto en nuestra aplicación Express!
Editaremos app.js con las siguientes modificaciones:
...
const bodyParser = require('body-parser');
const session = require('express-session'); //<-- Nuevo
const passport = require('passport'); //<-- Nuevo
require('./server/models/db.js');
...
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ // <-- Nuevo
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize()); // <-- Nuevo
app.use(passport.session()); // <-- Nuevo
app.use('/', index);
app.use('/users', users);
app.use('/auth', auth); // <-- Nuevo
...
Perfecto! Ya casi tenemos a Express listo para soportar Registro y Login de Usuarios. Sólo nos falta realizar la configuración de Passport, pero esto lo dejaremos para el próximo capítulo.
Recordad que podéis mirar el código desde aquí.