Skip to content

Commit

Permalink
Validate maximum file size after converting audio/video file for tipl…
Browse files Browse the repository at this point in the history
…ine content. (#2046)

We validate the size of a file uploaded to be the header of a newsletter or resource. But, depending on the file (for example, videos and audios) they get converted to the formats and codecs accepted by WhatsApp. It’s important to also validate the file size after converting, since in some (rare) cases they can be larger than the original file. For example, when the input file is a video that uses the H.265 codec, which is usually much lighter than the H.264 output codec.

Fixes: CV2-5326.
  • Loading branch information
caiosba authored Sep 23, 2024
1 parent aee7328 commit 637d04e
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 2 deletions.
4 changes: 3 additions & 1 deletion app/models/concerns/tipline_content_multimedia.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Attached file: image, audio or video

module TiplineContentMultimedia
class ConvertedFileTooLarge < StandardError; end
extend ActiveSupport::Concern

included do
Expand Down Expand Up @@ -50,11 +51,12 @@ def convert_header_file_audio_or_video(type)
output_path = File.join(Rails.root, 'tmp', "#{content_name}-#{type}-output-#{self.id}-#{now}.mp4")
video = FFMPEG::Movie.new(input.path)
video.transcode(output_path, options)
raise TiplineContentMultimedia::ConvertedFileTooLarge.new('Converted file for tipline content is too large') if (File.size(output_path).to_f / 1024000.0) > self.header_file_video_max_size
path = "#{content_name}/video/#{content_name}-#{type}-#{self.id}-#{now}"
CheckS3.write(path, 'video/mp4', File.read(output_path))
url = CheckS3.public_url(path)
rescue StandardError => e
CheckSentry.notify(e)
CheckSentry.notify(e, class: self.class, id: self.id)
ensure
FileUtils.rm_f input.path
FileUtils.rm_f output_path
Expand Down
6 changes: 5 additions & 1 deletion app/models/concerns/tipline_content_video.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ module TiplineContentVideo
extend ActiveSupport::Concern

# MP4 less than 10 MB (WhatsApp supports 16 MB, let's be safe)
def header_file_video_max_size
10
end

def validate_header_file_video
self.validate_header_file(10, ['mp4'], 'errors.messages.video_too_large')
self.validate_header_file(self.header_file_video_max_size, ['mp4'], 'errors.messages.video_too_large')
end

def should_convert_header_video?
Expand Down
Binary file added test/data/h265-video.mp4
Binary file not shown.
11 changes: 11 additions & 0 deletions test/models/tipline_newsletter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -479,4 +479,15 @@ def teardown
create_tipline_newsletter send_every: nil
end
end

test 'should validate video size after converting' do
# This test file is 300 KB, but 1.6 MB after converting
WebMock.stub_request(:get, /:9000/).to_return(body: File.read(File.join(Rails.root, 'test', 'data', 'h265-video.mp4')))
TiplineNewsletter.any_instance.stubs(:new_file_uploaded?).returns(true)
TiplineNewsletter.any_instance.stubs(:header_file_video_max_size).returns(1) # Maximum 1 MB
CheckSentry.stubs(:notify).once
Sidekiq::Testing.inline! do
create_tipline_newsletter header_type: 'video', header_file: 'h265-video.mp4'
end
end
end

0 comments on commit 637d04e

Please sign in to comment.