Tutorial de Sails.js: Creación del Modelo Usuario y Autenticación

Lo primero que vamos a hacer es crear el modelo y el controlador , para ello ejecutaremos la siguiente sentencia en la consola:
 

~/videoclub $ sails generate api user


Mediante el atributo api generamos el modelo y el controlador; Si quisiéramos crear únicamente el modelo utilizaríamos el atributo model ; Y si quisiéramos crear únicamente el controlador utilizaríamos el atributo controller .
 

Ahora, en el modelo escribiremos los siguiente:
 

      /**
        * User.js
        *
        * @description :: TODO: You might write a short summary of how this model works and what it represents here.
        * @docs        :: http://sailsjs.org/#!documentation/models
        */

        module.exports = {

          attributes: {

            name: {
              type: 'string',
              required: true
            },
            lastname: {
              type: 'string',
              required: true
            },
            email: {
              type: 'string',
              required: true,
              unique: true
            },
            encryptedPassword: {
              type: 'string'
            },

            // Este método es para evitar pasar toda la información del modelo
            // Evitamos pasar los siguientes parámetros: password, confirmation, encryptedpassword y _csrf. 
            toJSON: function() { 
              var obj = this.toObject();
              delete obj.password;
              delete obj.confirmation;
              delete obj.encryptedPassword;
              delete obj._csrf;
              return obj;
            }
          }
        };

Los atributos que permite Sails son los siguientes: string , text , integer , float , date , datetime , boolean , binary , array , json , email .
 

Además, podemos especificar si el atributo es obligatorio, único, su valor por defecto, etc. Todo esto nos permite crear un modelo de manera muy simple y nos abstrae a la hora de crearlo en la base de datos gracias a waterline .
 

Dentro del modelo podemos crear los métodos que deseemos y unos callbacks que se ejecutarán antes de ciertas acciones.
 

Callbacks on create

  • beforeValidate: fn(values, cb)
  • afterValidate: fn(values, cb)
  • beforeCreate: fn(values, cb)
  • afterCreate: fn(newlyInsertedRecord, cb)

Callbacks on update

  • beforeValidate: fn(valuesToUpdate, cb)
  • afterValidate: fn(valuesToUpdate, cb)
  • beforeUpdate: fn(valuesToUpdate, cb)
  • afterUpdate: fn(updatedRecord, cb)

Callbacks on destroy

  • beforeDestroy: fn(criteria, cb)
  • afterDestroy: fn(destroyedRecords, cb)
     

Más adelante veremos como utilizarlos.
 

Después iremos a views y crearemos la carpeta user y dentro de dicha carpeta los ficheros index.ejs :
 

      <div class="container">
      <h3>Usuarios
      <table class='table'>
          <tr>
              <th>ID
              <th>Nombre
              <th>Apellidos
              <th>Email
              <th>
              <th>
              <th>
          </tr>
          <% _.each(users, function(user) { %>
          <tr data-id="<%= user.id %>" data-model="user">
              <td><%= user.id %>
              <td><%= user.name %>
              <td><%= user.lastname %>
              <td><%= user.email %>
              <td><a href="/user/show/<%= user.id %>" class="btn btn-sm btn-primary">Show</a>
              <td><a href="/user/edit/<%= user.id %>" class="btn btn-sm btn-warning">Edit</a>
            <td><form action="/user/destroy/<%= user.id %>" method="POST"> 
                      <input type="hidden" name="_method" value="delete"/>
                      <input type="submit" class="btn btn-sm btn-danger" value="Delete"/>
                      <input type="hidden" name="_csrf" value="<%= _csrf %>" />
                  </form>
              </td>
          </tr>
          <% }) %>
      </table>
      <a href="/user/new">Crear Nuevo Usuario</a>
      </div>


Como podemos ver lo que hacemos es crear una tabla donde mostraremos la información de cada usuario creado.


Respecto al código podemos ver la siguiente línea: <% _.each(user, function(user) { %>


Lo que hace es recorrer cada uno de los usuarios (users) y llama a la funcion function(user) donde le pasa el user.id buscando dentro del modelo mediante data-id pasandole el nombre del modelo: data-model="user" .
 

        <% _.each(users, function(user) { %>
        <tr data-id="<%= user.id %>" data-model="user">
            <td><%= user.id %>
            <td><%= user.name %>
            <td><%= user.lastname %>
            <td><%= user.email %>
            <td><a href="/user/show/<%= user.id %>" class="btn btn-sm btn-primary">Show</a>
            <td><a href="/user/edit/<%= user.id %>" class="btn btn-sm btn-warning">Edit</a>
            <td><form action="/user/destroy/<%= user.id %>" method="POST"> 
                  <input type="hidden" name="_method" value="delete"/>
                  <input type="submit" class="btn btn-sm btn-danger" value="Delete"/>
                  <input type="hidden" name="_csrf" value="<%= _csrf %>" />
                </form>
              </td>
          </tr>
        <% }) %>


Y ahora el fichero new.ejs :
 

          <form action="/user/create" method="POST" class="form-signin">
            <h2 class="form-signin-heading"> Crear Usuario 
            <div class="control-group"> 
            <input type="text" class="form-control" placeholder="Nombre" name="name">
            </div>
            <div class="control-group">
                  <input type="text" class="form-control" placeholder="Apellidos" name="lastname">
                  </div>
                  <div class="control-group">
                  <input type="text" class="form-control" placeholder="Email" name="email">
                  </div>
                  <div class="control-group">
                  <input type="password" class="form-control" placeholder="Contraseña" name="password">
                  </div>
                  <div class="control-group">
                  <input type="password" class="form-control" placeholder="Repita Contraseña" name="confirmation">
                  </div>
            <br/>
                  <input type="submit" class="btn btn-lg btn-primary btn-block" value="Create User"/>
                  <input type="hidden" name="_csrf" value="<%=_csrf %>"/>
          </form>


Ahora vamos al controlador y cremos los métodos para dichas vistas. Los nombres serán los que están en el action .
 

          /**
           * UserController
           *
           * @description :: Server-side logic for managing users
           * @help        :: See http://links.sailsjs.org/docs/controllers
           */

          module.exports = {
            'new': function (req, res) {
              res.view();
            },
            index: function (req, res) {
              User.find(function foundUser (err, users) {
                if(err) return res.redirect('/user/new');
                res.view({
                  users: users
                });
              });
            },
            create: function(req, res) {
                User.create(req.params.all(), function userCreated(err, user) {
                  if (err) return res.redirect('/user/new');
                  res.redirect('/user/show/' + user.id); 
                });
              }
          };


Finalmente, accedemos al archivo routes.js y añadimos una nueva ruta para que cuando accedamos a cualquier vista de user no redireccione a 403, sino que permita renderizar las vistas. Para ello añadiremos el siguiente código debajo de la ruta raíz con una coma (,).
 

module.exports.policies = {

            // '*': true,

            'user': {
              'new': true,
              index: 'sessionAuth',
              '*': true
            }
          };


Que significa esto, pues vamos a explicar:
 

La parte comentada, // '*': true, significa que cualquier vista que se muestre tendrá todos los accesos y permisos abiertos.
 

Ahora hemos insertado 'user' que es el nombre del modelo y dentro damos los permisos para cada método del controlador. Como podemos ver para poder acceder a 'index' deberemos estar autenticados, si no lo estamos nos redireccionará la vista 'new' (dentro del metodo create: if (err) return res.redirect('/user/new'); ). sessionAuth hace referencia al fichero sessionAuth.js que está en api/policies.
 

Y para el resto de operaciones ( '*' ) tenemos todos los accesos, es decir no tenemos ninguna reestricción, como la necesidad de estar autenticados.

Las cookies nos permiten ofrecer nuestros servicios. Al utilizar nuestros servicios, aceptas el uso que hacemos de las cookies. Más Información