# Devise

[Devise](https://github.com/plataformatec/devise) es una gema que facilita la implementación de la autenticación en nuestras aplicaciones.

Generalmente lo que hago cuando voy a utilizar [Devise](https://github.com/plataformatec/devise) es ir a la documentación y seguir los pasos, pero los copiamos acá por referencia.

Vamos a continuar trabajando en nuestra aplicación de libros. Puedes utilizar la aplicación que has venido construyendo o clonar el proyecto y descargar la rama `step-5`:

```
$ git clone https://github.com/makeitrealcamp/books-app.git
$ cd books-app
$ git checkout step-5
```

1. El primer paso es agregar la gema al final del archivo `Gemfile`:

   ```ruby
    gem 'devise'
   ```
2. Ejecuta `bundle install` para instalarla.
3. Ejecuta el generador de [Devise](https://github.com/plataformatec/devise):

   ```
    $ rails generate devise:install
   ```
4. El siguiente paso es crear el modelo de los usuarios de la aplicación, generalmente `User`:

   ```
    $ rails generate devise User
   ```
5. Ejecuta `rails db:migrate` para correr las migraciones.

## Rutas que crea Devise

Asumiendo que el usuario es `User`, [Devise](https://github.com/plataformatec/devise) crea, entre otras, las siguientes rutas:

| Ruta                     | Nombre                  | Descripción            |
| ------------------------ | ----------------------- | ---------------------- |
| `GET /users/sign_up`     | new\_user\_registration | Formulario de registro |
| `POST /users`            |                         | Registrarse            |
| `GET /users/sign_in`     | new\_user\_session      | Formulario de login    |
| `POST /users/sign_in`    |                         | Login                  |
| `DELETE /users/sign_out` | destroy\_user\_session  | Salir                  |

Para ver el listado completo ejecuta `rails routes`. Las demás rutas son, en su mayoría, para el manejo de contraseñas (recuperar, cambiar, etc).

## Agregando los links de Devise

Para que el usuario pueda registrarse, ingresar y salir de nuestra aplicación vamos a agregar algunos links en el layout de la aplicación.

Abre `app/views/layouts/application.html.erb` y agrega lo siguiente después del `<body>`, antes de `<%= yield %>`:

```
<div>
  <% if signed_in? %>
    <%= link_to "Salir", destroy_user_session_path, method: :delete %>
  <% else %>
    <%= link_to "Registrarse", new_user_registration_path %>
    <%= link_to "Ingresar", new_user_session_path %>
  <% end %>
</div>
```

## Filtros y helpers de controlador

[Devise](https://github.com/plataformatec/devise) crea algunos métodos de ayuda y filtros para que puedas manejar la autenticación en tu aplicación.

Asumiendo que tu usuario se llama `User`, el filtro que puedes agregar sobre los controladores que quieres proteger es el siguiente:

```ruby
before_action :authenticate_user!
```

En nuestra aplicación de libros vamos a proteger todas las acciones del controlador `books` exceptuando `index` y `show` que son las que nos van a permitir listar y mostrar los detalles de un libro.

Agrega la siguiente línea dentro de la clase:

```ruby
before_action :authenticate_user!, except: [:index, :show]
```

Los métodos de ayuda a los que vas a tener acceso en los controladores y vistas son los siguientes:

| Método         | Descripción                                                            |
| -------------- | ---------------------------------------------------------------------- |
| `signed_in?`   | Retorna `true` si el usuario está autenticado, `false` de lo contrario |
| `current_user` | Retorna el usuario que está autenticado o `nil`                        |
| `user_session` | Retorna la sesión del usuario                                          |

En nuestra aplicación sólo vamos a mostrar los links de "Editar" y "Eliminar" si el usuario está autenticada. Cambia el archivo `app/views/books/index.html.erb` para que quede los links queden de la siguiente forma:

```
<td>
  <%= link_to "Mostrar", book %>
  <% if signed_in? %>
    <%= link_to "Editar", edit_book_path(book) %>
    <%= link_to "Eliminar", book, method: :delete, data: { confirm: "¿Estás seguro de eliminar este libro?" } %>
  <% end %>
</td>
```

Ahora sólo deberían aparecer los links de "Editar" y "Eliminar" si el usuario está autenticado.

## El modelo de usuario

Asumiendo que al usuario lo llamaste `User` al generarlo, el modelo que genera [Devise](https://github.com/plataformatec/devise) es el siguiente:

```ruby
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
```

Este es un modelo normal pero utiliza el método `devise` que recibe una serie de módulos que puedes activar o desactivar.

Los módulos que vienen activados son los siguientes:

| Módulo                     | Descripción                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `database_authenticatable` | Los usuarios se van a poder autenticar con un nombre de usuario y contraseña almacenado en la base de datos. |
| `registereable`            | Los usuarios van a poder registrarse, actualizar y eliminar su perfil.                                       |
| `recoverable`              | Los usuarios van a poder recuperar su contraseña                                                             |
| `rememberable`             | Habilita la opción "Recordarme" en el login                                                                  |
| `trackable`                | Habilita el seguimiento al usuario (de dónde se autenticó, cuantas veces, de qué IP, etc.)                   |
| `validatable`              | Valida el email y el password                                                                                |

## Modificando las vistas

Por defecto no vas a ver vistas ni controladores de [Devise](https://github.com/plataformatec/devise). Sin embargo, si quieres modificarlos puedes decirle a [Devise](https://github.com/plataformatec/devise) que los genere.

Para generar las vistas utiliza el siguiente comando:

```
$ rails generate devise:views
```

Para generar los controladores utiliza el siguiente comando:

```
$ rails generate devise:controllers users
```

Luego incorpora el controlador que quieras sobreescribir en routes de la siguiente manera:

```ruby
devise_for :users, :controllers => { registrations: 'users/registrations' }
```

De esta forma puedes modificar las vistas y cambiar funcionalidad de [Devise](https://github.com/plataformatec/devise).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://makeitrealcamp.gitbook.io/ruby-on-rails-5/8-devise.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
