lib/kojac/concentric.rb in kojac-0.13.0 vs lib/kojac/concentric.rb in kojac-0.15.0

- old
+ new

@@ -31,12 +31,25 @@ # model.update(params.permit( ring_fields(:write,model) )) # end # #end +# Update: 2015-03-26 +# +# * Extracted ConcentricPolicy from Kojac +# * Concentric is now a way of creating Pundit policies based on ConcentricPolicy. It allows shorthand ring security for +# simple scenarios, then allow_filter for refinement and arbitrary complex logic to be implemented +# * Concentric works on the simple idea that there are 4 basic abilities: read, write, create and delete. +# * Read and write apply primarily to fields; create and delete apply to records. +# * Creating a record requires the ability to create the record, then normally you require the ability to write some fields. +# * In order to read a record, you need the ability to read at least one field +# * In order to write to a record, you need the ability to write at least one field +# * In order to delete a record, you need the ability to delete the record +# * With Concentric you first use the ring and +# +# implement Pundit Policy classes and methods (eg. update? show?) by querying these 4 abilities - class Concentric cattr_accessor :config def self.lookup_ring(aRingName) @@ -65,33 +78,33 @@ module Concentric::Model def self.included(aClass) aClass.cattr_accessor :rings_abilities - aClass.rings_abilities = [] # [1] => {read: [:name,:address], delete: true} + aClass.rings_abilities = {} # [1] => {read: [:name,:address], delete: true} aClass.send :extend, ClassMethods end module ClassMethods # supports different formats : - # ring :sales, :write => [:name,:address] ie. sales can write the name and address fields - # ring :sales, :read ie. sales can read this model - # ring :sales, [:read, :create, :destroy] ie. sales can read, create and destroy this model - def ring(aRing,aAbilities) + # allow :sales, :write => [:name,:address] ie. sales can write the name and address fields + # allow :sales, :read ie. sales can read this model + # allow :sales, [:read, :create, :destroy] ie. sales can read, create and destroy this model + def allow(aRing,aAbilities) #aRing.each {|r| ring(r,aAbilities)} and return if aRing.is_a? Array shouldn't need this because of ring system aRing = Concentric.lookup_ring(aRing) raise "aRing must be a number or a symbol defined in Concentric.config.ring_names" if !aRing.is_a?(Fixnum) raise "aAbilities must be a Hash" unless aAbilities.is_a? Hash # eg. :write => [:name,:address] ring_rec = self.rings_abilities[aRing] - aAbilities.each do |abilities,fields| - abilities = [abilities] unless abilities.is_a?(Array) - fields = [fields] unless fields.is_a?(Array) + aAbilities.each do |abilities, fields| + abilities = [abilities] unless abilities.is_a?(Array) + fields = [fields] unless fields.is_a?(Array) next if fields.empty? - abilities.each do |a| - a = a.to_sym + abilities.each do |a| + a = a.to_sym ring_rec ||= {} if fields==[:this] ring_rec[a] = true unless ring_rec[a].to_nil else ring_fields = ring_rec[a] @@ -104,18 +117,25 @@ end self.rings_abilities[aRing] = ring_rec end end + # deprecated + def ring(aRing,aAbilities) + allow(aRing,aAbilities) + end + # returns properties that this ring can use this ability on def permitted(aRing,aAbility) aRing = Concentric.lookup_ring(aRing) raise "aRing must be a number or a symbol defined in Concentric.config.ring_names" if !aRing.is_a?(Fixnum) return [] unless aRing and rings_abilities = self.respond_to?(:rings_abilities) && self.rings_abilities.to_nil fields = [] - aRing.upto(rings_abilities.length-1) do |i| + ring_keys = rings_abilities.keys.sort + ring_keys.each do |i| + next unless i >= aRing next unless ring_rec = rings_abilities[i] if af = ring_rec[aAbility.to_sym] next if af==true fields += af if af.is_a?(Array) end @@ -126,11 +146,11 @@ end # Query # aFields specifies fields you require to act on # This is no longer used by KojacBasePolicy because it does not observe its filters that operate on fields. It may still provide a faster check when there are no filters applied - def ring_can?(aRing,aAbility,aFields=nil) + def allowed?(aRing,aAbility,aFields=nil) if aFields pf = permitted(aRing,aAbility) if aFields.is_a? Array return (aFields - pf).empty? else @@ -139,14 +159,21 @@ end aRing = Concentric.lookup_ring(aRing) return [] unless aRing and rings_abilities = self.respond_to?(:rings_abilities).to_nil && self.rings_abilities - aRing.upto(rings_abilities.length-1) do |i| + ring_keys = rings_abilities.keys.sort + ring_keys.each do |i| + next unless i >= aRing next unless ring_rec = rings_abilities[i] return true if ring_rec[aAbility.to_sym].to_nil end return false + end + + # deprecated + def ring_can?(aRing,aAbility,aFields=nil) + allowed?(aRing,aAbility,aFields) end end end