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.