Crear un sistema de gestión de usuarios es una de las tareas principales al empezar a desarrolalar casi cualquier tipo de proyecto. Hacerlo desde cero con un lenguaje puede llegar a ser un poco complicado. Y hacerlo desde cero en un framework también puede llegar a ser engorroso. En
Ruby on Rails es muy fácil hacerlo utilizando una gema llamada
Pundit.
Pundit proporciona a Rails una estructura de
manejo de usuarios orientada a objetos bastante sencilla de entender y de usar.
Instalación
Para instalar Pundit en un proyecto que ya tengamos, es necesario agregarlo a nuestro
Gemfile:
[ruby]gem "pundit"[/ruby]
Después, corremos
bundle install. Y luego incluimos Pundit en
application_controller.rb
[ruby]class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery
end[/ruby]
Bien, ahora estamos listos para empezar.
Roles
Supongamos que en nuestra aplicación tenemos un modelo llamado
User:, donde están nuestros usuarios. Si queremos definir roles como
admin, user,
moderador, etc; en nuestro modelo tendremos algo así:
[ruby]class User < ActiveRecord::Base
has_many :articles
enum role: [:admin, :user, :moderator]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :slave
end
end[/ruby]
Con la segunda línea definimos los roles que existirán. Estos se guardarán en la base de datos como
int. Luego, decimos que se establezca un rol por defecto a cada nuevo usuario; que, en este caso será
moderator. Una vez teniendo esto, podemos saber el rol de cada usuario con los métodos:
admin?,
user? y
moderator?; que retornarán
true cuando el usuario corresponda a ese rol.
Policies
Pundit establece los permisos (o autorización) a través de
Policies (políticas). Estas son clases que deberíamos colocar en
app/policies.Un Policy debe verse algo así:
[ruby] class ArticlePolicy
attr_reader :user, :article
def initialize(user, article)
@user = user
@post = post
end
def update?
user.admin? or article.user == user
end
end[/ruby]
Para entender esto debemos saber que Pundit asume que para un
ArticlePolicy existe un modelo
Article. En el método
initialize recibimos dos argumentos; el primero es un usuario, que será
current_user (este objeto nos lo proporciona la gema Devise), y el segundo es aquello en lo que quieres revisar los permisos del usuario, en este caso, un artículo.
Después tenemos un método
update?, que retornará verdadero sólo si el usuario es un administrador o el artículo es suyo.
Pundit nos ofrece también un generador que nos dará algunas bases útiles para nuestros Policies:
[ruby]rails g pundit:install[/ruby]
Creará las carpetas para los Policies y pondrá un ApplicationPolicy, del que podemos heredar para no reescribir algunas cosas en todos los Policies.
Usando los Policies
Ahora, para usar nuestro Policy en el controlador que autorizará al usuario, lo haríamos con authorize :
[ruby]def update
@article = Article.find(params[:id])
authorize @article
if @article.update(article_params)
redirect_to @article
else
render :edit
end
end[/ruby]
Authorize buscará en ArticlePolicy un método llamado update? para hacer la verificación con el usuario actual. Si por alguna razón queremos que llame a otro método; por ejemplo, cuando los permisos son iguales en dos métodos, podemos mandar el nombre de este como segundo parámetro:
[ruby]def publish
@article = Article.find(params[:id])
authorize @article, :update?
@article.publish!
redirect_to @article
end[/ruby]
Si quieres conocer aprender en vivo todo sobre esta gema de Ruby on Rails, no te pierdas la clase BONUS gratuita que tendremos mañana martes en
Platzi Comunidad, en los siguientes horarios:
- Colombia / Perú / Ecuador / México: 4:00 p. m.
- Guatemala: 3:00 p. m.
- España: 11:00 p. m.
- Argentina / Chile / Uruguay: 6:00 p. m.
- Bolivia: 5:00 p. m.
- Venezuela: 4:30 p. m.