Class: ActsAsCalculator::RenderLiquid
- Inherits:
-
Object
- Object
- ActsAsCalculator::RenderLiquid
- Defined in:
- lib/acts_as_calculator/render_liquid.rb
Overview
The security boundary. Template bodies are authored by non-developers (eventually through Phase 5's API), so this deliberately renders inside a private Liquid::Environment rather than Liquid's process-global default, which a host app is free to have repointed at a real file system or loaded its own tags into.
Defined Under Namespace
Classes: BoundedFor, IterationBudget
Constant Summary collapse
- FILE_SYSTEM_TAGS =
include/renderare the only tags that read from outside the assigns. A BlankFileSystem already refuses them; dropping the tags means the template fails at parse time with a syntax error instead of at render time with a file system error. %w[include render].freeze
- ITERATING_TAGS =
tablerowiterates a collection the same wayfordoes, but through its own render_to_output_buffer rather than a subclassable collection_segment. It is a storefront grid-layout tag with no use in rendering a calculation, so it is dropped rather than given a second, version-fragile bounded subclass. %w[tablerow].freeze
- RESOURCE_LIMITS =
Bounds output size and assign churn. These do NOT bound iteration on their own — render_score counts rendered nodes, so an empty loop body scores zero per pass. That gap is closed by BoundedFor/MAX_ITERATIONS below, not here.
{ render_length_limit: 2_000_000, render_score_limit: 200_000, assign_score_limit: 2_000_000 }.freeze
- MAX_ITERATIONS =
Cumulative across every loop in one render, so nested loops multiply into the same budget instead of each staying under a per-loop cap. Generous for presenting a calculation; a template needing more than this is not a template.
10_000- SANDBOX_TAGS =
Liquid::Tags::STANDARD_TAGS .reject { |name, _| (FILE_SYSTEM_TAGS + ITERATING_TAGS).include?(name) } .merge("for" => BoundedFor) .freeze
- SANDBOX =
Liquid::Environment.build( error_mode: :strict, file_system: Liquid::BlankFileSystem.new, tags: SANDBOX_TAGS ) do |environment| environment.default_resource_limits = RESOURCE_LIMITS environment.register_filter(LiquidFilters) end
Class Method Summary collapse
Class Method Details
.call(source:, assigns: {}) ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/acts_as_calculator/render_liquid.rb', line 103 def self.call(source:, assigns: {}) Liquid::Template .parse(source.to_s, environment: SANDBOX, line_numbers: true) .render!(assigns, registers: { iteration_budget: IterationBudget.new(MAX_ITERATIONS) }, strict_filters: true) rescue Liquid::Error => e raise TemplateRenderError, e.to_s end |