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

Était-ce utile?

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top