no CanCan que muestra elementos de la vista autorizados
-
26-09-2019 - |
Pregunta
Estoy tratando de conseguir un poco de autenticación / autorización básica con legado / cancán con rieles. En lugar de utilizar funciones como screencast de Ryan B y otros ejemplos en que estoy tratando de hacer algo básico:
1 - Un usuario puede iniciar sesión en
2 - Un usuario sólo puede editar / destruir sus propios artículos (sin papeles, ya sea que estés conectado y puede crear nuevos artículos y editar / destruir su propia o si está desconectado y sólo se puede ver artículos y de inicio de sesión)
Estoy usando legado para la primera parte y que está funcionando bien, pero no puedo obtener la segunda parte de trabajo con CanCan. El la edición y destruir enlaces para los artículos no aparecen cuando está conectado y la dirección URL directa (por ejemplo / artículos / 3 / editar) todavía permite que incluso si el artículo es para otro usuario.
Mi ability.rb
es
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.nil?
can :read, :all
else
# can :manage, :all #test - with this, all the edit/destroy links appear
can :manage, Article, :user_id == user
end
end
end
articles_controller.rb
:
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show] # for Devise
load_and_authorize_resource
# GET /articles
# GET /articles.xml
def index
@articles = Article.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
@article = Article.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/1/edit
def edit
@article = Article.find(params[:id])
end
# POST /articles
# POST /articles.xml
def create
@article = Article.new(params[:article])
@article.user = current_user
respond_to do |format|
if @article.save
format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
format.xml { render :xml => articles_path, :status => :created, :location => articles_path }
else
format.html { render :action => "new" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
@article = Article.find(params[:id])
respond_to do |format|
if @article.update_attributes(params[:article])
format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
@article = Article.find(params[:id])
@article.destroy
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
end
y la vista parcial que enumera los artículos _article_list.html.erb
:
<table>
<tr>
<th>Title</th>
<th>Description</th>
<th>User</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= article.user_id %></td>
<td><%= link_to 'Show', article %></td>
<% if can? :update, @article %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<% end %>
<% if can? :destroy, @article %>
<td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
<% end%>
</tr>
<% end %>
</table>
Con esta configuración, la edición / destruir enlaces en la vista no aparecen a menos que haya un can :manage, :all
manta, can :manage, Article
aún no funciona. Como he mencionado anteriormente, tampoco es la restricción de las acciones reales como usted es capaz de profunda enlace directo a la edición de un artículo y se lo permite.
No estoy seguro de lo que estoy haciendo mal aquí. Sería muy bueno para conseguir un poco de ayuda.
Gracias de antemano
Jason
Solución
Me las arreglé para resolver mi problema. Cómo reinicio mi entorno (RVM - resintalled las gemas y gemsets - rubí 1.9.2 y 3.0.0 rieles) y ha cambiado una parte del código y todos los problemas que estaba teniendo fui (bucle de redireccionamiento, elementos de la vista no cambiando en función estando conectado en, las acciones del controlador no autorizadas todavía permisibles). He pegado ability.rb
, articles_controller.rb
y _article_list.html.erb
.
ability.rb
:
class Ability
include CanCan::Ability
def initialize(user)
if user
can :create, Article
can :read, :all
can :update, Article, :user_id => user.id
can :delete, Article, :user_id => user.id
else
can :read, :all
end
end
end
supongo que tiene sentido ahora, pero debido a que sólo actualizar y borrar se supone que son para los artículos del usuario actual, Me dividir los elementos CRUD que es específica.
articles_controller.rb
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show]
# load_and_authorize_resource # RESTful automated CanCam authorization - excludes non RESTful
# GET /articles
# GET /articles.xml
def index
@articles = Article.all
authorize! :read, @articles
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
@article = Article.find(params[:id])
authorize! :read, @article
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
@article = Article.new
authorize! :create, @article
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @article }
end
end
# GET /articles/1/edit
def edit
@article = Article.find(params[:id])
authorize! :update, @article
end
# POST /articles
# POST /articles.xml
def create
@article = Article.new(params[:article])
@article.user = current_user
authorize! :create, @article
respond_to do |format|
if @article.save
format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
format.xml { render :xml => articles_path, :status => :created, :location => articles_path }
else
format.html { render :action => "new" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
@article = Article.find(params[:id])
authorize! :update, @article
respond_to do |format|
if @article.update_attributes(params[:article])
format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
@article = Article.find(params[:id])
@article.destroy
authorize! :delete, @article
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
def by
@user = User.find(params[:id])
@articles = @user.articles
authorize! :read, @articles
end
end
funciona load_and_authorize_resource
pero me he puesto específico autorizar! líneas en cada acción del controlador ya que tienen una acción adicional en la parte inferior. Tanto ahora trabajo.
Me ha actualizado la referencia a @ article al artículo para hacer referencia al artículo correspondiente de la lista de _article_list.html.rb
:
<table>
<tr>
<th>Title</th>
<th>Description</th>
<th>User</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.description %></td>
<td><%= article.user_id %></td>
<td><%= link_to 'Show', article %></td>
<% if can? :update, article %>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<% end %>
<% if can? :delete, article %>
<td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
Todo trabajando ahora. Gracias por la ayuda aquí y espero que esto le ayuda a otra persona si se encuentran con este problema.
Otros consejos
Su condición para que coincidan con un ID de usuario no está del todo bien. Debe ser:
can :manage, Article, :user_id => user.id
El atributo que desea comprobar se asigna al valor que desea comprobar en contra.
Además, está comprobando las user.nil?
cuando no puede ser cero, puesto que acaba inicializado él. (Probablemente un síntoma de tener un montón de cosas intentado!)
¿Trabaja su captura? Si se quite la lata: administrar: toda la línea será un usuario pueda editar su / su puesto (junto con todos los demás, por supuesto)
?¿Usted ha intentado cambiar, puede: administrar, artículo,: user_id == usuario
can :manage, Article do |article|
article.try(:user) == user
nunca he sido capaz de conseguir una carga de autorización a trabajar- aunque sospecho que estaba haciendo algo mal. Para evitar que alguien acceda a la dirección URL directamente, en la acción de editar su artículo, trate de añadir este
unauthorized! if cannot? :edit, @article