Switch traces to use ActiveStorage

This commit is contained in:
Tom Hughes 2021-10-17 16:00:22 +01:00
parent ef85e8c7b3
commit 0410596908
10 changed files with 249 additions and 268 deletions

View file

@ -54,6 +54,8 @@ module Api
send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment") send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
elsif request.format == Mime[:gpx] elsif request.format == Mime[:gpx]
send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment") send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
elsif trace.file.attached?
redirect_to rails_blob_path(trace.file, :disposition => "attachment")
else else
send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment") send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
end end
@ -97,12 +99,6 @@ module Api
# Sanitise the user's filename # Sanitise the user's filename
name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_") name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_")
# Get a temporary filename...
filename = "/tmp/#{rand}"
# ...and save the uploaded file to that location
File.open(filename, "wb") { |f| f.write(file.read) }
# Create the trace object, falsely marked as already # Create the trace object, falsely marked as already
# inserted to stop the import daemon trying to load it # inserted to stop the import daemon trying to load it
trace = Trace.new( trace = Trace.new(
@ -110,41 +106,15 @@ module Api
:tagstring => tags, :tagstring => tags,
:description => description, :description => description,
:visibility => visibility, :visibility => visibility,
:inserted => true, :inserted => false,
:user => current_user, :user => current_user,
:timestamp => Time.now.getutc :timestamp => Time.now.getutc,
:file => file
) )
if trace.valid?
Trace.transaction do
begin
# Save the trace object # Save the trace object
trace.save! trace.save!
# Rename the temporary file to the final name
FileUtils.mv(filename, trace.trace_name)
rescue StandardError
# Remove the file as we have failed to update the database
FileUtils.rm_f(filename)
# Pass the exception on
raise
end
begin
# Clear the inserted flag to make the import daemon load the trace
trace.inserted = false
trace.save!
rescue StandardError
# Remove the file as we have failed to update the database
FileUtils.rm_f(trace.trace_name)
# Pass the exception on
raise
end
end
end
# Finally save the user's preferred privacy level # Finally save the user's preferred privacy level
if pref = current_user.preferences.where(:k => "gps.trace.visibility").first if pref = current_user.preferences.where(:k => "gps.trace.visibility").first
pref.v = visibility pref.v = visibility

View file

@ -99,12 +99,8 @@ class TracesController < ApplicationController
logger.info(params[:trace][:gpx_file].class.name) logger.info(params[:trace][:gpx_file].class.name)
if params[:trace][:gpx_file].respond_to?(:read) if params[:trace][:gpx_file].respond_to?(:read)
begin
@trace = do_create(params[:trace][:gpx_file], params[:trace][:tagstring], @trace = do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
params[:trace][:description], params[:trace][:visibility]) params[:trace][:description], params[:trace][:visibility])
rescue StandardError => e
logger.debug e
end
if @trace.id if @trace.id
flash[:notice] = t ".trace_uploaded" flash[:notice] = t ".trace_uploaded"
@ -141,6 +137,8 @@ class TracesController < ApplicationController
send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment") send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
elsif request.format == Mime[:gpx] elsif request.format == Mime[:gpx]
send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment") send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
elsif trace.file.attached?
redirect_to rails_blob_path(trace.file, :disposition => "attachment")
else else
send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment") send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
end end
@ -217,8 +215,12 @@ class TracesController < ApplicationController
if trace.visible? && trace.inserted? if trace.visible? && trace.inserted?
if trace.public? || (current_user && current_user == trace.user) if trace.public? || (current_user && current_user == trace.user)
if trace.icon.attached?
redirect_to rails_blob_path(trace.image, :disposition => "inline")
else
expires_in 7.days, :private => !trace.public?, :public => trace.public? expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => "image/gif", :disposition => "inline") send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => "image/gif", :disposition => "inline")
end
else else
head :forbidden head :forbidden
end end
@ -234,8 +236,12 @@ class TracesController < ApplicationController
if trace.visible? && trace.inserted? if trace.visible? && trace.inserted?
if trace.public? || (current_user && current_user == trace.user) if trace.public? || (current_user && current_user == trace.user)
if trace.icon.attached?
redirect_to rails_blob_path(trace.icon, :disposition => "inline")
else
expires_in 7.days, :private => !trace.public?, :public => trace.public? expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline") send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline")
end
else else
head :forbidden head :forbidden
end end
@ -252,54 +258,20 @@ class TracesController < ApplicationController
# Sanitise the user's filename # Sanitise the user's filename
name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_") name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_")
# Get a temporary filename... # Create the trace object
filename = "/tmp/#{rand}"
# ...and save the uploaded file to that location
File.open(filename, "wb") { |f| f.write(file.read) }
# Create the trace object, falsely marked as already
# inserted to stop the import daemon trying to load it
trace = Trace.new( trace = Trace.new(
:name => name, :name => name,
:tagstring => tags, :tagstring => tags,
:description => description, :description => description,
:visibility => visibility, :visibility => visibility,
:inserted => true, :inserted => false,
:user => current_user, :user => current_user,
:timestamp => Time.now.getutc :timestamp => Time.now.getutc,
:file => file
) )
if trace.valid?
Trace.transaction do
begin
# Save the trace object # Save the trace object
trace.save! if trace.save
# Rename the temporary file to the final name
FileUtils.mv(filename, trace.trace_name)
rescue StandardError
# Remove the file as we have failed to update the database
FileUtils.rm_f(filename)
# Pass the exception on
raise
end
begin
# Clear the inserted flag to make the import daemon load the trace
trace.inserted = false
trace.save!
rescue StandardError
# Remove the file as we have failed to update the database
FileUtils.rm_f(trace.trace_name)
# Pass the exception on
raise
end
end
end
# Finally save the user's preferred privacy level # Finally save the user's preferred privacy level
if pref = current_user.preferences.where(:k => "gps.trace.visibility").first if pref = current_user.preferences.where(:k => "gps.trace.visibility").first
pref.v = visibility pref.v = visibility
@ -307,6 +279,7 @@ class TracesController < ApplicationController
else else
current_user.preferences.create(:k => "gps.trace.visibility", :v => visibility) current_user.preferences.create(:k => "gps.trace.visibility", :v => visibility)
end end
end
trace trace
end end

View file

@ -39,6 +39,10 @@ class Trace < ApplicationRecord
scope :visible_to_all, -> { where(:visibility => %w[public identifiable]) } scope :visible_to_all, -> { where(:visibility => %w[public identifiable]) }
scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) } scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) }
has_one_attached :file, :service => Settings.trace_file_storage
has_one_attached :image, :service => Settings.trace_image_storage
has_one_attached :icon, :service => Settings.trace_icon_storage
validates :user, :presence => true, :associated => true validates :user, :presence => true, :associated => true
validates :name, :presence => true, :length => 1..255, :characters => true validates :name, :presence => true, :length => 1..255, :characters => true
validates :description, :presence => { :on => :create }, :length => 1..255, :characters => true validates :description, :presence => { :on => :create }, :length => 1..255, :characters => true
@ -46,6 +50,7 @@ class Trace < ApplicationRecord
validates :visibility, :inclusion => %w[private public trackable identifiable] validates :visibility, :inclusion => %w[private public trackable identifiable]
after_destroy :remove_files after_destroy :remove_files
after_save :set_filename
def tagstring def tagstring
tags.collect(&:tag).join(", ") tags.collect(&:tag).join(", ")
@ -68,6 +73,18 @@ class Trace < ApplicationRecord
end end
end end
def file=(attachable)
case attachable
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
super(:io => attachable,
:filename => attachable.original_filename,
:content_type => content_type(attachable.path),
:identify => false)
else
super(attachable)
end
end
def public? def public?
visibility == "public" || visibility == "identifiable" visibility == "public" || visibility == "identifiable"
end end
@ -80,29 +97,27 @@ class Trace < ApplicationRecord
visibility == "identifiable" visibility == "identifiable"
end end
def large_picture=(data)
f = File.new(large_picture_name, "wb")
f.syswrite(data)
f.close
end
def icon_picture=(data)
f = File.new(icon_picture_name, "wb")
f.syswrite(data)
f.close
end
def large_picture def large_picture
if image.attached?
data = image.blob.download
else
f = File.new(large_picture_name, "rb") f = File.new(large_picture_name, "rb")
data = f.sysread(File.size(f.path)) data = f.sysread(File.size(f.path))
f.close f.close
end
data data
end end
def icon_picture def icon_picture
if icon.attached?
data = icon.blob.download
else
f = File.new(icon_picture_name, "rb") f = File.new(icon_picture_name, "rb")
data = f.sysread(File.size(f.path)) data = f.sysread(File.size(f.path))
f.close f.close
end
data data
end end
@ -119,46 +134,22 @@ class Trace < ApplicationRecord
end end
def mime_type def mime_type
filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp if file.attached?
gzipped = filetype.include?("gzip compressed") file.content_type
bzipped = filetype.include?("bzip2 compressed")
zipped = filetype.include?("Zip archive")
tarred = filetype.include?("tar archive")
if gzipped
"application/x-gzip"
elsif bzipped
"application/x-bzip2"
elsif zipped
"application/x-zip"
elsif tarred
"application/x-tar"
else else
"application/gpx+xml" content_type(trace_name)
end end
end end
def extension_name def extension_name
filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp case mime_type
gzipped = filetype.include?("gzip compressed") when "application/x-tar+gzip" then ".tar.gz"
bzipped = filetype.include?("bzip2 compressed") when "application/x-tar+x-bzip2" then ".tar.bz2"
zipped = filetype.include?("Zip archive") when "application/x-tar" then ".tar"
tarred = filetype.include?("tar archive") when "application/zip" then ".zip"
when "application/gzip" then ".gpx.gz"
if tarred && gzipped when "application/x-bzip2" then ".gpx.bz2"
".tar.gz" else ".gpx"
elsif tarred && bzipped
".tar.bz2"
elsif tarred
".tar"
elsif gzipped
".gpx.gz"
elsif bzipped
".gpx.bz2"
elsif zipped
".zip"
else
".gpx"
end end
end end
@ -207,6 +198,7 @@ class Trace < ApplicationRecord
end end
def xml_file def xml_file
with_trace_file do |trace_name|
filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp filetype = Open3.capture2("/usr/bin/file", "-Lbz", trace_name).first.chomp
gzipped = filetype.include?("gzip compressed") gzipped = filetype.include?("gzip compressed")
bzipped = filetype.include?("bzip2 compressed") bzipped = filetype.include?("bzip2 compressed")
@ -237,10 +229,12 @@ class Trace < ApplicationRecord
file file
end end
end
def import def import
logger.info("GPX Import importing #{name} (#{id}) from #{user.email}") logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
with_trace_file do |trace_name|
gpx = GPX::File.new(trace_name) gpx = GPX::File.new(trace_name)
f_lat = 0 f_lat = 0
@ -293,8 +287,8 @@ class Trace < ApplicationRecord
self.latitude = f_lat self.latitude = f_lat
self.longitude = f_lon self.longitude = f_lon
self.large_picture = gpx.picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points) image.attach(:io => gpx.picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points), :filename => "#{id}.gif", :content_type => "image/gif")
self.icon_picture = gpx.icon(min_lat, min_lon, max_lat, max_lon) icon.attach(:io => gpx.icon(min_lat, min_lon, max_lat, max_lon), :filename => "#{id}_icon.gif", :content_type => "image/gif")
self.size = gpx.actual_points self.size = gpx.actual_points
self.inserted = true self.inserted = true
save! save!
@ -304,9 +298,36 @@ class Trace < ApplicationRecord
gpx gpx
end end
end
private private
def content_type(file)
case Open3.capture2("/usr/bin/file", "-Lbz", file).first.chomp
when /.*\btar archive\b.*\bgzip\b/ then "application/x-tar+gzip"
when /.*\btar archive\b.*\bbzip2\b/ then "application/x-tar+x-bzip2"
when /.*\btar archive\b/ then "application/x-tar"
when /.*\bZip archive\b/ then "application/zip"
when /.*\bXML\b.*\bgzip\b/ then "application/gzip"
when /.*\bXML\b.*\bbzip2\b/ then "application/x-bzip2"
else "application/gpx+xml"
end
end
def with_trace_file
if file.attached?
file.open do |file|
yield file.path
end
else
yield trace_name
end
end
def set_filename
file.blob.update(:filename => "#{id}#{extension_name}") if file.attached?
end
def remove_files def remove_files
FileUtils.rm_f(trace_name) FileUtils.rm_f(trace_name)
FileUtils.rm_f(icon_picture_name) FileUtils.rm_f(icon_picture_name)

View file

@ -134,3 +134,6 @@ smtp_user_name: null
smtp_password: null smtp_password: null
# Storage services # Storage services
avatar_storage: "local" avatar_storage: "local"
trace_file_storage: "local"
trace_image_storage: "local"
trace_icon_storage: "local"

View file

@ -21,3 +21,6 @@ wikipedia_auth_secret: "dummy"
server_url: "test.host" server_url: "test.host"
# Storage services for testing # Storage services for testing
avatar_storage: "test" avatar_storage: "test"
trace_file_storage: "test"
trace_image_storage: "test"
trace_icon_storage: "test"

View file

@ -121,7 +121,7 @@ module GPX
output = StringIO.new output = StringIO.new
image.export(output) image.export(output)
output.read output
end end
def icon(min_lat, min_lon, max_lat, max_lon) def icon(min_lat, min_lon, max_lat, max_lon)
@ -161,7 +161,7 @@ module GPX
end end
end end
image.gif StringIO.new(image.gif)
end end
end end

View file

@ -119,11 +119,15 @@ module Api
# Now with some other user, which should work since the trace is public # Now with some other user, which should work since the trace is public
auth_header = basic_authorization_header create(:user).display_name, "test" auth_header = basic_authorization_header create(:user).display_name, "test"
get api_trace_data_path(public_trace_file), :headers => auth_header get api_trace_data_path(public_trace_file), :headers => auth_header
follow_redirect!
follow_redirect!
check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9" check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
# And finally we should be able to do it with the owner of the trace # And finally we should be able to do it with the owner of the trace
auth_header = basic_authorization_header public_trace_file.user.display_name, "test" auth_header = basic_authorization_header public_trace_file.user.display_name, "test"
get api_trace_data_path(public_trace_file), :headers => auth_header get api_trace_data_path(public_trace_file), :headers => auth_header
follow_redirect!
follow_redirect!
check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9" check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
end end
@ -136,7 +140,9 @@ module Api
# First get the data as is # First get the data as is
get api_trace_data_path(identifiable_trace_file), :headers => auth_header get api_trace_data_path(identifiable_trace_file), :headers => auth_header
check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/x-gzip", "gpx.gz" follow_redirect!
follow_redirect!
check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
# Now ask explicitly for XML format # Now ask explicitly for XML format
get api_trace_data_path(identifiable_trace_file, :format => "xml"), :headers => auth_header get api_trace_data_path(identifiable_trace_file, :format => "xml"), :headers => auth_header
@ -163,6 +169,8 @@ module Api
# And finally we should be able to do it with the owner of the trace # And finally we should be able to do it with the owner of the trace
auth_header = basic_authorization_header anon_trace_file.user.display_name, "test" auth_header = basic_authorization_header anon_trace_file.user.display_name, "test"
get api_trace_data_path(anon_trace_file), :headers => auth_header get api_trace_data_path(anon_trace_file), :headers => auth_header
follow_redirect!
follow_redirect!
check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701" check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
end end
@ -211,7 +219,7 @@ module Api
assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag) assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
assert_equal "trackable", trace.visibility assert_equal "trackable", trace.visibility
assert_not trace.inserted assert_not trace.inserted
assert_equal File.new(fixture).read, File.new(trace.trace_name).read assert_equal File.new(fixture).read, trace.file.blob.download
trace.destroy trace.destroy
assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
@ -229,7 +237,7 @@ module Api
assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag) assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
assert_equal "public", trace.visibility assert_equal "public", trace.visibility
assert_not trace.inserted assert_not trace.inserted
assert_equal File.new(fixture).read, File.new(trace.trace_name).read assert_equal File.new(fixture).read, trace.file.blob.download
trace.destroy trace.destroy
assert_equal "public", user.preferences.where(:k => "gps.trace.visibility").first.v assert_equal "public", user.preferences.where(:k => "gps.trace.visibility").first.v
@ -248,7 +256,7 @@ module Api
assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag) assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
assert_equal "private", trace.visibility assert_equal "private", trace.visibility
assert_not trace.inserted assert_not trace.inserted
assert_equal File.new(fixture).read, File.new(trace.trace_name).read assert_equal File.new(fixture).read, trace.file.blob.download
trace.destroy trace.destroy
assert_equal "private", second_user.preferences.where(:k => "gps.trace.visibility").first.v assert_equal "private", second_user.preferences.where(:k => "gps.trace.visibility").first.v
end end

View file

@ -369,16 +369,22 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
# First with no auth, which should work since the trace is public # First with no auth, which should work since the trace is public
get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file) get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
follow_redirect!
follow_redirect!
check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9" check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
# Now with some other user, which should work since the trace is public # Now with some other user, which should work since the trace is public
session_for(create(:user)) session_for(create(:user))
get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file) get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
follow_redirect!
follow_redirect!
check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9" check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
# And finally we should be able to do it with the owner of the trace # And finally we should be able to do it with the owner of the trace
session_for(public_trace_file.user) session_for(public_trace_file.user)
get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file) get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
follow_redirect!
follow_redirect!
check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9" check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
end end
@ -388,7 +394,9 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
# First get the data as is # First get the data as is
get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file) get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file)
check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/x-gzip", "gpx.gz" follow_redirect!
follow_redirect!
check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
# Now ask explicitly for XML format # Now ask explicitly for XML format
get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "xml") get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "xml")
@ -415,6 +423,8 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
# And finally we should be able to do it with the owner of the trace # And finally we should be able to do it with the owner of the trace
session_for(anon_trace_file.user) session_for(anon_trace_file.user)
get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file) get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
follow_redirect!
follow_redirect!
check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701" check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
end end
@ -598,7 +608,7 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag) assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
assert_equal "trackable", trace.visibility assert_equal "trackable", trace.visibility
assert_not trace.inserted assert_not trace.inserted
assert_equal File.new(fixture).read, File.new(trace.trace_name).read assert_equal File.new(fixture).read, trace.file.blob.download
trace.destroy trace.destroy
assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
end end
@ -789,19 +799,22 @@ class TracesControllerTest < ActionDispatch::IntegrationTest
end end
def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx") def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
assert_response :success
assert_equal digest, Digest::MD5.hexdigest(response.body) assert_equal digest, Digest::MD5.hexdigest(response.body)
assert_equal content_type, response.media_type assert_equal content_type, response.media_type
assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"] assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
end end
def check_trace_picture(trace) def check_trace_picture(trace)
follow_redirect!
follow_redirect!
assert_response :success assert_response :success
assert_equal "image/gif", response.media_type assert_equal "image/gif", response.media_type
assert_equal trace.large_picture, response.body assert_equal trace.large_picture, response.body
end end
def check_trace_icon(trace) def check_trace_icon(trace)
follow_redirect!
follow_redirect!
assert_response :success assert_response :success
assert_equal "image/gif", response.media_type assert_equal "image/gif", response.media_type
assert_equal trace.icon_picture, response.body assert_equal trace.icon_picture, response.body

View file

@ -17,14 +17,14 @@ FactoryBot.define do
fixture { nil } fixture { nil }
end end
after(:create) do |trace, evaluator| after(:build) do |user, evaluator|
if evaluator.fixture if evaluator.fixture
FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gpx"), user.file.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gpx")))
File.join(Settings.gpx_trace_dir, "#{trace.id}.gpx"))
FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gif"), if evaluator.inserted
File.join(Settings.gpx_image_dir, "#{trace.id}.gif")) user.image.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}.gif")))
FileUtils.copy(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}_icon.gif"), user.icon.attach(Rack::Test::UploadedFile.new(Rails.root.join("test", "gpx", "fixtures", "#{evaluator.fixture}_icon.gif")))
File.join(Settings.gpx_image_dir, "#{trace.id}_icon.gif")) end
end end
end end
end end

View file

@ -136,11 +136,11 @@ class TraceTest < ActiveSupport::TestCase
check_mime_type("a", "application/gpx+xml") check_mime_type("a", "application/gpx+xml")
check_mime_type("b", "application/gpx+xml") check_mime_type("b", "application/gpx+xml")
check_mime_type("c", "application/x-bzip2") check_mime_type("c", "application/x-bzip2")
check_mime_type("d", "application/x-gzip") check_mime_type("d", "application/gzip")
check_mime_type("f", "application/x-zip") check_mime_type("f", "application/zip")
check_mime_type("g", "application/x-tar") check_mime_type("g", "application/x-tar")
check_mime_type("h", "application/x-gzip") check_mime_type("h", "application/x-tar+gzip")
check_mime_type("i", "application/x-bzip2") check_mime_type("i", "application/x-tar+x-bzip2")
end end
def test_extension_name def test_extension_name
@ -168,24 +168,16 @@ class TraceTest < ActiveSupport::TestCase
def test_large_picture def test_large_picture
picture = File.read(Rails.root.join("test/gpx/fixtures/a.gif"), :mode => "rb") picture = File.read(Rails.root.join("test/gpx/fixtures/a.gif"), :mode => "rb")
trace = create(:trace, :fixture => "a")
trace = Trace.create
trace.large_picture = picture
assert_equal "7c841749e084ee4a5d13f12cd3bef456", md5sum(File.new(trace.large_picture_name))
assert_equal picture, trace.large_picture assert_equal picture, trace.large_picture
trace.destroy
end end
def test_icon_picture def test_icon_picture
picture = File.read(Rails.root.join("test/gpx/fixtures/a_icon.gif"), :mode => "rb") picture = File.read(Rails.root.join("test/gpx/fixtures/a_icon.gif"), :mode => "rb")
trace = create(:trace, :fixture => "a")
trace = Trace.create
trace.icon_picture = picture
assert_equal "b47baf22ed0e85d77e808694fad0ee27", md5sum(File.new(trace.icon_picture_name))
assert_equal picture, trace.icon_picture assert_equal picture, trace.icon_picture
trace.destroy
end end
def test_import_removes_previous_tracepoints def test_import_removes_previous_tracepoints
@ -215,29 +207,27 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_creates_icon def test_import_creates_icon
trace = create(:trace, :fixture => "a") trace = create(:trace, :inserted => false, :fixture => "a")
icon_path = File.join(Settings.gpx_image_dir, "#{trace.id}_icon.gif")
FileUtils.rm(icon_path) assert_not trace.icon.attached?
assert_not File.exist?(icon_path)
trace.import trace.import
assert_path_exists(icon_path) assert trace.icon.attached?
end end
def test_import_creates_large_picture def test_import_creates_large_picture
trace = create(:trace, :fixture => "a") trace = create(:trace, :inserted => false, :fixture => "a")
large_picture_path = File.join(Settings.gpx_image_dir, "#{trace.id}.gif")
FileUtils.rm(large_picture_path) assert_not trace.image.attached?
assert_not File.exist?(large_picture_path)
trace.import trace.import
assert_path_exists(large_picture_path) assert trace.image.attached?
end end
def test_import_handles_bz2 def test_import_handles_bz2
trace = create(:trace, :fixture => "c") trace = create(:trace, :inserted => false, :fixture => "c")
trace.import trace.import
@ -245,7 +235,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_plain def test_import_handles_plain
trace = create(:trace, :fixture => "a") trace = create(:trace, :inserted => false, :fixture => "a")
trace.import trace.import
@ -253,7 +243,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_plain_with_bom def test_import_handles_plain_with_bom
trace = create(:trace, :fixture => "b") trace = create(:trace, :inserted => false, :fixture => "b")
trace.import trace.import
@ -261,7 +251,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_gz def test_import_handles_gz
trace = create(:trace, :fixture => "d") trace = create(:trace, :inserted => false, :fixture => "d")
trace.import trace.import
@ -269,7 +259,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_zip def test_import_handles_zip
trace = create(:trace, :fixture => "f") trace = create(:trace, :inserted => false, :fixture => "f")
trace.import trace.import
@ -277,7 +267,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_tar def test_import_handles_tar
trace = create(:trace, :fixture => "g") trace = create(:trace, :inserted => false, :fixture => "g")
trace.import trace.import
@ -285,7 +275,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_tar_gz def test_import_handles_tar_gz
trace = create(:trace, :fixture => "h") trace = create(:trace, :inserted => false, :fixture => "h")
trace.import trace.import
@ -293,7 +283,7 @@ class TraceTest < ActiveSupport::TestCase
end end
def test_import_handles_tar_bz2 def test_import_handles_tar_bz2
trace = create(:trace, :fixture => "i") trace = create(:trace, :inserted => false, :fixture => "i")
trace.import trace.import