2013-08-28 62 views
0

我正在使用CanCan开发Rails应用程序,授权。该应用程序有数据库模型User和PositionGameStat。 PositionGameStat有一个user_id的外键。 position_game_stat的索引页面显示了用户提交的统计信息列表,每个统计信息都有一个编辑按钮。目前它容易注射(.../position_game_stats/130 /编辑)CanCan授权问题 - 作者编辑Post

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

换句话说,如果有人试图注入的网址.../position_game_stats/129 /编辑,他们没有进入这些统计数据,这将被拒绝访问下面是我的代码。

我的代码: 应用程序/控制器/ 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 

任何建议都欢迎和好评。

UPDATE:每陈会毅的建议 为似乎是与此代码至少在某种程度上更接近: 能力

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仍然可以访问,即使它是由不同的用户创建的。

有什么建议吗?

+0

为什么你在给它赋值之前授权'@ position_game_stat'?你遇到的问题是什么? – deefour

+0

我遇到的问题是授权正在停止用户编辑position_game_stat。我为'用户'工作,所以你无法注入一个不同的用户值到params中,但现在我正在使用外键,并且在使用position_game_stat模型时遇到了问题。 – lando2319

回答

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 

谢谢两位陈会毅和Steakchaser您的建议,这是足以让我去。无论出于何种原因,current_user在Ability.rb中都不起作用。

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真正执行像@position_game_stat = PositionGameStat.find(params[:id])这样的事情。如果你不希望这种行为,你可以这样进行手动授权:

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

最后指惨惨文档的这一部分获取更多详情:https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks

+0

收到错误未定义的方法'include?'对于# lando2319

+0

您可以将load_and_authorize_resource放在控制器def的顶部;在采取任何行动之前? – steakchaser

+0

我试过了,并在索引页面上得到了相同的错误。 – lando2319

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

完成。

更新

好吧,我看到的问题。此行错误

authorize! :manage, @position_game_stat 

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

authorize! :manage, PositionGameStat 
+0

不幸的是,这对我不起作用,CanCan仍然拒绝访问。 – lando2319

+0

@ lando2319,你有'current_user'方法吗?来自Devise或你自己的。 –

+0

是从设计。它在应用程序的其他地方使用 – lando2319