CanCan授权问题 - 作者编辑发布

时间:2013-08-28 03:41:41

标签: ruby-on-rails devise authorization cancan

我正在使用CanCan开发Rails应用程序授权。该应用程序具有db模型User和PositionGameStat。 PositionGameStat具有user_id的外键。 position_game_stat的索引页面显示用户已提交的统计信息列表,每个统计信息都带有一个编辑按钮。目前它易受注射(... / position_game_stats / 130 / edit)

我希望用户只能编辑等于当前用户的position_game_stat条目。

换句话说,如果有人试图注入网址... / position_game_stats / 129 / edit并且他们没有输入这些统计数据,那么CanCan将拒绝访问该网址

以下是我的代码。

我的代码: 应用程序/控制器/ position_game_stats_controller.rb

class PositionGameStatsController < ApplicationController  

    before_filter :authenticate_user! 
    ...   
    def edit
      authorize! :manage, @position_game_stat 
      @position_game_stat = PositionGameStat.find(params[:id])
    end 
    ... 
  end

应用程序/模型/ ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user_id == user.id
    end  
  end 
end

任何建议都很受欢迎。

更新: 根据Billy Chan的建议似乎至少与这段代码更接近: 能力

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user == current_user
    end
  end
end

控制器

class PositionGameStatsController < ApplicationController

  before_filter :authenticate_user!

...

  def edit
    authorize! :manage, PositionGameStat
    @position_game_stat = PositionGameStat.find(params[:id])
  end
...
end

这使我更接近于它不会拒绝访问页面,但它仍然容易受到注入。例如/ position_game_stats / 137 / edit仍可访问,即使它是由其他用户创建的。

有什么建议吗?

3 个答案:

答案 0 :(得分:0)

在你的ability.rb中,你需要指定如何应用授权规则:

  can :manage, PositionGameStat, PositionGameStat.find_all_by_user_id(user.id) do |position_game_stat|
    position_game_stat.new_record? or position_game_stat.user.id == user.id
  end

在您的控制器中,您可以使用以下方式申请授权:

  load_and_authorize_resource

注意:load_and_authorize_resource actuall执行@position_game_stat = PositionGameStat.find(params[:id])之类的操作。如果您不想要这种行为,可以像这样手动执行授权:

  @position_game_stat = PositionGameStat.accessible_by(current_ability).find(params[:id])

最后,请参阅CanCan文档的这一部分以获取更多详细信息:https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks

答案 1 :(得分:0)

can :manage, PositionGameStat do |t|
  t.user == current_user
end  

完成。

更新

好的,我看到了问题。这条线错了

authorize! :manage, @position_game_stat

您仅授权此特定实例。那是错的。应该是

authorize! :manage, PositionGameStat

答案 2 :(得分:0)

最终解决方案: PositionGameStatsController.rb

    class PositionGameStatsController < ApplicationController

      before_filter :authenticate_user!

      load_and_authorize_resource

...

      def edit
        authorize! :manage, PositionGameStat
        @position_game_stat = PositionGameStat.find(params[:id])
      end
...
    end

Ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user.id == user.id
    end
  end
end

感谢Billy Chan和Steakchaser的建议,这足以让我走了。无论出于何种原因,current_user在Ability.rb中都不起作用。