我正在尝试使用cancan实现特定的对象(行)授权,我希望它以一种用户只能对Record
进行更改(更新/编辑)的方式工作特定Record
的角色。在咨询了康康文档后,我尝试了以下操作:
class Ability
include CanCan::Ability
def initialize(user)
can :manage, Record do |record|
user.can_edit(record)
end
end
end
class User
has_many :assignments
has_many :roles_as_editor, :through => :assignments, :class_name => "Role", :source => :role, :conditions => {:edit => true}
def rec_as_editor
self.roles_as_editor.collect{ |x| Record.where(:cp_secondary_id => x.record_id) }.flatten.uniq
end
def can_edit(rec)
rec_as_editor.include?(rec)
end
end
can_edit
方法接受Record
对象并确保用户具有通过返回true或false来对其进行更改所必需的角色。这个方法经过测试并且工作正常所以问题似乎与CanCan代码有关,因为当我尝试编辑一个记录时,用户有权持有它的角色仍然允许我对记录进行更改,任何人都知道为什么这不起作用?
如果您需要任何进一步的信息,请通过评论告诉我。
谢谢
答案 0 :(得分:3)
您是在授权控制器中的资源吗?
你的控制器应该有load_and_authorize_resource
或
def edit
@critical_process = CriticalProcess.find(params[:id])
#this here is what you use
authorize! :edit, @critical_process
end
在关键过程控制器内的编辑方法中。
答案 1 :(得分:1)
我个人更喜欢将此逻辑与模型完全分开,这样我就不必深入了解模型代码来查找授权问题。换句话说,user.can_edit检查授权,这是能力文件应该负责的。不管怎么样......在这种情况下我认为你可能在can_edit方法中有问题。我使用的代码看起来几乎和你的代码完全没有问题很多次:
can :manage, Record do |record|
user.has_role?(:record_manager)
end
我建议包含can_edit的代码或使用调试器查看can_edit返回的值。
答案 2 :(得分:0)
我认为问题来自于您查询应该将用户作为编辑者的记录的方式。
我复制/粘贴您的代码并从头开始构建其他关联。 并在控制台中测试它,当我使用它时它按预期工作:
>> u = User.last
>> a = Ability.new(u)
>> a.can :edit, Role.last
false
我唯一改变的是对记录的查询:它似乎寻找拥有该角色的记录(您的角色有 record_id ),但随后在cp_secondary_id下查找相同的密钥。
我认为您的查询有问题,但取决于您的架构和关联:
roles_as_editor.collect{ |x| Record.where(:cp_secondary_id => x.record_id) }.flatten.uniq
因为我理解你的代码,我们正在遍历这样的联想:
User=>Assignment<=Role(boolean edit flag)<=Record