3

Railsを使用してdevise/cancanで基本認証/承認を取得しようとしています。Ryan Bのスクリーンキャストやその他の例のような役割を使用するのではなく、基本的なことをしようとしています。

1-ユーザーはログインできます
2-ユーザーは自分の記事のみを編集/破棄できます(役割はありません。ログインして新しい記事を作成して自分の記事を編集/破棄できるか、ログアウトして自分だけができます記事を見てログイン)

私は最初の部分にdeviseを使用していて、それはうまく機能していますが、2番目の部分をCanCanで機能させることができません。ログインすると、記事の編集リンクと破棄リンクは表示されません。また、記事が別のユーザーのものであっても、直接URL(/ articles / 3 / editなど)で許可されます。

ability.rb

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

記事を一覧表示する部分ビュー_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>

この設定では、ビュー内の編集/破棄リンクは、ブランケットがない限り表示されずcan :manage, :allcan :manage, Article機能しません。上で述べたように、記事の編集に直接ディープリンクすることができ、それが許可されるため、実際のアクションを制限することもありません。

ここで何が間違っているのかわかりません。助けを得るのは素晴らしいことです。

よろしくお願いします
ジェイソン

4

3 に答える 3

2

私はなんとか問題を解決することができました。私は自分の環境をリセットし(rvm-gemsとgemsetsをresintalled-ruby1.9.2とrails3.0.0)、コードの一部と私が取り除いていたすべての問題を変更しました(リダイレクトループ、ログに基づいて変更されない要素の表示で、許可されていないコントローラーのアクションは引き続き許可されます)。ability.rb、、、articles_controller.rbを貼り付けまし_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

今は理にかなっていると思いますが、現在のユーザーの記事は更新と削除のみが想定されていたため、CRUD要素を具体的に分割しました。

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動作しますが、私は特定の承認を入れました!下部に追加のアクションがあるため、各コントローラーアクションの行。両方とも動作するようになりました。

@article to articleへの参照を更新して、リスト内の現在の記事を参照します_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>

すべてが現在機能しています。ここで助けてくれてありがとう、そしてうまくいけば、これは他の誰かがこの問題に遭遇した場合に役立つでしょう。

于 2010-09-30T04:23:30.520 に答える
1

ユーザーIDを照合するための条件が正しくありません。そのはず:

can :manage, Article, :user_id => user.id

チェックする属性は、チェックする値にマップされます。

user.nil?また、初期化したばかりであるためにnilになれない場合をチェックしています。(おそらく、たくさんのことを試したことの症状です!)

于 2010-09-28T09:02:13.890 に答える
0

あなたのキャッチは機能しますか?can:manage、:all行のコメントを外すと、ユーザーは自分の投稿を(もちろん他のすべての人と一緒に)編集できるようになりますか?

変更してみましたか、:manage、Article、:user_id == user to

can :manage, Article do |article|
 article.try(:user) == user

何か間違ったことをしているのではないかと思いますが、ロードを許可して動作させることはできませんでした。誰かがURLに直接アクセスできないようにするには、記事の編集アクションでこれを追加してみてください

 unauthorized! if cannot? :edit, @article
于 2010-09-28T18:10:11.497 に答える