From 8ac9d19e73737c6591be851cb8790f57e280ad16 Mon Sep 17 00:00:00 2001 From: Steven Miers Date: Mon, 15 Dec 2014 18:02:51 -0600 Subject: [PATCH] VRFS-2481 : Use jam_tracks object hierarchy to create jkz file, and upload to AWS. Meshed out spec to verify creation and upload, including a real ogg file (required by the python tool). --- ruby/lib/jam_ruby/jam_tracks_manager.rb | 92 +++++++++++++----- ruby/lib/jam_ruby/models/jam_track.rb | 6 +- ruby/lib/jam_ruby/models/jam_track_right.rb | 19 ++++ ruby/spec/files/on.ogg | Bin 0 -> 4303 bytes .../jam_ruby/models/jam_track_right_spec.rb | 54 +++++++++- 5 files changed, 141 insertions(+), 30 deletions(-) create mode 100644 ruby/spec/files/on.ogg diff --git a/ruby/lib/jam_ruby/jam_tracks_manager.rb b/ruby/lib/jam_ruby/jam_tracks_manager.rb index 1c4b481aa..5f63365f1 100644 --- a/ruby/lib/jam_ruby/jam_tracks_manager.rb +++ b/ruby/lib/jam_ruby/jam_tracks_manager.rb @@ -1,6 +1,8 @@ require 'json' require 'tempfile' require 'open3' +require 'fileutils' +require 'open-uri' module JamRuby @@ -8,31 +10,69 @@ module JamRuby class JamTracksManager class << self def save_jam_track_jkz(user, jam_track) - py_root = File.expand_path(File.join("..", "..", "jamtracks")) - tmp_dir = Dir::Tmpname.make_tmpname("/tmp/jamtrack", nil) - puts "Executing python in #{py_root}, outputting to #{tmp_dir}" - - - sku=jam_track.id - tracks_filename=tmp_dir + "/jamtrack.info" - output_jkz="tmp_dir/#{jam_track.name.tableize}.jkz" - title=jam_track.name - - # From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819: - #Open3.popen3("ls") do |stdin, stdout, stderr, wait_thr| - Open3.popen3("python", - "#{py_root}/jkcreate.py", - "-D -k #{sku} -c art.png -p #{tmp_dir}/pkey.pem -s #{tmp_dir}/skey.pem -I #{tracks_filename} -o #{output_jkz} -t '#{title}'" - ) do |stdin, stdout, stderr, wait_thr| - pid = wait_thr.pid - exit_status = wait_thr.value - err = stderr.read(1000) - raise ArgumentError, "Error calling python script: #{err}" if err.present? - end - - tmp_dir + jam_track_right = jam_track.right_for_user(user) + raise ArgumentError if jam_track_right.nil? + save_jam_track_right_jkz(jam_track_right) end - end - end -end + def save_jam_track_right_jkz(jam_track_right) + jam_track = jam_track_right.jam_track + py_root = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "jamtracks")) + + Dir.mktmpdir do |tmp_dir| + jam_file_opts="" + jam_track.jam_track_tracks.each do |jam_track_track| + nm=jam_track_track.filename + nm.gsub!(" ", "_") + track_filename = File.join(tmp_dir, nm) + track_url = jam_track_track.sign_url + copy_url_to_file(track_url, track_filename) + jam_file_opts << " -i '#{track_filename}+#{jam_track_track.part}'" + end + + sku=jam_track.id + title=jam_track.name + output_jkz=File.join(tmp_dir, "#{title.parameterize}.jkz") + py_file = File.join(py_root, "jkcreate.py") + puts "Executing python source in #{py_file}, outputting to #{tmp_dir} (#{output_jkz})" + + # From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819: + cli = "python #{py_file} -D -k #{sku} -p #{tmp_dir}/pkey.pem -s #{tmp_dir}/skey.pem #{jam_file_opts} -o #{output_jkz} -t '#{title}'" + Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr| + pid = wait_thr.pid + exit_status = wait_thr.value + err = stderr.read(1000) + out = stdout.read(1000) + #puts "stdout: #{out}, stderr: #{err}" + raise ArgumentError, "Error calling python script: #{out}" if out && (out.index("No track files specified") || out.index("Cannot find file")) + raise ArgumentError, "Error calling python script: #{err}" if err.present? + jam_track_right[:url] + + jam_track_right.url.store!(File.open(output_jkz)) + jam_track_right.save! + end + end # mktmpdir + jam_track_right + end # save_jam_track_jkz + + def copy_url_to_file(url, filename) + uri = URI(url) + open(filename, 'wb') do |io| + Net::HTTP.start(uri.host, uri.port) do |http| + request = Net::HTTP::Get.new uri + http.request request do |response| + response_code = response.code.to_i + unless response_code >= 200 && response_code <= 299 + raise "bad status code: #{response_code}. body: #{response.body}" + end + response.read_body do |chunk| + io.write chunk + end + end + end + end + end # copy_url_to_file + + end # self + end # class +end # module diff --git a/ruby/lib/jam_ruby/models/jam_track.rb b/ruby/lib/jam_ruby/models/jam_track.rb index f93087046..3658a2fc1 100644 --- a/ruby/lib/jam_ruby/models/jam_track.rb +++ b/ruby/lib/jam_ruby/models/jam_track.rb @@ -43,7 +43,7 @@ module JamRuby has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'position ASC' - has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight", inverse_of: 'jam_track', :foreign_key => "jam_track_id" + has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight" #, inverse_of: 'jam_track', :foreign_key => "jam_track_id" has_many :owners, :through => :jam_track_rights, :class_name => "JamRuby::User", :source => :user accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true @@ -107,6 +107,10 @@ module JamRuby #JamTrack.joins(:recording).joins(:recording => :claimed_recordings) end + def right_for_user(user) + jam_track_rights.where("user_id=?", user).first + end + private diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb index 33a036a05..81b6cbc10 100644 --- a/ruby/lib/jam_ruby/models/jam_track_right.rb +++ b/ruby/lib/jam_ruby/models/jam_track_right.rb @@ -2,6 +2,7 @@ module JamRuby # describes what users have rights to which tracks class JamTrackRight < ActiveRecord::Base + include JamRuby::S3ManagerMixin attr_accessible :user, :jam_track, :user_id, :jam_track_id, :url, :md5, :length, :download_count belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track belongs_to :jam_track, class_name: "JamRuby::JamTrack" @@ -16,6 +17,15 @@ module JamRuby mount_uploader :url, JamTrackRightUploader MAX_JAM_TRACK_DOWNLOADS = 1000 + + def store_dir + "#{jam_track.store_dir}/rights" + end + + # create name of the file + def filename + "#{jam_track.name}.jkz" + end def verify_download_count if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !@current_user.admin @@ -28,5 +38,14 @@ module JamRuby end + # creates a short-lived URL that has access to the object. + # the idea is that this is used when a user who has the rights to this tries to download this JamTrack + # we would verify their rights (can_download?), and generates a URL in response to the click so that they can download + # but the url is short lived enough so that it wouldn't be easily shared + def sign_url(expiration_time = 120) + s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'jkz', :secure => false}) + end + + end end diff --git a/ruby/spec/files/on.ogg b/ruby/spec/files/on.ogg new file mode 100644 index 0000000000000000000000000000000000000000..743d6e3aa6ca187978d95bb768ef449e0ccc6071 GIT binary patch literal 4303 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 literal 0 HcmV?d00001 diff --git a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb index 1df21358f..5dea3c4fe 100644 --- a/ruby/spec/jam_ruby/models/jam_track_right_spec.rb +++ b/ruby/spec/jam_ruby/models/jam_track_right_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' describe JamTrackRight do - + include UsesTempFiles + include CarrierWave::Test::Matchers it "created" do jam_track_right = FactoryGirl.create(:jam_track_right) @@ -28,13 +29,60 @@ describe JamTrackRight do end end - it "saves JKZ" do + describe "JKZ" do + before(:all) do + original_storage = JamTrackTrackUploader.storage = :fog + original_storage = JamTrackRightUploader.storage = :fog + end + + after(:all) do + JamTrackTrackUploader.storage = @original_storage + JamTrackRightUploader.storage = @original_storage + end + + before(:each) do + #content_for_file('abc') + end + + it "should fail if no tracks" do user = FactoryGirl.create(:user) jam_track = FactoryGirl.create(:jam_track) right = JamTrackRight.create(:user=>user, :jam_track=>jam_track) expect { JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track) - }.to_not raise_error + }.to raise_error(ArgumentError) + end + + it "should create" do + ogg_path = File.join('spec', 'files', 'on.ogg') + user = FactoryGirl.create(:user) + #jam_track = FactoryGirl.create(:jam_track) + jam_track_track = FactoryGirl.create(:jam_track_track) + jam_track = jam_track_track.jam_track + + uploader = JamTrackTrackUploader.new(jam_track_track, :url) + uploader.store!(File.open(ogg_path)) + jam_track_track.save! + + jam_track_track[:url].should == jam_track_track.store_dir + '/' + jam_track_track.filename + + # verify it's on S3 + s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) + s3.exists?(jam_track_track[:url]).should be_true + s3.length(jam_track_track[:url]).should == File.size?(ogg_path) + + jam_track_right = JamTrackRight.create(:user=>user, :jam_track=>jam_track) + expect { + JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track) + }.to_not raise_error(ArgumentError) + jam_track_right.reload + jam_track_right[:url].should == jam_track_right.store_dir + '/' + jam_track_right.filename + + # verify it's on S3 + s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key) + s3.exists?(jam_track_right[:url]).should be_true + s3.length(jam_track_right[:url]).should > File.size?(ogg_path) + end end end