class Controlist::Permission
Attributes
clause[RW]
properties is hash with property and value pair, operation READ only need keys
constrains[RW]
properties is hash with property and value pair, operation READ only need keys
is_allowed[RW]
properties is hash with property and value pair, operation READ only need keys
joins[RW]
properties is hash with property and value pair, operation READ only need keys
klass[RW]
properties is hash with property and value pair, operation READ only need keys
operations[RW]
properties is hash with property and value pair, operation READ only need keys
procs_read[RW]
properties is hash with property and value pair, operation READ only need keys
properties[RW]
properties is hash with property and value pair, operation READ only need keys
Public Class Methods
new(klass, operations=nil, is_allowed = true, constrains=nil)
click to toggle source
# File lib/controlist/permission.rb, line 13 def initialize(klass, operations=nil, is_allowed = true, constrains=nil) self.procs_read = [] self.klass = klass unless operations.nil? if operations.is_a? Array self.operations = operations else self.operations = [operations] end end self.is_allowed = is_allowed self.joins = [] if self.operations.nil? init_for_read constrains init_for_persistence constrains else init_for_read constrains if self.operations.include? Controlist::Permissions::READ if self.operations.include?(Controlist::Permissions::CREATE) || self.operations.include?(Controlist::Permissions::UPDATE) || self.operations.include?(Controlist::Permissions::DELETE) init_for_persistence constrains end end end
Public Instance Methods
apply(*properties)
click to toggle source
# File lib/controlist/permission.rb, line 38 def apply(*properties) self.properties = {id: nil} properties.each do |property_pair| if property_pair.is_a? Hash self.properties.merge! property_pair else self.properties[property_pair] = nil end end self end
handle_for_read(relation)
click to toggle source
# File lib/controlist/permission.rb, line 50 def handle_for_read(relation) relation._select!(*self.properties.keys) unless self.properties.blank? relation = relation.joins(*self.joins) if self.joins.size > 0 relation = relation.where("#{self.clause}") if self.clause unless self.procs_read.blank? self.procs_read.each do |proc| relation = proc.call(relation) end end relation end
match_constains_for_persistence(object, operation)
click to toggle source
# File lib/controlist/permission.rb, line 82 def match_constains_for_persistence(object, operation) if self.constrains.blank? constrain_matched = true else constrain_matched = self.constrains.any? do |constrain| if constrain.proc_persistence.is_a?(Proc) && constrain.proc_persistence.lambda? inner_matched = constrain.proc_persistence.call object, operation else inner_matched = false property = constrain.property value = constrain.value operator = constrain.operator if constrain.relation.nil? if object.persisted? && (changes = object.changes[property]) inner_matched = match_value(changes.first, value, operator) else inner_matched = match_value(object[property], value, operator) end else relation_object = object.send(constrain.relation) inner_matched = (relation_object && match_value(relation_object[property], value, operator)) end end inner_matched end end Controlist.debug{"Controlist #{operation} constrains checked: #{constrain_matched}"} constrain_matched end
match_for_persistence(object, operation)
click to toggle source
# File lib/controlist/permission.rb, line 62 def match_for_persistence(object, operation) properties_matched = match_properties_for_persistence object, operation properties_matched && match_constains_for_persistence(object, operation) end
match_properties_for_persistence(object, operation)
click to toggle source
# File lib/controlist/permission.rb, line 67 def match_properties_for_persistence(object, operation) return true if operation == Controlist::Permissions::DELETE || self.properties.blank? properties_matched = false changes = object.changes self.properties.each do |property, value| change = changes[property] if change && (value.nil? || Array(value).include?(change.last)) properties_matched = true break end end Controlist.debug{"Controlist #{operation} properties checked: #{properties_matched}"} properties_matched end
Private Instance Methods
append_joins(relation_name)
click to toggle source
# File lib/controlist/permission.rb, line 200 def append_joins(relation_name) reflections = self.klass.reflections # Rails 4.2 use string key, instead Rails 4.1 use symbol key relation = reflections[relation_name.to_s] || reflections[relation_name.to_sym] raise "Relation #{relation_name} Not found for class #{self.klass}!" if relation.nil? self.joins << relation_name.to_sym relation.table_name end
build_clause()
click to toggle source
# File lib/controlist/permission.rb, line 154 def build_clause clause = "" self.constrains.each do |constrain| if constrain.proc_read.is_a?(Proc) self.procs_read << constrain.proc_read next else if !constrain.clause.nil? part_clause = constrain.clause else table_name = append_joins constrain.relation if constrain.relation table_name ||= (constrain.table_name || self.klass.table_name) property = constrain.property value = constrain.value raise ArgumentError.new("property could not be nil") if property.blank? raise ArgumentError.new("value could not be nil") if value.blank? default_operator = '=' if value.is_a?(Proc) && value.lambda? Controlist.skip{ value = value.call } end if value.is_a? Array if value.first.is_a? String value = "('" + value.join("','") + "')" else value = "(" + value.join(",") + ")" end default_operator = 'in' else if value.is_a? String if value.upcase == 'NULL' default_operator = 'is' else value = "'#{value}'" end end end operator = constrain.operator || default_operator part_clause = "#{table_name}.#{property} #{operator} #{value}" end clause += " and " if clause.length > 0 clause += "(#{part_clause})" end end clause end
init_for_persistence(constrains)
click to toggle source
# File lib/controlist/permission.rb, line 114 def init_for_persistence(constrains) return if constrains.nil? if !(constrains.is_a?(Controlist::Permissions::Constrain) ||constrains.is_a?(Array)) raise ArgumentError.new("constrains has unknown type #{constrains.class}") end constrains = [constrains] if constrains.is_a? Controlist::Permissions::Constrain constrains.compact! constrains.each do |constrain| raise "Persistence operation can't use constrain clause" unless constrain.clause.blank? end self.constrains = constrains end
init_for_read(constrains)
click to toggle source
# File lib/controlist/permission.rb, line 139 def init_for_read(constrains) return if constrains.nil? case constrains when String self.clause = constrains when Array, Controlist::Permissions::Constrain constrains = [constrains] if constrains.is_a? Controlist::Permissions::Constrain self.constrains = constrains.compact self.clause = build_clause self.clause = "not (#{self.clause})" if self.is_allowed == false else raise ArgumentError.new("constrains has unknown type #{constrains.class}") end end
match_value(target, value, operator)
click to toggle source
# File lib/controlist/permission.rb, line 127 def match_value(target, value, operator) if operator.nil? if value.is_a? Array value.include? target else target == value end else target.send(operator.to_sym, value) end end