From b7ecf4791a9d633079fd6a194f7a68a6bd0ea584 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 9 Jan 2021 01:07:11 +0000 Subject: [PATCH] Extract more sanitizing logic from Api::ProductSerializer and make service more generic/re-usable. --- app/serializers/api/product_serializer.rb | 17 +++++----- app/services/content_sanitizer.rb | 36 ++++++++++++++++++++++ app/services/product_description_filter.rb | 16 ---------- 3 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 app/services/content_sanitizer.rb delete mode 100644 app/services/product_description_filter.rb diff --git a/app/serializers/api/product_serializer.rb b/app/serializers/api/product_serializer.rb index e22edaf9e1..33c8ba4430 100644 --- a/app/serializers/api/product_serializer.rb +++ b/app/serializers/api/product_serializer.rb @@ -1,8 +1,6 @@ require "open_food_network/scope_variant_to_hub" class Api::ProductSerializer < ActiveModel::Serializer - include ActionView::Helpers::SanitizeHelper - attributes :id, :name, :permalink, :meta_keywords attributes :group_buy, :notes, :description, :description_html attributes :properties_with_values, :price @@ -18,17 +16,12 @@ class Api::ProductSerializer < ActiveModel::Serializer # return an unformatted descripton def description - return unless d = strip_tags(object.description&.strip) - - ProductDescriptionFilter.filter(d) + sanitizer.strip_content(object.description) end # return a sanitized html description def description_html - ProductDescriptionFilter.filter( - sanitize(object.description, tags: ["p", "b", "strong", "em", "i", "a", "u"], - attributes: ["href", "target"]).to_s.html_safe - ) + sanitizer.sanitize_content(object.description).html_safe end def properties_with_values @@ -50,4 +43,10 @@ class Api::ProductSerializer < ActiveModel::Serializer object.master.price_with_fees(options[:current_distributor], options[:current_order_cycle]) end end + + private + + def sanitizer + @sanitizer ||= ContentSanitizer.new + end end diff --git a/app/services/content_sanitizer.rb b/app/services/content_sanitizer.rb new file mode 100644 index 0000000000..4b2c7d3046 --- /dev/null +++ b/app/services/content_sanitizer.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Sanitizes and cleans up user-provided content that may contain tags, special characters, etc. + +class ContentSanitizer + include ActionView::Helpers::SanitizeHelper + + ALLOWED_TAGS = ["p", "b", "strong", "em", "i", "a", "u"].freeze + ALLOWED_ATTRIBUTES = ["href", "target"].freeze + FILTERED_CHARACTERS = { + "&amp;" => "&", + "&" => "&", + " " => " " + }.freeze + + def strip_content(content) + content = strip_tags(content.to_s.strip) + + filter_characters(content) if content.length + end + + def sanitize_content(content) + content = sanitize(content.to_s, tags: ALLOWED_TAGS, attributes: ALLOWED_ATTRIBUTES) + + filter_characters(content) if content.length + end + + private + + def filter_characters(content) + FILTERED_CHARACTERS.each do |character, sub| + content = content.gsub(character, sub) + end + content + end +end diff --git a/app/services/product_description_filter.rb b/app/services/product_description_filter.rb deleted file mode 100644 index da66ae23cc..0000000000 --- a/app/services/product_description_filter.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class ProductDescriptionFilter - FILTERED_CHARACTERS = { - "&amp;" => "&", - "&" => "&", - " " => " " - }.freeze - - def self.filter(descripton) - FILTERED_CHARACTERS.each do |character, sub| - descripton = descripton.gsub(character, sub) - end - descripton - end -end