Parte 2 | Creando un sistema de chat sobre NodeJS con Socket.IO, MongoDB, Foundation y Openshift

Esta es la segunda parte de la serie de artículos ‘Creando un sistema de chat sobre NodeJS’, en total son 5 partes:

Registro y login de usuarios.

A la aplicación del articulo anterior, añadiremos la capacidad de saber exactamente que usuarios están conectados a la aplicación en cualquier momento, también informaremos a los usuarios cada vez que alguien se desconecte.

Cada usuario deberá registrarse y autenticarse en el sistema para poder utilizar el chat, de esta manera sabremos que usuarios están activos y que usuario envía cada mensaje, con esta información podremos crear un historial de conversaciones en los siguientes artículos.

Requisitos necesarios.

Los requisitos para este articulo son los mismos que en el primer articulo. Trabajaremos sobre el código que escribimos durante la primera parte. Para poder utilizar el driver de Mongodb y las funciones de bcrypt-nodejs instalaremos los siguienes paquetes:

>$ npm install --save mongodb
>$ npm install --save bcrypt-nodejs

Usuarios.

Para manejar objetos ‘usuario’ vamos a crear funciones especificas para almacenar y recuperar usuarios en la base de datos. Crearemos un objeto especifico para ello, llamado UserDAO (User Data Access Object | Objeto de acceso a datos del usuario). Los datos que almacenaremos de cada usuario son: username, password y email, para mantener seguros los password de nuestros usuarios, vamos a encriptar los passwords mediante bcrypt-nodejs.

El código para nuestro UserDAO.js:

/* Util para encriptar el password del usuario */
var bcrypt = require('bcrypt-nodejs');
/**
* Data Access Object (DAO) para 'users',
* Debe ser construido con un objeto conectado a la
* base de datos
*/
function UserDAO(db) {
/**
* Si el constructor es llamado sin el operador 'new',
* muestra una advertencia y lo llama correctamente.
*/
if (false == (this instanceof UserDAO)) {
console.log('WARNING: UserDAO constructor called without "new" operator');
return new UserDAO(db);
}
/* Colección 'users' en la base de datos */
var users = db.collection('users');
this.addUser = function (username, password, email, callback) {
// Verificamos que el usuario no exista aun
users.findOne({'_id': username}, function (err, user) {
if (err) throw err;
if (user) {
var user_yet_exist_error = new Error('User yet exists');
user_yet_exist_error.msg = "User yet exists"
return callback(user_yet_exist_error, null);
}
else {
// Generate password hash
var salt = bcrypt.genSaltSync();
var password_hash = bcrypt.hashSync(password, salt);
// Crear el nuevo 'user' con los parametros dados.
var user = {'_id': username, 'password': password_hash, 'email': email};
// Insertar el nuevo usuario en la base de datos
users.insert(user, function (err, result) {
if (err) return callback(err, null);
console.log('Nuevo usuario creado');
return callback(null, result[0]);
});
}
});
}
this.validateLogin = function (username, password, callback) {
users.findOne({'_id': username}, function (err, user) {
if (err) return callback(err, null);
if (user) {
if (bcrypt.compareSync(password, user.password)) {
callback(null, user);
}
else {
var invalid_password_error = new Error('Invalid password');
invalid_password_error.msg = 'Invalid password';
callback(invalid_password_error, null);
}
}
else {
var no_such_user_error = new Error('User not found');
no_such_user_error.msg = 'User not found';
callback(no_such_user_error, null);
}
});
}
}
module.exports.UserDAO = UserDAO;
view raw UsersDAO.js hosted with ❤ by GitHub

Sobre el código:

  • El archivo ‘UserDAO.js’ se encuentra dentro de la carpeta ‘dao’ ubicada en la raíz de la aplicación.
  • La función ‘addUser’ solo creara un usuario en la base de datos si el username asignado no ha sido registrado antes con otro usuario.
  • En las lineas 38 y 39 se genera un hash basado en el password ingresado por el usuario y sera lo que almacenaremos en la base de datos.
  • La función ‘validateLogin’ utiliza bcrypt para comparar la contraseña ingresada con el hash almacenado en la base de datos para validar las credenciales del usuario.
  • Al crear un objeto UserDAO deberá pasarse como parámetro un objeto conectado a la base de datos para poder consultar e insertar usuarios.

El registro.

Para que los usuarios puedan registrarse, creamos una pagina con un formulario para los datos de registro.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Signup to chat team SS</title>
</head>
<body>
<h1> Signup to chat team SS</h1>
<form id="signup-form">
<label for="username">Username</label><br>
<input id="username" name="username" placeholder="Choose an username" required>
<br><br><label for="password">Password</label><br>
<input id="password" name="password" placeholder="Type a password" type="password" required>
<br><br><label for="email">Email</label><br>
<input id="email" name="email" placeholder="User email" type="email" required>
<br><br><button onclick="signup()" type="button">Signup</button>
</form>
<br><span id="msg"></span>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script&gt;
<script type="text/javascript">
/**
* Esta funcion se ejecuta al hacer clic en el boton 'Signup'
* registra mediante ajax al nuevo usuario
*/
function signup() {
$.ajax({
type: "POST",
url: '/signup',
data: $('#signup-form').serialize(),
success: function (data) {
$('#msg').empty();
if (data.error) {
$('#msg').append(data.err.msg);
}
else {
$('#msg').append('User registered successfully');
$('#signup-form')[0].reset();
window.location = '/';
}
},
dataType: 'json'
});
}
</script>
</body>
</html>
view raw signup.html hosted with ❤ by GitHub
  • El archivo ‘signup.html’ debe ir dentro de la carpeta ‘views’
  • Cuando se presiona el botón ‘signup’ se enviaran los datos al servidor mediante ajax, , el servidor enviara como respuesta un objeto JSON para informar sobre el resultado de nuestra petición.
  • Si el usuario ya ha sido registrado antes, se mostrara un mensaje de error en la página de registro.
  • Si el registro es exitoso, se direccionará al usuario a la página de login, para que pueda iniciar sesión y utilizar el sistema.

El cliente.

Ahora vamos a implementar las nuevas funcionalidades en el Frontend del sistema, utilizaremos Zurb Foundation para mostrar un ‘modal dialog’ solicitando las credenciales al usuario antes de poder utilizar el sistema. En los siguientes artículos analizaremos como funciona Zurb Foundation, por ahora nos limitaremos a utilizar el ‘modal dialog’. También en el cliente crearemos listeners para los eventos de WebSocket generados por el servidor.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chat room</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/foundation.min.css">
</head>
<body>
<h3>Connected users:</h3>
<a id="btn-login" href="#" data-reveal-id="login-modal">Login</a>
<ul id="online-userslist"></ul>
<h3>Messages:</h3>
<ul id="list-msgs">
</ul>
<textarea id="new-msg" cols="30" rows="5" placeholder="New message"></textarea>
<!-- Modal dialog for login -->
<div id="login-modal" class="reveal-modal" data-reveal>
<h2>Login</h2>
<div id="alerts"></div>
<form id="login-form">
<label for="username">Username:</label>
<input name="username" type="text" placeholder="Username" required >
<br><label>Password:</label>
<input name="password" type="password" placeholder="Password" required >
<button onclick="login()" type="button">Login</button>
<br><span>Or <a href='/signup'>signup</a> if you dont have an account</span>
</form>
</div>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script&gt;
<script src="js/foundation.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var user = {};
$(document).foundation();
$(document).ready(function () {
$('#login-modal').foundation('reveal', 'open');
});
function login() {
$.ajax({
type: "POST",
url: '/login',
data: $('#login-form').serialize(),
success: function (data) {
$('#alerts').empty();
if (data.error) {
var html = '<div data-alert class="alert-box alert round">'
+ data.err.msg + '</div>';
$('#alerts').append(html);
}
else {
user = data.user;
var socket = new io();
configureSocket(socket);
$('#btn-login').css('display', 'none');
$('#login-modal').foundation('reveal', 'close');
}
},
dataType: 'json'
});
}
function configureSocket(socket) {
/**
* Cuando el servidor envia la lista de usuarios conectados.
* se reciben a través de este evento,
* cada usuario se agrega a la lista de usuarios online
* @param {[type]} users Array con usuarios conectados en el momento
*/
socket.on('all online users', function (users) {
console.log(users.length + ' users received');
for (var i=0; i<users.length; i++)
{
var htmluser = '<li id="' + users[i]._id + '">' + users[i]._id + '</li>';
$('#online-userslist').append(htmluser);
}
});
/**
* Listener para el evento 'chat message'
* Notese que es el mismo evento que se envia
* desde el servidor.
* Agregamos el mensage entrante a la lista.
*/
socket.on('chat message', function (msg) {
$('#list-msgs').append( $('<li>').text(msg) );
});
/**
* Listener para evento 'new user', el servidor lo emite
* cuando un usuario se ha conectado
* @param {[json]} nuser el usuario recien conectado
*/
socket.on('new user', function (nuser) {
var linuser = '<li id="' + nuser._id + '">'+ nuser._id + '</li>';
$('#online-userslist').append(linuser);
});
/**
* Cada vez que un usuario se desconecta, debemos eliminarlo
* de la lista de usuarios conectados, el servidor envia un mensaje
* con este evento para informarnos sobre un usuario desconectado.
* @param {[json]} nuser El usuarios que se acaba de desconectar
*/
socket.on('remove user', function (nuser) {
$('#' + nuser._id).remove();
})
/**
* Emitimos un evento de tipo 'chat message' cada vez
* que se presiona 'Enter' en el textarea y enviamos
* su contenido como mensaje al servidor.
*/
$('#new-msg').keyup(function (evt) {
if (evt.keyCode === 13) {
socket.emit('chat message', $('#new-msg').val());
$('#new-msg').val('');
}
});
/**
* Solicitamos al servidor la lista de usuarios conectados
* en este momento.
*/
socket.emit('all online users');
/**
* Emitimos el evento 'new user' para que el servidor
* informe a todos los usuarios que estamos en linea.
*/
socket.emit('new user', user);
}
</script>
</body>
</html>
view raw chat.html hosted with ❤ by GitHub
  • El WebSocket no se inicializa ni los escuchadores de eventos se activan hasta que el usuario se haya autenticado correctamente.
  • El botón ‘login’ ejecuta la función ‘login()’, que envía los datos al servidor y recibe una respuesta a través de ajax, en la cual el servidor nos dice si las credenciales son correctas o no, si las credenciales son correctas se inicializa el socket y se configuran los escuchadores de eventos.
  • En la función ‘configureSocket’ (Ejecutada después de un login exitoso) Se configuran los listener para los eventos, a continuación se emite el evento ‘all online users’ para solicitar al servidor la lista de todos los usuarios conectados en este momento, luego se emite el evento ‘new user’ para que el servidor informe a todos los usuarios del sistema que nos hemos conectado.
  • Cuando el cliente deje la página, el servidor detectara que el socket se ha desconectado y notificara al resto de usuarios que un usuario se ha desconectado.
  • Asegúrate de descargar Zurb Foundation Framework e incluir ‘normalize.css’ y ‘foundation.min.css’ en la carpeta ‘views/css’. También deberás incluir el archivo ‘foundation.min.js’ en la carpeta ‘views/js’

El servidor.

La pieza central de todo el sistema es el código del servidor, este debe atender y procesar las peticiones del frontend. Debemos agregar al servidor las rutas para registrar y autenticar usuarios, así como las rutas para las solicitudes de archivos css y javascript que el frontend requiera. También configuraremos ‘Socket.IO’ para responder apropiadamente a los nuevos tipos de eventos.

/**
* Server.js
* @author : DiganmeGiovanni | https://twitter.com/DiganmeGiovanni
* @Created on: 25 Oct, 2014
*/
/* Librerias necesarias para la aplicación */
var bodyParser = require('body-parser');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var MongoClient = require('mongodb').MongoClient;
var userDAO = require('./dao/UserDAO').UserDAO;
// Para acceder a los parametros de las peticiones POST
app.use(bodyParser());
/* Mongodb config */
var mdbconf = {
host: 'localhost',
port: '27017',
db: 'chatSS'
};
/* Get a mongodb connection and start application */
MongoClient.connect('mongodb://'+mdbconf.host+':'+mdbconf.port+'/'+mdbconf.db, function (err, db) {
if (err) return new Error('Connection to mongodb unsuccessful');
var usersDAO = new userDAO(db); // Initialize userDAO
var onlineUsers = [];
/** *** *** ***
* Configuramos el sistema de ruteo para las peticiones web:
*/
app.get('/signup', function (req, res) {
res.sendFile( __dirname + '/views/signup.html');
});
app.post('/signup', function (req, res) {
var username = req.body.username;
var password = req.body.password;
var email = req.body.email;
usersDAO.addUser(username, password, email, function (err, user) {
if (err) {
res.send({ 'error': true, 'err': err});
}
else {
user.password = null;
res.send({ 'error': false, 'user': user });
}
});
});
app.post('/login', function (req, res) {
var username = req.body.username;
var password = req.body.password;
usersDAO.validateLogin(username, password, function (err, user) {
if (err) {
res.send({'error': true, 'err': err});
}
else {
user.password = null;
res.send({ 'error': false, 'user': user});
}
});
});
/** css and js request */
app.get('/css/foundation.min.css', function (req, res) {
res.sendFile(__dirname + '/views/css/foundation.min.css');
});
app.get('/css/normalize.css', function (req, res) {
res.sendFile(__dirname + '/views/css/normalize.css');
});
app.get('/js/foundation.min.js', function (req, res) {
res.sendFile(__dirname + '/views/js/foundation.min.js');
});
/** *** *** */
app.get('*', function(req, res) {
res.sendFile( __dirname + '/views/chat.html');
});
/** *** *** ***
* Configuramos Socket.IO para estar a la escucha de
* nuevas conexiones.
*/
io.on('connection', function(socket) {
console.log('New user connected');
/**
* Cada nuevo cliente solicita con este evento la lista
* de usuarios conectados en el momento.
*/
socket.on('all online users', function () {
socket.emit('all online users', onlineUsers);
});
/**
* Cada nuevo socket debera estar a la escucha
* del evento 'chat message', el cual se activa
* cada vez que un usuario envia un mensaje.
*
* @param msg : Los datos enviados desde el cliente a
* través del socket.
*/
socket.on('chat message', function(msg) {
io.emit('chat message', msg);
});
/**
* Mostramos en consola cada vez que un usuario
* se desconecte del sistema.
*/
socket.on('disconnect', function() {
onlineUsers.splice(onlineUsers.indexOf(socket.user), 1);
io.emit('remove user', socket.user);
console.log('User disconnected');
});
/**
* Cuando un cliente se conecta, emite este evento
* para informar al resto de usuarios que se ha conectado.
* @param {[type]} nuser El nuevo usuarios
*/
socket.on('new user', function (nuser) {
socket.user = nuser;
onlineUsers.push(nuser);
io.emit('new user', nuser);
});
});
/**
* Iniciamos la aplicación en el puerto 3000
*/
http.listen(3000, function() {
console.log('listening on *:3000');
});
});
view raw server.js hosted with ❤ by GitHub
  • El objeto ‘mdbconf’ almacena los parámetros necesarios para establecer una conexión con mongodb.
  • En la linea 15 indicamos que vamos a utilizar el código de ‘./daos/UserDAO.js’, NodeJS infiere la extensión ‘js’, por lo que solo escribimos el nombre del archivo.
  • Una vez establecida la conexión con mongodb, se inicializa el objeto UsersDAO (linea 32) para ingresar y consultar con la base de datos.
  • Las peticiones POST (Signup y Login) se realizan mediante ajax, por lo que, el servidor no necesita enviar ningún archivo como respuesta, bastará con enviar un objeto JSON como respuesta.
  • En las lineas 75 – 87 se configuran las rutas para los archivos estáticos css y javascript que se utilizan en el frontend.
  • A partir de la linea 98 se configuran los eventos para ‘Socket.IO’, también cada vez que un cliente se conecta, se agrega a la lista de usuarios conectados que el servidor utiliza para llevar el registro de usuarios online.

El resultado.

Para poner a funcionar la aplicación asegúrate antes de iniciar la base de datos para que se pueda establecer la conexión, despues bastara con ejecutar el servidor con nodejs.

>$ node server.js
Imagen de login

Login page

Signup page

Signup page

Chat in action

Chat in action

La mayoría de funciones están documentadas en el código, asegúrate de leerlo detenidamente junto con la documentación incluida.

En los siguientes artículos agregaremos belleza y funcionalidad a nuestra aplicación.

Si estas a punto cometer suicidio tratando de poner a funcionar esta aplicación, no dudes en comentar tus dudas sobre la implementación del código fuente. 🙂

Happy Coding !!

52 comentarios en “Parte 2 | Creando un sistema de chat sobre NodeJS con Socket.IO, MongoDB, Foundation y Openshift

  1. Pingback: Parte 1 | Creando un sistema de chat sobre NodeJS con Socket.IO, MongoDB, Foundation y Openshift | Linea por linea

    1. enrique

      discupla me aparece error que dice que
      C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\mongo_client.js:804
      throw err;
      ^

      TypeError: db.collection is not a function
      at new UserDAO (C:\Users\enrique\Desktop\chat+\dao\UserDAO.js:13:17)
      at C:\Users\enrique\Desktop\chat+\vistas\server.js:24:18
      at C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\utils.js:414:17
      at executeCallback (C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\utils.js:406:9)
      at C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\mongo_client.js:270:5
      at connectCallback (C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\mongo_client.js:944:5)
      at C:\Users\enrique\Desktop\chat+\node_modules\mongodb\lib\mongo_client.js:801:11
      at nextTickCallbackWith0Args (node.js:420:9)
      at process._tickCallback (node.js:349:13)

      Responder
    1. diganmegiovanni Autor

      Que tal @Gerson … Has trabajado con el API de facebook o twitter anteriormente? … A través de las APIs podrías acceder a los mensajes del usuario y enviar mensajes ne su nombre … Es algo complejo que no cabe en un comentario de respuesta, me parece un buen punto para incluir dentro de esta serie de artículos, posiblemente lo anexe 🙂 … Pero si tienes mucha curiosidad te recomiendo visitar https://developers.facebook.com/ y también https://dev.twitter.com/ … Allí encontraras guías practicas para comenzar a trabajar con las APIs de facebook o twitter.

      Responder
  2. C. Giovanni

    Hola, realicé toda la Parte 1 y funcionó a la perfección.
    Posteriormente realicé la Parte 2, sin embargo al ejecutar el archivo server.js en la consola de comandos de node.js arroja el siguiente error:
    __________________________________________________________________________________________________________________
    C:\Users\Admin\Documents\Chat-SS>node server.js

    module.js:340
    throw err;
    ^
    Error: Cannot find module ‘./dao/UserDAO’
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object. (C:\Users\Admin\Documents\Chat-SS\server.js:15:19)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    _________________________________________________________________________________________________________________
    ¿Quisiera saber porque arroja el error? y ¿Cómo se puede solucionar?.
    =)

    Responder
    1. diganmegiovanni Autor

      Que tal C. Giovanni.
      Mirando el mensaje de error que node proporciona, puedes ver que te indica que no ha podido localizar el modulo ‘./dao/UserDAO’, asegurate de colocar el archivo ‘UserDAO.js’ en la carpeta ‘dao’ en la raiz de la aplicación, que en tu caso seria en la ruta: ‘C:\Users\Admin\Documents\Chat-SS\dao\’ … (([ Asegurate de que el nombre del archivo sea ‘UserDAO.js’ en lugar de ‘UsersDAO.js’ || He actualizado la redacción del articulo para aclarar el nombre del archivo y los directorios ])).

      Comentanos si esto resuelve el problema. 🙂
      Happy Coding !!

      Responder
      1. C. Giovanni

        Muchas gracias, me sirvió bastante, de hecho en el archivo Server.js de la línea 15 viene algo así:
        var userDAO = require(‘./dao/UserDAO’).UserDAO; lo cual requiere el módulo UserDAO y ahora entiendo porque me lanzaba dicho error.
        (>‿◠)✌
        Por cierto instale los drivers de MongoDB para Nodejs [ npm install –save mongodb] pero: ¿Debo instalar MongoDB en la PC para iniciar la base de datos? o ¿Sólamente los drivers de MongoDB son suficientes para ejecutar la aplicación?

        Responder
        1. diganmegiovanni Autor

          Para poder utilizar mongodb desde tu aplicación node, debes tener instalado el servidor de base de datos mongodb en tu maquina, en la primera parte de la serie de articulos, en el apartado de requisitos previos se menciona que debes tener una instalación funcional de mongodb para poder seguir estos articulos. Puedes buscar en google como instalarla en Windows o en cualquier otro OS que quieras utilizar 🙂

          Responder
  3. Josue Fernández

    Hola, ¿como podría implementar en cada mensaje el nombre del remitente del mismo?, es decir que aparezca en los mensajes: nombre_usuario:mensaje

    Responder
  4. Nelson

    Hola amigo he seguido todos los pasos en este post. Me ha funcionado casi en su totalidad.

    El unico error que me esta pasando es el siguiente:
    cuando intento registrar un nuevo usuario, el lo hace pero me detiene el server, tengo que volver a arrancarlo.
    te muestro el error:

    New user connected
    User disconnected
    User disconnected
    Nuevo usuario creado
    C:\Chat-SS\node_modules\mongodb\lib\utils.js:97
    process.nextTick(function() { throw err; });
    ^
    TypeError: Cannot set property ‘password’ of undefined
    at C:\Chat-SS\server.js:54:23
    at C:\Chat-SS\dao\UserDAO.js:49:18
    at handleCallback (C:\Chat-SS\node_modules\mongodb\lib\utils.js:95:12)
    at C:\Chat-SS\node_modules\mongodb\lib\collection.js:496:5
    at executeOp (C:\Chat-SS\node_modules\mongodb\node_modules\mongodb-core\lib\
    wireprotocol\2_4_support.js:370:33)
    at C:\Chat-SS\node_modules\mongodb\node_modules\mongodb-core\lib\wireprotoco
    l\2_4_support.js:416:11
    at Callbacks.emit (C:\Chat-SS\node_modules\mongodb\node_modules\mongodb-core
    \lib\topologies\server.js:84:3)
    at null.messageHandler (C:\Chat-SS\node_modules\mongodb\node_modules\mongodb
    -core\lib\topologies\server.js:218:23)
    at Socket. (C:\Chat-SS\node_modules\mongodb\node_modules\mongodb-
    core\lib\connection\connection.js:259:22)
    at Socket.emit (events.js:107:17)

    C:\Chat-SS>

    Responder
    1. Alexis Reyes

      yo ví el código, y encontré que el problema viene cuando borras el pass del usuario. Creo que hay que corregirlo desde el código original:

      else {
      user.password = null;
      res.send({ ‘error’: false, ‘user’: user });
      }

      por esto otro:
      else {
      res.send({ ‘error’: false, ‘user’: user });
      }

      saludos

      Responder
    1. diganmegiovanni Autor

      Entre la escuela y los proyectos personales he tenido muy poco tiempo disponible, sin embargo, aprovechando estos dias de receso en la universidad he puesto manos a la obra y publicare la siguiente parte muy pronto.

      Responder
    1. diganmegiovanni Autor

      Hola Manuel.
      Seguro, lo que mencionas parece una buena practica, muy similar al flujo de autenticación JWT (Json Web Tokens), te sugiero googlear un poco sobre el tema, ya que es un buen estilo para garantizar la seguridad en APIs.

      Por otro lado, con respecto a nuestra aplicación, he dejado bastante simple el tema de la autenticación ya que ese no es el objetivo del articulo, a pesar de esto si un usuario no cuenta con el password correcto, sera muy dificil que pueda entrar al sistema para leer las conversaciones.

      Responder
      1. Nelson

        Manuel buenas tardes, necesito de ayuda sobre nodejs, socket.io. Veo que a través de tus respuestas posees grandes conocimientos. Por favor soy novato en muchas cosas y necesito de una orientación en cuanto a este tema. mi correo es ngomezleal@gmail.com.Por favor escríbeme para así basado en tu valioso tiempo, puedas ayudarme.

        A la espera de tu valiosa respuesta, se despide,
        Nelson Gomez

        Responder
  5. Nelson

    Muy buenas tardes Giovanni, amigo necesito de su GRAN AYUDA sobre nodejs, socket.io. te he escrito varias veces por facebook por favor veirifica tan pronto puedas los mensajes.

    A la espera de tu valiosa respuesta, se despide,

    Nelson Gomez

    Responder
  6. Pingback: Parte 3 | Creando un sistema de chat sobre NodeJS con Socket.IO, ExpressJS, MongoDB, Foundation y Openshift | Linea por linea

  7. chano

    body-parser deprecated bodyParser: use individual json/urlencoded middlewares se
    rver.js:18:9
    body-parser deprecated undefined extended: provide extended option node_modules\
    body-parser\index.js:85:29

    porque me sale este error en la consola?

    Responder
  8. nodejs

    hola todavia iba bien en la primera parte del codigo muy explicado en la segunda parte he tengo varios problema ayudas por favor. inciaba con node server.js salian muchos errores y vi en el codigo de server.js tenia una variable que no habia instalodo es la siguiente var bodyParser = require(‘body-parser’); asi que la instale con npm install –body-parser no se es la forma correcta esta vez cuando intente inciar con node server.js pense que ya estaba solucionado pera salio este otro error

    body-parser deprecated bodyParser: use individual json/urlencoded middlewares se
    rver.js:18:9
    body-parser deprecated undefined extended: provide extended option node_modules\
    body-parser\index.js:85:29

    leyendo en los comentarios vi que ya lo habias respodido y lo modifique en la linea 18 con este
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    pero aun persisten estos 3 o 4 errores y no se como solucionarlos??

    C:\Users\nodejs>cd C:\Users\malware\Desktop\chatSS

    C:\Users\nodejs\Desktop\chatSS>node server.js
    { [Error: Cannot find module ‘../build/Release/bson’] code: ‘MODULE_NOT_FOUND’ }

    js-bson: Failed to load c++ bson extension, using pure JS version
    { [Error: Cannot find module ‘../build/Release/bson’] code: ‘MODULE_NOT_FOUND’ }

    js-bson: Failed to load c++ bson extension, using pure JS version
    { [Error: Cannot find module ‘../build/Release/bson’] code: ‘MODULE_NOT_FOUND’ }

    js-bson: Failed to load c++ bson extension, using pure JS version
    { [Error: Cannot find module ‘../build/Release/bson’] code: ‘MODULE_NOT_FOUND’ }

    js-bson: Failed to load c++ bson extension, using pure JS version

    C:\Users\nodejs\Desktop\chatSS>

    Responder
  9. pepelucho

    hola tengo este problema
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    estoy intentando realizarlo con mysql y me sale este problema , alguien me podria dar solucionar

    Responder
    1. diganmegiovanni Autor

      Que tal @pepelucho
      Asegurate de tener instalado el modulo body-parser de nodejs.
      Puedes instalarlo desde la raiz de tu proyecto con «npm install body-parser». Si esto no funciona por favor comentanos mas detalles sobre el error que te arroja la consolaal ejecutar el proyecto.

      Responder
  10. Pingback: Parte 4 | Creando un sistema de chat sobre NodeJS con Socket.IO, ExpressJS, MongoDB, Foundation y Openshift | Linea por linea

  11. Pingback: Parte 5 | Creando un sistema de chat sobre NodeJS con Socket.IO, ExpressJS, MongoDB, Foundation y Openshift | Linea por linea

  12. Denison Ceciliano

    Hola Giovanni, vieras que tome todos los elementos que diste para el ejemplo y puse a correr el servidor, pero lo ejecuto y no hace nada, inmediatamente me cuelga, pero no me da mensaje de error ni ningun tipo de advertencia, ayudaaaa!!

    Responder
    1. DiganmeGiovanni Autor

      Hola Denison. Quisiera preguntarte, ¿Ejecutas el servidor sobre Linux o Windows?, ¿MongoDB esta funcionando bien?, ¿Los puertos que estas utilizando en tu aplicación estan disponibles?, ¿Puedes ejecutar otras aplicaciones NodeJS o el problema es solo con el sistema de chat?. Por favor responde algunas de las preguntas para intentar averiguar cual es el problema.

      Responder
  13. Oscar

    Hola tengo el problema siguiente. Cuando ejecuto la app desde el cmd (node server.js) no se inicia el servidor, vuelve a la carpeta para escribir de nuevo un comando. Que puede Ser? Muchas gracias

    Responder
  14. oscar

    No sale ningún mensaje. Solo tarda dos o tres segundos y me vuelve a posicionar en la carpeta del proyecto. Si puedo ejecutar otros proyectos normalmente. Tengo Windows. Gracias

    Responder
  15. keven

    Buenas noches instale mongo db correctamente , sin embargo cuando registro un usuario: me sale esto en la consola del server:
    D:\Chat>node index.js
    listening on *:3000
    New user connected
    Nuevo usuario creado
    D:\Chat\node_modules\mongodb\node_modules\mongodb-core\lib\topologies\server.js:757
    catch(err) { process.nextTick(function() { throw err}); }
    ^

    TypeError: Cannot set property ‘password’ of undefined
    at D:\Chat\index.js:55:31
    at D:\Chat\dao\UserDAO.js:48:28
    at D:\Chat\node_modules\mongodb\lib\collection.js:449:5
    at D:\Chat\node_modules\mongodb\lib\collection.js:593:5
    at executeCommands (D:\Chat\node_modules\mongodb\lib\bulk\ordered.js:389:12)
    at resultHandler (D:\Chat\node_modules\mongodb\lib\bulk\ordered.js:416:5)
    at D:\Chat\node_modules\mongodb\node_modules\mongodb-core\lib\topologies\server.js:756:13

    at Callbacks.emit (D:\Chat\node_modules\mongodb\node_modules\mongodb-core\lib\topologies\server.js:95:3)
    at null.messageHandler (D:\Chat\node_modules\mongodb\node_modules\mongodb-core\lib\topologies\server.js:243:23)
    at Socket.<anonymous> (D:\Chat\node_modules\mongodb\node_modules\mongodb-core\lib\connection\connection.js:262:22)
    

    No lo logro encontrar la solucion me podrias ayudar por favor 🙂

    Responder
    1. DiganmeGiovanni Autor

      Hola Kevin. En la linea 55 de tu archivo ‘index.js’. Se produce el error: ‘Cannot set property ‘password’ of undefined. Tratas de asignarle un valor a la propiedad password de un objeto que no existe. ¿Estas seguro de que la variable existe y estas usando el mismo nombre? Si es asi, ¿Podrias mostrarnos la linea 55 de tu código (index.js) asi como 10 lineas hacia arriba y 10 lineas hacia abajo para poder investigar mas?

      Responder
      1. Alexis Reyes

        yo, como lo comenté más arriba, en el código del archivo server.js, en la linea 54, está escrito esto:
        user.password = null;

        Si nos damos cuenta qué es lo que está haciendo el algoritmo,

        usersDAO.addUser(username, password, email, function (err, user) {
          if (err) {
            res.send({ 'error': true, 'err': err});
          }
          else {
            user.password = null;
            res.send({ 'error': false, 'user': user });
          }
        });
        

        });

        aquí se está haciendo manejo de algún error que haya provocado la conexión para agregar el usuario, es por esto que lo mas recomendable es comentar la linea 54 o bien borrarla. Con esto me funcionó.
        Aprovechando, tengo un problema con foundation, ya que no me aparece correctamente el login-modal (de hecho, tube que sacar ‘reveal’ de $(‘#login-modal’).foundation(‘reveal’, ‘close’); dejándolo en $(‘#login-modal’).foundation(‘close’);, para que así me apareciera el campo, pero con esto el login se muestra pero deshabitado, solo puedo acceder a ese login presionando el «tab» para llegar a los campos.

        saludos.

        Responder
  16. keven

    Si esta es gracias :

    /* Colección ‘users’ en la base de datos */
    var users = db.collection(‘users’);

    this.addUser = function (username, password, email, callback) {
    
        // Verificamos que el usuario no exista aun
        users.findOne({'_id': username}, function (err, user) {
            if (err) throw err;
    
            if (user) {
                var user_yet_exist_error = new Error('User yet exists');
                user_yet_exist_error.msg = "User yet exists"
                return callback(user_yet_exist_error, null);
            }
            else {
    
                // Generate password hash
                var salt = bcrypt.genSaltSync();
                var password_hash = bcrypt.hashSync(password, salt);
    
                // Crear el nuevo 'user' con los parametros dados.
                var user = {'_id': username, 'password': password_hash, 'email': email};
    
                // Insertar el nuevo usuario en la base de datos
                users.insert(user, function (err, result) {
                    if (err) return callback(err, null);
    
                    console.log('Nuevo usuario creado');
                    return callback(null, result[0]);
                });
            }
        });
    }
    
    this.validateLogin = function (username, password, callback) {
    

    /LINEA 55/
    users.findOne({‘_id’: username}, function (err, user) {
    if (err) return callback(err, null);

            if (user) {
                if (bcrypt.compareSync(password, user.password)) {
                    callback(null, user);
                }
                else {
                    var invalid_password_error = new Error('Invalid password');
                    invalid_password_error.msg = 'Invalid password';
                    callback(invalid_password_error, null);
                }
            }
            else {
                var no_such_user_error = new Error('User not found');
                no_such_user_error.msg = 'User not found';
                callback(no_such_user_error, null);
            }
        });
    }
    

    }

    module.exports.UserDAO = UserDAO;

    Responder
  17. hmplug

    La respuesta es:
    en la linea 49
    // Insertar el nuevo usuario en la base de datos
    users.insert(user, function (err, result) {
    if (err) return callback(err, null);

    console.log('Nuevo usuario creado');
     return callback(null, result[0]);
    

    });

    El codigo quedaria asi:
    // Insertar el nuevo usuario en la base de datos
    users.insert(user, function (err, result) {
    if (err) return callback(err, null);

    console.log('Nuevo usuario creado');
     return callback(null, result);
    

    });

    Ya que al llamar a result[0] no estamos hablando al objeto si no al objeto en la posicion 0 por lo mismo si deseamos modificar el valor no vamos a poder

    Saludos

    Responder
  18. dmedina2150

    Buenas quien me puede apoyar con este error:

    module.js:442
    throw err;
    ^

    Error: Cannot find module ‘body-parser’
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at Object. (C:\DAJAN\Organizando\Proyectos\ChatVirtual\chatPrueba
    \server.js:8:19)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)

    Ya revise todos los comentarios y vi que habia que modificar el body-parser de esta manera:

    app.use (bodyParser.urlencoded ({
    extended: true
    }));
    app.use (bodyParser.json());

    Pero sigue apareciendo el error.

    Responder
      1. Edisson

        Me partí el coco una semana con este problema luego otra semana Body-parser en des uso pero con solo encender mongodb funciono perfecto sin cambiar nada en body-parser es necesario cambiar esas lineas de código.

        Responder
  19. superjoanji

    Hola que tal me esta encantado el articulo pero me sucede un problema, es el mismo problema de Oscar el de que en la terminal cuando pongo node server.js tarda 3 segundos, no sale nada y no arranca (en teoría tendría que salir el listening *:3000). En la primera parte no tuve ningún problema. He mirado todo sobre la base de datos Mongodb, lo he revisado y la base de datos en teoría la tengo instalada, en los pre-requisitos que pedías en la primera parte, como en esta parte con npm install –save mongodb. No se que hacer, y me molesta no poder seguir xD, pero bueno espero tu respuesta. Un saludo!

    Responder
    1. DiganmeGiovanni Autor

      Hola superjoanji. En que sistema operativo estas? A que te refieres cuando dices «en teoria la tengo instalada». Puedes verificar tu instalación a traves del cliente de mongo para ver si puedes conectarte, también el comando ‘npm –save mongodb’ debes ejecutarlo en la raiz de tu proyecto para instalar el modulo que permite conectar desde nodejs a mongodb. Puedes verificar esto y decirnos como te va para poder ayudarte. Saludos y que bueno que estes disfrutando el artículo, es para aprender.

      Responder
  20. giss66

    Hola disculpa me sale este error, me podrías ayudar.?

    SyntaxError: Invalid or unexpected token
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:542:28)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

    Responder

Replica a diganmegiovanni Cancelar la respuesta