Cancan对嵌套属性的操作授权

时间:2013-04-13 06:14:07

标签: ruby-on-rails cancan

我有一个表单,用户可以在其中编辑用户模型和照片模型中的属性。用户模型有很多照片。

当用户提交表单时,参数将有,

:user => { :name => "blah blah",
           :photos_attributes => {
                "1" => { "id" => 10, "description" => "Some description"}
           }
         }

我在控制器上做了current_user.update_attributes(params[:user])

一切都很好。但是没有对该行动进行授权。从而留下安全漏洞。用户只需更改表单帖子中传递的id(在photo_attribtues中)即可修改其遗嘱的任何照片。

如何检查当前用户是否具有使用CanCan更改photo_attributes中指定的照片的权限(即,如果他是所有者)。

注意:photos_attributes是可选的。 params可能包含也可能不包含photos_attributes。如果params [:user]

中没有photos_attributes,解决方案不应该失败

3 个答案:

答案 0 :(得分:0)

这是一个老问题,但我遇到了同样的问题

根据cancan wiki(Defining Abilities),可以使用哈希条件,例如:

class Ability
  include CanCan::Ability

  def initialize(user)
    #...
    #other abilities
    #...

    # first we check user can only edit his profile (id: user.id)
    # then we check he can only edit his photos
    can :update, User, id: user.id, photos: { id: user.photos_ids }
  end
end

答案 1 :(得分:-1)

简短回答:CanCan无法做到这一点(可行的努力)。

答案很长:从CanCan的角度来看,您只处理恰好具有User属性的photos_attributes资源。 CanCan必须挂钩ActiveRecord的accepts_nested_attributes_for实现,以便在控制器上下文中将引用的关联范围限定为Photo.accessible_by(current_ability),而不仅仅是Photo。难看!

如果您认真对待授权并且可以在没有accepts_nested_attributes_for的额外舒适度的情况下生活,那么唯一可行的实用解决方案可能是您自己处理额外的模型(即在您的控制器代码中)。

答案 2 :(得分:-2)

我假设您将路线定义如下:

resources :users do
  resources :photos
end

如果是,那么,在ability.rb文件中,您可以执行以下操作:

def initialize(user)
  can :manage, Photos, :user_id => user.id
end

并且应该验证照片是否属于正确的用户。

请参阅:https://github.com/ryanb/cancan/wiki/Nested-Resources