Cancan ne montrant pas autorisé affichage des éléments
-
26-09-2019 - |
Question
Je suis tenté de se faire de l'authentification de base/avec l'autorisation de concevoir/french cancan avec des Rails.Plutôt que d'utiliser des rôles comme Ryan B screencast et d'autres exemples autour de moi, je suis en train de faire quelque chose de fondamental:
1 - Un utilisateur peut se connecter
2 - Un utilisateur peut seulement modifier/détruire leurs propres articles (pas de rôles, soit vous êtes connecté et peut créer de nouveaux articles et de modifier/détruire votre propre ou vous êtes connecté (e) et vous ne pouvez voir les articles et login)
Je suis l'aide de concevoir pour la première partie et qui travaille bien, mais je ne peux pas obtenir la deuxième partie de travail avec french CanCan.Le le modifier et détruire les liens pour les articles n'apparaissent pas lorsque vous êtes connecté et que l'URL directe (par ex./articles/3/édition) permet toujours, même si l'article est destiné à un autre utilisateur.
Mon ability.rb
est
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
et la vue partielle que des listes d'articles _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>
Avec cette configuration, le modifier/détruire des liens dans la vue ne s'affichent pas moins qu'il y ait une couverture can :manage, :all
, même can :manage, Article
ne fonctionne pas.Comme je l'ai mentionné ci-dessus, ce n'est pas de restreindre les actions que vous êtes en mesure de lien profond directement à l'édition d'un article et qu'il permet.
Je ne suis pas sûr de ce que je fais mal ici.Il serait bon d'obtenir de l'aide.
Merci d'avance
Jason
La solution
J'ai réussi à résoudre mon problème.J'ai réinitialisé mon environnement (rvm - resintalled les gemmes et les gemsets - ruby 1.9.2 et les rails 3.0.0) et changé le code, et tous les problèmes que je vivais en alla (redirection en boucle, afficher des éléments qui ne changent en fonction de vous être connecté, non autorisée des actions de contrôleur encore permises).Je l'ai collé ability.rb
, articles_controller.rb
, et _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
Je suppose que cela fait sens aujourd'hui, mais parce que la mise à jour et suppression est censé être pour l'utilisateur en cours, des articles, j'ai divisé le CRUD éléments pour être précis.
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
load_and_authorize_resource
fonctionne mais j'ai mis spécifiques autoriser!lignes d'action du contrôleur que j'ai une action au fond.Les deux fonctionnent maintenant.
J'ai mis à jour la référence à @article pour l'article de référence de l'actuel article dans la liste _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>
Tout fonctionne à présent.Merci pour l'aide ici, et j'espère que cela aidera quelqu'un d'autre si ils ont ce problème.
Autres conseils
Votre condition correspondant à un id utilisateur n'est pas tout à fait droit.Il devrait être:
can :manage, Article, :user_id => user.id
L'attribut que vous souhaitez vérifier est mappé à la valeur que vous souhaitez vérifier.
Aussi, vous êtes à la vérification de user.nil?
quand il ne peut pas être nul car vous avez initialisé il.(Probablement un symptôme de l'avoir essayé beaucoup de choses!)
Est-ce que votre catch travail?Si vous supprimez le pouvez :gérer :tous ligne un utilisateur puisse éditer son post ( ainsi que tous les autres bien sûr )?
Avez-vous essayé de changer, pouvez :gérer, d'Article :user_id == utilisateur
can :manage, Article do |article|
article.try(:user) == user
Je n'ai jamais été capable de se charger d'une autorisation de travail - bien que je soupçonne que je faisais quelque chose de mal.Pour empêcher quelqu'un d'accéder à l'url directement, dans votre article de modification d'action, essayez d'ajouter ce
unauthorized! if cannot? :edit, @article