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
all
method which returns an array of restricted records. -
#any? ⇒ Object
A proxy for
any?
method which returns a raw value. -
#average ⇒ Object
A proxy for
average
method which returns a raw value. -
#build ⇒ Object
A proxy for
build
method which adds fixtures to the attribute list and returns a restricted record. -
#calculate ⇒ Object
A proxy for
calculate
method which returns a raw value. -
#count ⇒ Object
A proxy for
count
method which returns a raw value. - #creatable? ⇒ Boolean
-
#create ⇒ Object
A proxy for
create
method 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
delete
method which works on a:delete
scope. -
#delete_all ⇒ Object
A proxy for
delete_all
method which works on a:delete
scope. -
#destroy ⇒ Object
A proxy for
destroy
method which works on a:delete
scope. -
#destroy_all ⇒ Object
A proxy for
destroy_all
method which works on a:delete
scope. -
#each {|record| ... } ⇒ Object
A proxy for
each
which 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
extending
method which returns a restricted scope. -
#find(*args) ⇒ Proxy::Record+
A proxy for
find
which restricts the returned record or records. -
#first ⇒ Object
A proxy for
first
method 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
includes
which 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
joins
method which returns a restricted scope. -
#klass ⇒ Object
A proxy for
klass
method which returns a raw value. -
#last ⇒ Object
A proxy for
last
method which returns a restricted record. -
#last! ⇒ Object
A proxy for
last!
method which returns a restricted record. -
#length ⇒ Object
A proxy for
length
method which returns a raw value. -
#limit ⇒ Object
A proxy for
limit
method which returns a restricted scope. -
#lock ⇒ Object
A proxy for
lock
method which returns a restricted scope. -
#many? ⇒ Object
A proxy for
many?
method which returns a raw value. -
#maximum ⇒ Object
A proxy for
maximum
method 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
minimum
method which returns a raw value. -
#model_name ⇒ Object
A proxy for
model_name
method which returns a raw value. -
#new ⇒ Object
A proxy for
new
method which adds fixtures to the attribute list and returns a restricted record. -
#offset ⇒ Object
A proxy for
offset
method which returns a restricted scope. -
#order ⇒ Object
A proxy for
order
method which returns a restricted scope. -
#pluck ⇒ Object
A proxy for
pluck
method which returns a raw value. -
#reflect_on_security ⇒ Hash
Return the associated security metadata.
-
#reorder ⇒ Object
A proxy for
reorder
method 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_order
method which returns a restricted scope. -
#scoped ⇒ Object
A proxy for
scoped
method which returns a restricted scope. -
#size ⇒ Object
A proxy for
size
method which returns a raw value. -
#sum ⇒ Object
A proxy for
sum
method which returns a raw value. -
#to_a ⇒ Object
A proxy for
to_a
method which returns an array of restricted records. -
#to_ary ⇒ Object
A proxy for
to_ary
method which returns an array of restricted records. -
#uniq ⇒ Object
A proxy for
uniq
method which returns a restricted scope. -
#where ⇒ Object
A proxy for
where
method 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 |