SOME INTERESTING THINGS YOU CAN DO WITH RENDER Being a Brief Treatise on Matters of Efficiency & Security Alex Koppel - Railsberry
Nov 29, 2014
SOME INTERESTING THINGS YOU CAN DO WITH RENDER
Being a Brief Treatise on Matters of Efficiency & Security
Alex Koppel - Railsberry
BACKGROUND/GOALS
Wunderkit: an API-driven app Give clients control over the data returned Provide secured output Universal implementation
THE RENDER METHOD
Stable signature (2.3-4.0beta) For our purposes
Arguments => options hash This hash is provided to renderers
to_json, to_xml, ActiveModel::Serializers, etc. Controller action
Complete access to user state
DEF RENDER # /actionpack/lib/abstract_controller/rendering.rb (3.2)
def render(*args, &block) options = _normalize_render(*args, &block) self.response_body = render_to_body(options) end
EXAMPLE: DATASET SIZE
Problem: different devices want different amounts of data Web: full record at first encounter iOS: only what’s needed
Ideal solution Serialization solution handles dataset contents
Model#as_json, serializer, etc.
API exposes universal options
MAKE IT SO
def render(*args, &block) # ensure we have an options hash options = args.find {|a| a.is_a?(Hash)} args << (options = {}) unless options
# set the dataset option options[:dataset] = params[:dataset] || "full"
# proceed super end
EXAMPLE: CURRENT USER INFO
Example: current user info Problem: some info should only be shown to
the current user Billing status, location info ActiveModel::Serializers provides this automatically
Ideal solution Serializer/model knows what (if any) sensitive data
they contain Controllers filter that data transparently
ENGAGE
def render(*args, &block) # ensure we have an options hash options = args.find {|a| a.is_a?(Hash)} args << (options = {}) unless options
# store the current user options[:user] = current_user
# proceed super end
SECURITY
Can we use a similar approach? Prevent unauthorized data access?
Sure! But…
ACTIVATE SHIELDS
def render(*args, &block) # ...
if data = options[:json] # remove any items that the user shouldn't see secure_content!(data) end
# ... super end
GENERAL DOWNSIDES
Patching render somehow feels wrong Is it?
Other libraries may handle options hash badly Occasionally seen options defaulted to nil
Low risk of the render signature changing
SECURITY DOWNSIDES
Huge risk of accidental overhead Structure carefully to only use data in memory
Not bulletproof Handling non-Array data types gets tricky Misses data as_json’d in the controller Inflexible (though probably for the best)
THANKS!
@arsduo I work for @6wunderkinder
I’ll talk about this at @baruco2012 too