Class: Heimdallr::Proxy::Collection
- Inherits:
-
Object
- Object
- Heimdallr::Proxy::Collection
- Includes:
- Enumerable
- Defined in:
- lib/heimdallr/proxy/collection.rb
Overview
A security-aware proxy for ActiveRecord scopes. This class validates all the
method calls and either forwards them to the encapsulated scope or raises
an exception.
There are two kinds of collection proxies, explicit and implicit, which instantiate the corresponding types of record proxies. See also Record.
Instance Method Summary collapse
-
#all ⇒ Object
A proxy for
allmethod which returns an array of restricted records. -
#any? ⇒ Object
A proxy for
any?method which returns a raw value. -
#average ⇒ Object
A proxy for
averagemethod which returns a raw value. -
#build ⇒ Object
A proxy for
buildmethod which adds fixtures to the attribute list and returns a restricted record. -
#calculate ⇒ Object
A proxy for
calculatemethod which returns a raw value. -
#count ⇒ Object
A proxy for
countmethod which returns a raw value. - #creatable? ⇒ Boolean
-
#create ⇒ Object
A proxy for
createmethod which adds fixtures to the attribute list and returns a restricted record. -
#create! ⇒ Object
A proxy for
create!method which adds fixtures to the attribute list and returns a restricted record. -
#delete ⇒ Object
A proxy for
deletemethod which works on a:deletescope. -
#delete_all ⇒ Object
A proxy for
delete_allmethod which works on a:deletescope. -
#destroy ⇒ Object
A proxy for
destroymethod which works on a:deletescope. -
#destroy_all ⇒ Object
A proxy for
destroy_allmethod which works on a:deletescope. -
#each {|record| ... } ⇒ Object
A proxy for
eachwhich restricts the yielded records. -
#empty? ⇒ Object
A proxy for
empty?method which returns a raw value. -
#exists? ⇒ Object
A proxy for
exists?method which returns a raw value. -
#extending ⇒ Object
A proxy for
extendingmethod which returns a restricted scope. -
#find(*args) ⇒ Proxy::Record+
A proxy for
findwhich restricts the returned record or records. -
#first ⇒ Object
A proxy for
firstmethod which returns a restricted record. -
#first! ⇒ Object
A proxy for
first!method which returns a restricted record. -
#include? ⇒ Object
A proxy for
include?method which returns a raw value. -
#includes(*associations) ⇒ Object
A proxy for
includeswhich adds Heimdallr conditions for eager loaded associations. -
#initialize(context, scope, options = {}) ⇒ Collection
constructor
Create a collection proxy.
-
#insecure ⇒ Object
Return the underlying scope.
-
#insecurely(*args, &block) ⇒ Proxy::Collection
Insecurely taps method saving restricted context for the result Method (or block) is supposed to return proper relation.
-
#inspect ⇒ String
Describes the proxy and proxified scope.
-
#joins ⇒ Object
A proxy for
joinsmethod which returns a restricted scope. -
#klass ⇒ Object
A proxy for
klassmethod which returns a raw value. -
#last ⇒ Object
A proxy for
lastmethod which returns a restricted record. -
#last! ⇒ Object
A proxy for
last!method which returns a restricted record. -
#length ⇒ Object
A proxy for
lengthmethod which returns a raw value. -
#limit ⇒ Object
A proxy for
limitmethod which returns a restricted scope. -
#lock ⇒ Object
A proxy for
lockmethod which returns a restricted scope. -
#many? ⇒ Object
A proxy for
many?method which returns a raw value. -
#maximum ⇒ Object
A proxy for
maximummethod which returns a raw value. -
#method_missing(method, *args) ⇒ Object
Wraps a scope or a record in a corresponding proxy.
-
#minimum ⇒ Object
A proxy for
minimummethod which returns a raw value. -
#model_name ⇒ Object
A proxy for
model_namemethod which returns a raw value. -
#new ⇒ Object
A proxy for
newmethod which adds fixtures to the attribute list and returns a restricted record. -
#offset ⇒ Object
A proxy for
offsetmethod which returns a restricted scope. -
#order ⇒ Object
A proxy for
ordermethod which returns a restricted scope. -
#pluck ⇒ Object
A proxy for
pluckmethod which returns a raw value. -
#reflect_on_security ⇒ Hash
Return the associated security metadata.
-
#reorder ⇒ Object
A proxy for
reordermethod which returns a restricted scope. -
#restrict(context, options = nil) ⇒ Object
Collections cannot be restricted with different context or options.
-
#reverse_order ⇒ Object
A proxy for
reverse_ordermethod which returns a restricted scope. -
#scoped ⇒ Object
A proxy for
scopedmethod which returns a restricted scope. -
#size ⇒ Object
A proxy for
sizemethod which returns a raw value. -
#sum ⇒ Object
A proxy for
summethod which returns a raw value. -
#to_a ⇒ Object
A proxy for
to_amethod which returns an array of restricted records. -
#to_ary ⇒ Object
A proxy for
to_arymethod which returns an array of restricted records. -
#uniq ⇒ Object
A proxy for
uniqmethod which returns a restricted scope. -
#where ⇒ Object
A proxy for
wheremethod which returns a restricted scope.
Constructor Details
#initialize(context, scope, options = {}) ⇒ Collection
Create a collection proxy.
The scope is expected to be already restricted with :fetch scope.
18 19 20 21 22 23 |
# File 'lib/heimdallr/proxy/collection.rb', line 18 def initialize(context, scope, ={}) @context, @scope, @options = context, scope, @restrictions = @scope.restrictions(context) @options[:eager_loaded] ||= {} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
Wraps a scope or a record in a corresponding proxy.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/heimdallr/proxy/collection.rb', line 241 def method_missing(method, *args) if method =~ /^find_all_by/ @scope.send(method, *args).map do |element| element.restrict(@context, ) end elsif method =~ /^find_by/ @scope.send(method, *args).restrict(@context, ) elsif @scope.heimdallr_scopes && @scope.heimdallr_scopes.include?(method) Proxy::Collection.new(@context, @scope.send(method, *args), ) elsif @scope.respond_to? method raise InsecureOperationError, "Potentially insecure method #{method} was called" else super end end |
Instance Method Details
#all ⇒ Object
A proxy for all method which returns an array of restricted records.
160 |
# File 'lib/heimdallr/proxy/collection.rb', line 160 delegate_as_records :all |
#any? ⇒ Object
A proxy for any? method which returns a raw value.
135 |
# File 'lib/heimdallr/proxy/collection.rb', line 135 delegate_as_value :any? |
#average ⇒ Object
A proxy for average method which returns a raw value.
144 |
# File 'lib/heimdallr/proxy/collection.rb', line 144 delegate_as_value :average |
#build ⇒ Object
A proxy for build method which adds fixtures to the attribute list and
returns a restricted record.
115 |
# File 'lib/heimdallr/proxy/collection.rb', line 115 delegate_as_constructor :build, :assign_attributes |
#calculate ⇒ Object
A proxy for calculate method which returns a raw value.
142 |
# File 'lib/heimdallr/proxy/collection.rb', line 142 delegate_as_value :calculate |
#count ⇒ Object
A proxy for count method which returns a raw value.
143 |
# File 'lib/heimdallr/proxy/collection.rb', line 143 delegate_as_value :count |
#creatable? ⇒ Boolean
305 306 307 |
# File 'lib/heimdallr/proxy/collection.rb', line 305 def creatable? @restrictions.can? :create end |
#create ⇒ Object
A proxy for create method which adds fixtures to the attribute list and
returns a restricted record.
117 |
# File 'lib/heimdallr/proxy/collection.rb', line 117 delegate_as_constructor :create, :update_attributes |
#create! ⇒ Object
A proxy for create! method which adds fixtures to the attribute list and
returns a restricted record.
118 |
# File 'lib/heimdallr/proxy/collection.rb', line 118 delegate_as_constructor :create!, :update_attributes! |
#delete ⇒ Object
A proxy for delete method which works on a :delete scope.
150 |
# File 'lib/heimdallr/proxy/collection.rb', line 150 delegate_as_destroyer :delete |
#delete_all ⇒ Object
A proxy for delete_all method which works on a :delete scope.
151 |
# File 'lib/heimdallr/proxy/collection.rb', line 151 delegate_as_destroyer :delete_all |
#destroy ⇒ Object
A proxy for destroy method which works on a :delete scope.
152 |
# File 'lib/heimdallr/proxy/collection.rb', line 152 delegate_as_destroyer :destroy |
#destroy_all ⇒ Object
A proxy for destroy_all method which works on a :delete scope.
153 |
# File 'lib/heimdallr/proxy/collection.rb', line 153 delegate_as_destroyer :destroy_all |
#each {|record| ... } ⇒ Object
A proxy for each which restricts the yielded records.
234 235 236 237 238 |
# File 'lib/heimdallr/proxy/collection.rb', line 234 def each @scope.each do |record| yield record.restrict(@context, ) end end |
#empty? ⇒ Object
A proxy for empty? method which returns a raw value.
134 |
# File 'lib/heimdallr/proxy/collection.rb', line 134 delegate_as_value :empty? |
#exists? ⇒ Object
A proxy for exists? method which returns a raw value.
138 |
# File 'lib/heimdallr/proxy/collection.rb', line 138 delegate_as_value :exists? |
#extending ⇒ Object
A proxy for extending method which returns a restricted scope.
130 |
# File 'lib/heimdallr/proxy/collection.rb', line 130 delegate_as_scope :extending |
#find(*args) ⇒ Proxy::Record+
A proxy for find which restricts the returned record or records.
218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/heimdallr/proxy/collection.rb', line 218 def find(*args) result = @scope.find(*args) if result.is_a? Enumerable result.map do |element| element.restrict(@context, ) end else result.restrict(@context, ) end end |
#first ⇒ Object
A proxy for first method which returns a restricted record.
155 |
# File 'lib/heimdallr/proxy/collection.rb', line 155 delegate_as_record :first |
#first! ⇒ Object
A proxy for first! method which returns a restricted record.
156 |
# File 'lib/heimdallr/proxy/collection.rb', line 156 delegate_as_record :first! |
#include? ⇒ Object
A proxy for include? method which returns a raw value.
137 |
# File 'lib/heimdallr/proxy/collection.rb', line 137 delegate_as_value :include? |
#includes(*associations) ⇒ Object
A proxy for includes which adds Heimdallr conditions for eager loaded
associations.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/heimdallr/proxy/collection.rb', line 166 def includes(*associations) # Normalize association list to strict nested hash. normalize = ->(list) { if list.is_a? Array list.map(&normalize).reduce(:merge) elsif list.is_a? Symbol { list => {} } elsif list.is_a? Hash hash = {} list.each do |key, value| hash[key] = normalize.(value) end hash end } associations = normalize.(associations) current_scope = @scope.includes(associations) add_conditions = ->(associations, scope) { associations.each do |association, nested| reflection = scope.reflect_on_association(association) if reflection && !reflection.[:polymorphic] associated_klass = reflection.klass if associated_klass.respond_to? :restrict nested_scope = associated_klass.restrictions(@context).request_scope(:fetch) where_values = nested_scope.where_values if where_values.any? current_scope = current_scope.where(*where_values) end add_conditions.(nested, associated_klass) end end end } unless Heimdallr.skip_eager_condition_injection add_conditions.(associations, current_scope) end = @options.merge(eager_loaded: @options[:eager_loaded].merge(associations)) Proxy::Collection.new(@context, current_scope, ) end |
#insecure ⇒ Object
Return the underlying scope.
261 262 263 |
# File 'lib/heimdallr/proxy/collection.rb', line 261 def insecure @scope end |
#insecurely(*args, &block) ⇒ Proxy::Collection
Insecurely taps method saving restricted context for the result Method (or block) is supposed to return proper relation
269 270 271 272 273 274 275 276 277 278 |
# File 'lib/heimdallr/proxy/collection.rb', line 269 def insecurely(*args, &block) if block_given? result = yield @scope else method = args.shift result = @scope.send method, *args end Proxy::Collection.new(@context, result, ) end |
#inspect ⇒ String
Describes the proxy and proxified scope.
283 284 285 |
# File 'lib/heimdallr/proxy/collection.rb', line 283 def inspect "#<Heimdallr::Proxy::Collection: #{@scope.to_sql}>" end |
#joins ⇒ Object
A proxy for joins method which returns a restricted scope.
123 |
# File 'lib/heimdallr/proxy/collection.rb', line 123 delegate_as_scope :joins |
#klass ⇒ Object
A proxy for klass method which returns a raw value.
132 |
# File 'lib/heimdallr/proxy/collection.rb', line 132 delegate_as_value :klass |
#last ⇒ Object
A proxy for last method which returns a restricted record.
157 |
# File 'lib/heimdallr/proxy/collection.rb', line 157 delegate_as_record :last |
#last! ⇒ Object
A proxy for last! method which returns a restricted record.
158 |
# File 'lib/heimdallr/proxy/collection.rb', line 158 delegate_as_record :last! |
#length ⇒ Object
A proxy for length method which returns a raw value.
140 |
# File 'lib/heimdallr/proxy/collection.rb', line 140 delegate_as_value :length |
#limit ⇒ Object
A proxy for limit method which returns a restricted scope.
125 |
# File 'lib/heimdallr/proxy/collection.rb', line 125 delegate_as_scope :limit |
#lock ⇒ Object
A proxy for lock method which returns a restricted scope.
124 |
# File 'lib/heimdallr/proxy/collection.rb', line 124 delegate_as_scope :lock |
#many? ⇒ Object
A proxy for many? method which returns a raw value.
136 |
# File 'lib/heimdallr/proxy/collection.rb', line 136 delegate_as_value :many? |
#maximum ⇒ Object
A proxy for maximum method which returns a raw value.
146 |
# File 'lib/heimdallr/proxy/collection.rb', line 146 delegate_as_value :maximum |
#minimum ⇒ Object
A proxy for minimum method which returns a raw value.
147 |
# File 'lib/heimdallr/proxy/collection.rb', line 147 delegate_as_value :minimum |
#model_name ⇒ Object
A proxy for model_name method which returns a raw value.
133 |
# File 'lib/heimdallr/proxy/collection.rb', line 133 delegate_as_value :model_name |
#new ⇒ Object
A proxy for new method which adds fixtures to the attribute list and
returns a restricted record.
116 |
# File 'lib/heimdallr/proxy/collection.rb', line 116 delegate_as_constructor :new, :assign_attributes |
#offset ⇒ Object
A proxy for offset method which returns a restricted scope.
126 |
# File 'lib/heimdallr/proxy/collection.rb', line 126 delegate_as_scope :offset |
#order ⇒ Object
A proxy for order method which returns a restricted scope.
127 |
# File 'lib/heimdallr/proxy/collection.rb', line 127 delegate_as_scope :order |
#pluck ⇒ Object
A proxy for pluck method which returns a raw value.
148 |
# File 'lib/heimdallr/proxy/collection.rb', line 148 delegate_as_value :pluck |
#reflect_on_security ⇒ Hash
Return the associated security metadata. The returned hash will contain keys
:context, :scope and :options, corresponding to the parameters in
#initialize, :model and :restrictions, representing the model class.
Such a name was deliberately selected for this method in order to reduce namespace pollution.
295 296 297 298 299 300 301 302 303 |
# File 'lib/heimdallr/proxy/collection.rb', line 295 def reflect_on_security { model: @scope, context: @context, scope: @scope, options: @options, restrictions: @restrictions, }.merge(@restrictions.reflection) end |
#reorder ⇒ Object
A proxy for reorder method which returns a restricted scope.
128 |
# File 'lib/heimdallr/proxy/collection.rb', line 128 delegate_as_scope :reorder |
#restrict(context, options = nil) ⇒ Object
Collections cannot be restricted with different context or options.
29 30 31 32 33 34 35 |
# File 'lib/heimdallr/proxy/collection.rb', line 29 def restrict(context, =nil) if @context == context && .nil? self else raise RuntimeError, "Heimdallr proxies cannot be restricted with nonmatching context or options" end end |
#reverse_order ⇒ Object
A proxy for reverse_order method which returns a restricted scope.
129 |
# File 'lib/heimdallr/proxy/collection.rb', line 129 delegate_as_scope :reverse_order |
#scoped ⇒ Object
A proxy for scoped method which returns a restricted scope.
120 |
# File 'lib/heimdallr/proxy/collection.rb', line 120 delegate_as_scope :scoped |
#size ⇒ Object
A proxy for size method which returns a raw value.
139 |
# File 'lib/heimdallr/proxy/collection.rb', line 139 delegate_as_value :size |
#sum ⇒ Object
A proxy for sum method which returns a raw value.
145 |
# File 'lib/heimdallr/proxy/collection.rb', line 145 delegate_as_value :sum |
#to_a ⇒ Object
A proxy for to_a method which returns an array of restricted records.
161 |
# File 'lib/heimdallr/proxy/collection.rb', line 161 delegate_as_records :to_a |
#to_ary ⇒ Object
A proxy for to_ary method which returns an array of restricted records.
162 |
# File 'lib/heimdallr/proxy/collection.rb', line 162 delegate_as_records :to_ary |
#uniq ⇒ Object
A proxy for uniq method which returns a restricted scope.
121 |
# File 'lib/heimdallr/proxy/collection.rb', line 121 delegate_as_scope :uniq |
#where ⇒ Object
A proxy for where method which returns a restricted scope.
122 |
# File 'lib/heimdallr/proxy/collection.rb', line 122 delegate_as_scope :where |