class Controlist::Interceptor
Constants
- PROXY_CLASSES
Public Class Methods
build_proxy(target)
click to toggle source
used by hook_attribute
# File lib/controlist/interceptor.rb, line 16 def build_proxy(target) klass = target.class proxy_class = (PROXY_CLASSES[klass] ||= create_value_object_proxy_class klass) proxy_class.new target end
hook()
click to toggle source
# File lib/controlist/interceptor.rb, line 9 def hook hook_read hook_persistence hook_attribute end
Private Class Methods
_select!(*value)
click to toggle source
# File lib/controlist/interceptor.rb, line 97 def _select!(*value) self.select_values += Array.wrap(value) end
build_arel_with_controlist()
click to toggle source
# File lib/controlist/interceptor.rb, line 136 def build_arel_with_controlist permission_manager = Controlist.permission_manager if permission_manager.skip? build_arel_without_controlist else self.real_build_arel_with_controlist end end
create_value_object_proxy_class(klass)
click to toggle source
# File lib/controlist/interceptor.rb, line 148 def create_value_object_proxy_class(klass) attributes = klass.columns.map(&:name) attributes.delete klass.primary_key proxy_class = Class.new code_block = "" attributes.each do |attribute| code_block += %Q{ def #{attribute} @target.#{attribute} rescue nil end } end proxy_class.class_eval %Q{ def initialize(target) @target = target end def [](attribute) @target[attribute] rescue nil end #{code_block} } proxy_class end
enabled()
click to toggle source
# File lib/controlist/interceptor.rb, line 106 def self.enabled false end
enabled?()
click to toggle source
# File lib/controlist/interceptor.rb, line 103 def self.enabled? false end
find(*args)
click to toggle source
Bypass find_by_statement_cache, otherwise will use cached sql which may has wrong permissions
Calls superclass method
# File lib/controlist/interceptor.rb, line 113 def find(*args) super end
find_by(*args)
click to toggle source
Calls superclass method
# File lib/controlist/interceptor.rb, line 116 def find_by(*args) super end
hook_attribute()
click to toggle source
# File lib/controlist/interceptor.rb, line 24 def hook_attribute ActiveRecord::Persistence.class_eval %Q{ def #{Controlist.attribute_proxy}(attr) self.#{Controlist.value_object_proxy}[attr] end def #{Controlist.value_object_proxy} @#{Controlist.value_object_proxy} ||= Controlist::Interceptor.build_proxy self end } end
hook_persistence()
click to toggle source
# File lib/controlist/interceptor.rb, line 36 def hook_persistence if Controlist.is_activerecord3? settings = { create: :create, update: :update, delete: [:delete, :destroy] } else settings = { create: :_create_record, update: :_update_record, delete: [:delete, :destroy] } end settings.each do |operation, methods| Array(methods).each do |method| ActiveRecord::Persistence.module_eval %Q{ def #{method}_with_controlist(*args) permission_manager = Controlist.permission_manager unless permission_manager.skip? permission_package = permission_manager.get_permission_package permissions = permission_package.list_#{operation}[self.class] if permission_package if permissions.blank? raise NoPermissionError else passed = false matched_permission = nil permissions.each do |permission| if permission.match_for_persistence(self, Controlist::Permission::#{operation.upcase}) Controlist.debug{"Controlist matched to \#{permission.is_allowed ? 'allow' : 'forbid'} \#{permission.inspect}"} if permission.is_allowed passed = true end matched_permission = permission break end end if passed Controlist.debug{"Controlist #{operation} checked: PASSED"} else Controlist.debug{"Controlist #{operation} checked: FORBIDDEN"} if matched_permission.nil? raise NoPermissionError else raise PermissionForbidden.new "Forbidden by permission", matched_permission end end end end # Avoid effect fetching arel in original update method Controlist.skip { #{method}_without_controlist(*args) } end alias_method_chain :#{method}, :controlist unless method_defined? :#{method}_without_controlist } end end end
hook_read()
click to toggle source
# File lib/controlist/interceptor.rb, line 94 def hook_read if Controlist.is_activerecord3? ActiveRecord::QueryMethods.module_eval do def _select!(*value) self.select_values += Array.wrap(value) end end #Avoid id based cache ActiveRecord::IdentityMap.module_eval do def self.enabled? false end def self.enabled false end end else ActiveRecord::Core::ClassMethods.module_eval do #Bypass find_by_statement_cache, otherwise will use cached sql which may has wrong permissions def find(*args) super end def find_by(*args) super end end end ActiveRecord::Relation.class_eval do def real_build_arel_with_controlist relation = self permission_manager = Controlist.permission_manager permission_package = permission_manager.get_permission_package permissions = permission_package.list_read[@klass] if permission_package if permissions.blank? relation = self.where("1 != 1") else permissions.each do |permission| relation = permission.handle_for_read relation end end relation.send(:build_arel_without_controlist) end def build_arel_with_controlist permission_manager = Controlist.permission_manager if permission_manager.skip? build_arel_without_controlist else self.real_build_arel_with_controlist end end alias_method_chain :build_arel, :controlist unless method_defined? :build_arel_without_controlist end end
real_build_arel_with_controlist()
click to toggle source
# File lib/controlist/interceptor.rb, line 122 def real_build_arel_with_controlist relation = self permission_manager = Controlist.permission_manager permission_package = permission_manager.get_permission_package permissions = permission_package.list_read[@klass] if permission_package if permissions.blank? relation = self.where("1 != 1") else permissions.each do |permission| relation = permission.handle_for_read relation end end relation.send(:build_arel_without_controlist) end