tecnologiaenegocios / access_control

Access control for RoR
2 stars 1 forks source link

Parents added/removed by application code dealing with Node API #2

Open rcabralc opened 11 years ago

rcabralc commented 11 years ago

The following case doesn't work in app code without accessing Node API in the same transaction:

class Person < ActiveRecord::Base
  include AccessControl::Securable

  has_many :insurances, :autosave => true
  inherits_permissions_from :parent_records

  def parent_records
    insurances.map(&:contract).map(&:stipulator)
  end
end

class Insurance < ActiveRecord::Base
  belongs_to :person
  after_save do |record|
    AccessControl.refresh_parents_of(record.person)
  end
end

person = Person.new
person.insurances << Insurance.new(:contract => contract)
person.save! # -> will generate a database error

The insurance, when saved, will refresh the parents of the person. This breaks because all the code runs in the same transaction, thus the node of the person doesn't exist (actually it's not persisted yet), therefore cannot be added to ac_parents.

The application code can check the state of the node and skip the refresh:

class Insurance < ActiveRecord::Base
  after_save do |record|
    if AccessControl::Node(record.person).persisted?
      AccessControl.refresh_parents_of(record.person)
    end
  end
end

This works because the node will be persisted in the end of the transaction and will trigger a refresh of parents anyway. But application code should not deal with the concept of nodes. The bug/feature request is: provide a better way to handle this situation without forcing app code to access Node API.

rcabralc commented 11 years ago

Maybe AccessControl.refresh_parents_of should do nothing if the record's node is not persisted yet.