diff --git a/app/services/rich_text_migrator.rb b/app/services/rich_text_migrator.rb index ec8ad4a73..7782fdb4e 100644 --- a/app/services/rich_text_migrator.rb +++ b/app/services/rich_text_migrator.rb @@ -1,5 +1,8 @@ class RichTextMigrator - include ActionText::ContentHelper + include Rails.application.routes.url_helpers + + require "nokogiri" + require "uri" PLACEHOLDER_TEXT = "image not found" @@ -7,76 +10,54 @@ def initialize(record, old_column) @record = record @old_column = old_column.to_s @new_column = "rhino_#{@old_column}" - @blobs_by_key = index_resource_blobs end def migrate! + return unless valid_columns? + html = @record.public_send(@old_column) return if html.blank? - sanitized_html = sanitize_html(html) - - @record.assign_attributes(@new_column => ActionText::Content.new(sanitized_html)) - - @record.save(validate: false) - end - - private - - def sanitize_html(html) - sanitized = ActionController::Base.helpers.sanitize( - html, - tags: allowed_tags, - attributes: allowed_attributes - ) - - convert_images_to_attachments(sanitized) - end - - def allowed_tags - ActionText::ContentHelper.allowed_tags - end - - def allowed_attributes - ActionText::ContentHelper.allowed_attributes - end - - def convert_images_to_attachments(html) fragment = Nokogiri::HTML::DocumentFragment.parse(html) fragment.css("img").each do |img| - aws_key = extract_aws_key(img["src"]) - blob = @blobs_by_key[aws_key] + img_url = img["src"] + next unless img_url + + signed_id = extract_signed_id(img_url) + next unless signed_id + blob = find_blob(signed_id) if blob - attachment = ActionText::Attachment.from_attachable(blob) + attachment = ActionText::Attachment.from_attachable(blob, url: url_for(blob)) + img.replace(attachment.to_html) else - img.replace(placeholder_node(img["src"])) + img.replace(placeholder_node(img_url)) end end - fragment.to_html + @record.public_send(@new_column).update!(body: fragment.to_html) end - def index_resource_blobs - @record.images - .includes(file_attachment: :blob) - .map(&:file) # get ActiveStorage::Attached::One - .map(&:blob) - .compact # remove nil blobs - .index_by(&:aws_key) + private + + def valid_columns? + @record.respond_to?(@old_column) && @record.respond_to?(@new_column) end - def extract_aws_key(src) - return if src.blank? + def extract_signed_id(url) + path_segments = URI.parse(url).path.split("/blobs/")[1]&.split("/") + return nil unless path_segments + + (path_segments.first == "redirect") ? path_segments[1] : path_segments.first + rescue + nil + end - uri = URI.parse(src) - uri.path - .sub(%r{^/}, "") # remove leading slash - .split("?") - .first - rescue URI::InvalidURIError + def find_blob(signed_id) + ActiveStorage::Blob.find_signed(signed_id) + rescue ActiveSupport::MessageVerifier::InvalidSignature nil end diff --git a/lib/tasks/rich_text_urls_update.rake b/lib/tasks/rich_text_urls_update.rake index 3431f616f..f436ce4a1 100644 --- a/lib/tasks/rich_text_urls_update.rake +++ b/lib/tasks/rich_text_urls_update.rake @@ -31,7 +31,6 @@ namespace :rich_text_urls_update do def run_update(dry_run:, html_attr:, start_id: nil, finish_id: nil) models = [ Address, - AgeRange, AnswerOption, Attachment, Banner, @@ -70,7 +69,6 @@ namespace :rich_text_urls_update do UserForm, User, WindowsType, - WorkshopAgeRange, WorkshopIdea, WorkshopLog, WorkshopResource,