Autorización de acciones

¡Entra CanCan!

CanCanCan es el estándar para desarrollar sistemas que requieren autorización en el mundo de RoR, es una gema bastante popular y sin duda muy útil. Comenzaremos con instalarla, como es usual, abre Gemfile y añadela:

# Gemfile
gem 'cancancan', '~> 1.10'

A continuación, corre el comando bundle:

$ bundle

Ahora que tenemos CanCan instalada, debemos generar una clase “Ability” usando CanCan, por lo tanto desde tu terminal escribe:

$ rails g cancan:ability

Un nuevo archivo se abra creado en tu directorio de modelos, ábrelo y haremos los primeros cambios:

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.has_role? :admin
      can :manage, :all
    else
      can :read, :all
      can :create, :all
    end

    can :update, Fact do |fact|
      fact.user == user
    end

    can :destroy, Fact do |fact|
      fact.user == user
    end
  end
end

Puede verse un poco aterrador pero esto es lo que esta sucediendo:

  1. Si el usuario tiene el rol de admin, puede manejar todos los recursos a su antojo (crear, editar, eliminar…). Como podrás darte cuenta aún no tenemos roles, ¡lo configuraremos en un momento!
  2. Si el mismo usuario que esta logeado es el que creo un Fact, puede editarlo o eliminarlo, no sería divertido que otras personas eliminaran tus Facts sin tu consentimiento.

Necesitamos usar CanCan en nuestro controlador, por lo tanto ábrelo y añade la linea:

# facts_controller.rb
load_and_authorize_resource :except => [:index, :show]

Esto viene de la documentación de CanCan, lo que hacemos es verificar si el usuario tiene los privilegios para hacer cualquier cosa excepto en los métodos Index y Show (todos pueden ver los facts).

Como tenemos todo hasta ahora, si los usuarios visitan una acción que no pueden realizar les aparecerá un error muy grande de Rails diciendoles que no pueden hacer eso, buscamos redirigirlos al index de nuestra página y mostrarles el error en su lugar.

# application_controller.rb
rescue_from CanCan::AccessDenied do |exception|
  redirect_to root_path, :alert => exception.message
end

Ahora solo falta validar quienes pueden ver los botones para editar o eliminar un fact. Esto se realiza de la siguiente forma:

<% if can? :METODO, @MODELO %>
  ...
<% end %>

Por lo tanto nuestras dos acciones (editar y eliminar) quedarían así:

<% if can? :update, @fact %>
  <%= link_to "Edit fact", edit_fact_path(@fact), class: "ui teal small button" %>
<% end %>

<% if can? :destroy, @fact %>
  <%= link_to "Delete", edit_fact_path(@fact), method: :delete, data: {confirm: "Are you sure?"}, class: "ui red small button" %>
<% end %>

Finalmente nuestra vista quedaría así:

Roles utilizando Rolify

Como te podrás haber dado cuenta ya, en Ruby existe una gema para casi todo lo que se te ocurra, el caso de roles no es una excepción. Usaremos Rolify para administrar nuestros roles.

Instala la gema como es usual, en Gemfile añadela y luego corre bundle:

# Gemfile
gem "rolify"

Terminal:

$ bundle

Ahora, debemos generar el rol de usuario:

$ rails g rolify Role User

Corremos migraciones:

$ rails db:migrate

Ahora en nuestro modelo de Facts añade:

resourcify

Ahora en nuestra terminal dirigirte al directorio donde tienes el proyecto y abre la consola con:

$ rails c

Finalmente, si tienes una cuenta creada usa su id para darte el rol de administrador:

user = User.find(1)
user.add_role :admin

¡Todo debería estar funcionando ahora! En el próximo artículo crearemos los comentarios.