Vamos a continuar con nuestra aplicación de red social en Meteor. Recordemos que dejamos la app funcionando puesto que ya registraba en la base de datos los mensajes que se le introducían pero aún no se mostraban ni podíamos ver de quién eran, etc…

Hoy implementaremos un sistema de autenticación, que gracias a la enorme paquetería de la que dispone el repositorio de Meteor será cuestión de minutos como vais a ver.

Hablando de ver, habréis podido comprobar que faltan pocas horas para que dé inicio el curso de Meteor de Openwebinars, os recomiendo ir reservando sitio porque esto que estamos montando en este tutorial es una pequeñez al lado del material que se impartirá.

Cuentas de Usuario

Crear una interfaz de usuario en Meteor no requerirá más de una línea de comando (retocarla para dejarla a nuestro gusto ya dependerá de la complejidad que le queramos otorgar al proyecto). Bastará con escribir la siguiente línea en una terminal situada en la carpeta de nuestro proyecto:

Meteor add accounts-ui accounts-password

Existen multitud de paqueterías referentes a la gestión de usuario, hemos elegido una de las más descargadas y sencillas aunque no menos eficaz. Ésta viene con una plantilla predefinida que podremos implementar únicamente añadiendo una llamada al archivo miTwitter.html ({{> loginButtons}}) tal y como vemos en la imagen, donde ya se muestra el cuadro de login:

captura de login y cuenta

Integrar un sistema de registro en un .html hace tiempo hubiese sido impensable, otro punto por el que Meteor se está consolidando como una de las opciones principales a la hora de elegir un framework permanente, tanto para usuarios como para empresas.

Además de esta útil (que no bonita… aunque para gustos colores…) interfaz, acabamos de integrar un sistema que registrará los usuarios en la base de datos, gestor de cuentas, autenticaciones, etc… Esto lo podemos comprobar si registramos un usuario (en mi caso he registrado el usuario con el correo electrónico Toushiro@openwebinars.net):

registro usuario

Y a continuación accedemos a la consola de MongoDB en meteor con este comando (recordamos como vimos en la anterior entrega, situados en la carpeta del proyecto):

Meteor mongo

E introducimos la siguiente búsqueda:

db.users.find()

A lo que deberíamos obtener algo parecido a lo que muestra esta imagen:

buscar en MongoDB

Personalizando el Registro

Al igual que hicimos con el tweetBox para ofrecer a nuestros usuarios un aspecto más al estilo de la tan famosa red de microblogging, podemos editar los tres ficheros que vimos en las entregas anteriores para cambiar el aspecto de estos nuevos componentes.

miTwitter.css

Con los nuevos objetos que hemos integrado, deberemos modificar ligeramente los estilos aplicados, y en mi caso este será el contenido del fichero miTwitter.css :


.tweetbox-container {
  margin: 30px;
  margin-left: 10px;
}

.tweetbox,.userBox {
  background-color: rgb(240, 247, 254);
}

.tweetbox .btnGroup {
  margin-top: 10px;
  display: flex;
  align-items: center;
}

.tweetbox .charCount {
  margin-right: 10px;
  color: gray;
}

.tweetbox .errCharCount {
  margin-right: 10px;
  color: red;
}

.user-container {
  margin-top: 30px;
  margin-left: 30px;
}

.user-container h4 {
  color: gray;
}

.user-container .fullbutton {
  width: 100%;
}

.user-container .input-sm {
  margin-bottom: 5px;
}

.user-container .login {
  margin-bottom: 15px;
}

miTwitter.html:

En este fichero haremos una llamada a una nueva plantilla que definiremos en el fichero JavaScript, y retocaremos un par de cositas para al igual que decía antes, integrar correctamente los nuevos objetos.

<template name="userManagement">

  <h4>New User?</h4>
  <div class="form-group">
    <input class="form-control input-sm" id="signup-username" placeholder="Nombre de Usuario">
    <input class="form-control input-sm" id="signup-fullname" placeholder="Apellido (Opcional)">
    <input class="form-control input-sm" id="signup-password" placeholder="Contraseña" type="password">
  </div>

  <button type="button" class="btn btn-info fullbutton" id="signup">Regístrate</button>

</template>

miTwitter.js

Añadiremos un evento para la plantilla userManagement que creará el registro de la cuenta de usuario:


Template.userManagement.events({  
  'click #signup': function() {
    var user = {
      username: $('#signup-username').val(),
      password: $('#signup-password').val(),
      profile: {
        fullname: $('#signup-fullname').val()
      }
    };

    Accounts.createUser(user, function (error) {
      if(error) alert(error);
    });
  }
});

Esta plantilla que estamos creando (userManagement) estará esperando que el usuario haga clic en el botón de registro para tomar las variables que contiene en ese momento y crear la cuenta gracias a Accounts.createUser() , un método incluido en el paquete que instalamos al inicio de este post. Además, soporta registros mediante servicios de terceros, pudiendo habilitar el registro mediante Google+, Facebook, etc…

Personalizando el Acceso

Por separado, incluiremos un módulo que permitirá a los usuarios ya registrados el acceso a sus cuentas y al que daremos forma incluyendo estos bloques en sus ficheros correspondientes:

miTwitter.html

<template name="userManagement">  
  ...

  <h4>¿Ya tienes una cuenta?</h4>
  <div class="form-group">
    <input class="form-control input-sm" id="login-username" placeholder="Nombre de Usuario">
    <input class="form-control input-sm" id="login-password" placeholder="Contraseña" type="password">
  </div>

  <button type="button" class="btn btn-info fullbutton login" id="login">Acceder</button>

</template>

miTwitter.js


Template.userManagement.events({  
  'click #login': function() {
    var username = $('#login-username').val();
    var password = $('#login-password').val();

    Meteor.loginWithPassword(username, password, function(error) {
      if(error) alert(error);
    });
  }
});

El método Meteor.loginWithpassword() intentará dar acceso al usuario mediante el nombre y contraseña que acaba de ingresar. Si la validación es correcta se le dará la bienvenida al usuario, en cambio, si esta resulta fallida se mostrará un mensaje de error en pantalla.

En ningún momento deberemos preocuparnos por los procesos de encriptación y validación, ya que vienen totalmente integrados en la paquetería instalada.

Unificando

Vamos ahora a hacer una puesta en común entre un módulo y otro, asegurándonos que el usuario que está en su cuenta tenga la posibilidad de cerrar su sesión y de que aquel que no ha iniciado sesión pueda hacerlo. Veamos entonces cómo hacer esto:

miTwitter.html

<head>
  <title>miTwitter</title>
</head>
<body>  
  <div class="row">
    <div class="col-md-4 col-sm-4">{{> userManagement}}</div>
    <div class="col-md-8 col-sm-8">{{> tweetBox}}</div>
  </div>
</body>

<template name="userManagement">  
  <div class="user-container">
    <div class="panel panel-default userBox">
      <div class="panel-body">
        {{# if currentUser}}
        <!—Mensaje de bienvenida para los usuarios logueados -->
        <p>Hola! <strong>@{{currentUser.username}}</strong>, bienvenido a tuTwitter en miTwitter!</p>

        {{else}}
        <!—módulo de acceso -->
        <h4>¿Ya tienes una cuenta?</h4>
        <div class="form-group">
          <input class="form-control input-sm" id="login-username" placeholder="Nombre de Usuario">
          <input class="form-control input-sm" id="login-password" placeholder="Contraseña" type="password">
        </div>

        <button type="button" class="btn btn-info fullbutton login" id="login">Acceder</button>


        <!—módulo de registro -->
        <h4>¿Nuevo por aquí?</h4>
        <div class="form-group">
          <input class="form-control input-sm" id="signup-username" placeholder="Nombre de Usuario">
          <input class="form-control input-sm" id="signup-fullname" placeholder="Apellido (Opcional)">
          <input class="form-control input-sm" id="signup-password" placeholder="Contraseña" type="password">
        </div>

        <button type="button" class="btn btn-info fullbutton" id="signup">Regístrate</button>
        {{/if}}

      </div>
    </div>
  </div>
</template>

Como veis el apartado {{# if currentUser}} {{else}} {{/if}} mostrará el mensaje de bienvenida si el usuario accede a su cuenta o un formulario de registro u acceso en caso de que no sea usuario registrado. Y mediante {{currentUser.username}} obtenemos el contenido de ese objeto para mostrar en el navegador pudiendo personalizar los mensajes que queramos destinar a los usuarios.

Cierre de Sesión

Vale, ya tenemos nuestros módulos de acceso y registro completos, pero puede que nuestros usuarios en algún momento quieran cerrar sus sesiones, por lo que sería muy amable por nuestra parte facilitarles esta tarea con una opción que los desconecte. Vamos con ello añadiendo estos bloques a los diferentes archivos:

miTwitter.html

<button type="button" class="btn btn-info fullbutton" id="logout">Desconectar</button>  

miTwitter.js
'click #logout': function() {  
  Meteor.logout();
}

Asignando autores a los mensajes

A no ser que queramos que esta red social sea un panel anónimo de mensajes y por aquello de satisfacer el ego de algunos usuarios a los que tanto les gusta ver su nombre en todos los rincones de internet deberíamos añadir el nombre del usuario a la base de datos relacionándolo con el mensaje que acaba de publicar.

Para esto, nos iremos al archivo miTwitter.js y añadiremos Meteor.user() a la información que se registrará en la base de datos con respecto al mensaje en cuestión. Recordemos que esta opción la pusimos como evento del tweetBox (Template.tweetBox.events({…) .

Pero resulta que los usuarios que no hayan iniciado sesión también podrán publicar mensajes, y eso podría traer a nuestros usuarios algún que otro problema, que ya conocemos a los que andan por internet… Así que añadiremos un ‘if’ con el que asegurarnos de que se trata de un usario regsitrado y logueado en el sistema, quedando el bloque de código así:


'click button': function() {
      var tweet = $('#tweetText').val();
      $('#tweetText').val("");
      Session.set('numChars', 0);
      if (Meteor.user()) {
        Tweets.insert({message: tweet, user: Meteor.user().username});
      }
    }

Y para terminar de asegurarnos, desactivaremos el botón de ‘Twittear’ si se cumple esta misma regla, que el usuario no esté registrado o logueado. Para esto sólo tenemos que añadir a la función que creamos para deshabilitar dicho botón la condición !Meteor.user() dentro de la lectura de la sesión en la que se está escribiendo el mensaje. Este bloque de código quedaría tal que así:


disableButton: function() {
      if (Session.get('numChars') <= 0 ||
          Session.get('numChars') > 140 ||
          !Meteor.user()) {
        return 'disabled';
      }
    }

Por si aún quedase algún usuario que no terminase de entender el por qué no puede publicar su mensaje, vamos a dejarle un mensaje en el botón de ‘Twittear’ para que sepa que se ha saltado el paso de registrarse o acceder a su cuenta.

Para ello nos iremos a miTwitter.html y en la plantilla de tweetBox añadiremos el siguiente código:


{{#if currentUser}}
  <button class="btn btn-info pull-right" type="button" {{disableButton}}>Twittear</button>
{{else}}
  <button class="btn btn-info pull-right" type="button" disabled>Por favor inicia sesión</button>
{{/if}}

Y con esto sólo nos faltaría comprobar en la consola de MongoDB que la información del usuario que ha publicado el mensaje se ha añadido correctamente a la entrada.


meteor:PRIMARY> db.twitts.find()
{ "_id" : "vAW33nxavMbc73rxN", "message" : "mi primer mensaje con autoría!!!", “user”: “Toushiro” }

Como vemos en este extracto de la terminal, ya tenemos registrándose los mensajes con los usuarios que los han escrito.

En breve continuamos montando la app, pero si quieres aprender más profundamente sobre meteor deberías mirar el curso de Meteor JS , donde tendréis profesionales ampliamente experimentados que os guiarán por este framework y todas sus posibilidades tanto para particulares como para empresas.