开发者

Rails 3 & cancan: User should not be allowed to edit record but is able to?

开发者 https://www.devze.com 2023-02-23 01:21 出处:网络
I am trying to implement specific object (row) authorisation using cancan, I want it to work in a way that a user can only make a change(update/edit) to a Record if he/she has the role for that specif

I am trying to implement specific object (row) authorisation using cancan, I want it to work in a way that a user can only make a change(update/edit) to a Record if he/she has the role for that specific Record. after consulting the cancan docs I tried doing the following:

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

The can_edit method takes in a Record object and ensures that a User has the role necessary to make a change to it by returning true or false. this method is tested and works correctly so the problem seems to be with the CanCan code because when i try editing a Record that the user dosen开发者_运维问答t hold the role for it still allows me to make changes to the Record, anyone know why this wont work?

If you require any further information please let me know through a comment.

Thank You


Are you authorizing the resource in the controller?

you should have load_and_authorize_resource in your controller

or

def edit
    @critical_process = CriticalProcess.find(params[:id])
    #this here is what you use
    authorize! :edit, @critical_process
  end 

in your edit method inside the critical process controller.


I personally prefer to keep this logic completely separate from models so that I don't have to dig into model code to find authorization issues. In other words, user.can_edit checks for authorization which is what the ability file is supposed to be in charge of. Shouldn't matter though... in this case I think you might have a problem inside the can_edit method. I have used code that looks nearly identical to yours without problems many times like this:

can :manage, Record do |record|
  user.has_role?(:record_manager)
end

I suggest including your code for can_edit or use the debugger to see what value gets returned from can_edit.


I think the problem comes from the way you query for the records that are supposed to have the user as an editor.

I copy/pasted your code and built the other associations from scratch. And testing it in the console it works as expected when I use it:

>> u = User.last
>> a = Ability.new(u)
>> a.can :edit, Role.last
false

The only thing I changed is the query for the records: it seemed to look for a record that owns the role (your Role has a record_id) but then looks for the same key under cp_secondary_id.

I think something is wrong in your query, but what depends on your schema and associations:

roles_as_editor.collect{ |x| Record.where(:cp_secondary_id => x.record_id) }.flatten.uniq

as I understood your code we are traversing associations like this:

User=>Assignment<=Role(boolean edit flag)<=Record
0

精彩评论

暂无评论...
验证码 换一张
取 消