aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/concerns/configurable.rb26
-rw-r--r--app/services/file_service.rb23
-rw-r--r--app/services/http_service.rb36
-rw-r--r--app/services/zip_service.rb55
-rw-r--r--app/workers/workbench_import_worker.rb21
5 files changed, 156 insertions, 5 deletions
diff --git a/app/concerns/configurable.rb b/app/concerns/configurable.rb
new file mode 100644
index 000000000..c7d0f1fd9
--- /dev/null
+++ b/app/concerns/configurable.rb
@@ -0,0 +1,26 @@
+module Configurable
+
+ module ClassMethods
+ def config &blk
+ blk ? blk.(configuration) : configuration
+ end
+
+ private
+ def configuration
+ @__configuration__ ||= Rails::Application::Configuration.new
+ end
+ end
+
+ module InstanceMethods
+ private
+
+ def config
+ self.class.config
+ end
+ end
+
+ def self.included(into)
+ into.extend ClassMethods
+ into.send :include, InstanceMethods
+ end
+end
diff --git a/app/services/file_service.rb b/app/services/file_service.rb
new file mode 100644
index 000000000..efccbe24f
--- /dev/null
+++ b/app/services/file_service.rb
@@ -0,0 +1,23 @@
+module FileService extend self
+
+ def unique_filename( path, enum_with: with_ints )
+ file_names = enum_with.map( &file_name_maker(path) )
+ file_names
+ .drop_while( &File.method(:exists?) )
+ .next
+ end
+
+ def with_ints(format='%d')
+ (0..Float::INFINITY)
+ .lazy
+ .map{ |n| format % n }
+ end
+
+
+ private
+
+ def file_name_maker path
+ ->(n){ [path, n].join('_') }
+ end
+
+end
diff --git a/app/services/http_service.rb b/app/services/http_service.rb
new file mode 100644
index 000000000..a3c4d2569
--- /dev/null
+++ b/app/services/http_service.rb
@@ -0,0 +1,36 @@
+class HTTPService
+ def self.get_resource(*args)
+ new.get_resource(*args)
+ end
+
+ def get_resource(host:, path:, token: nil, params: {}, parse_json: false)
+ Faraday.new(url: host) do |c|
+ c.headers['Authorization'] = "Token token=#{token.inspect}" if token
+ c.adapter Faraday.default_adapter
+
+ resp = c.get path, params
+ if resp.status == 200
+ return parse_json ? JSON.parse(resp.body) : resp.body
+ else
+ raise "Error on api request status : #{resp.status} => #{resp.body}"
+ end
+ end
+ end
+
+ def post_resource(host:, path:, resource_name:, token: nil, params: {}, upload: nil)
+ Faraday.new(url: host) do |c|
+ c.headers['Authorization'] = "Token token=#{token.inspect}" if token
+ c.request :multipart
+ c.request :url_encoded
+ c.adapter Faraday.default_adapter
+
+ if upload
+ name = upload.keys.first
+ value, mime_type, as_name = upload.values.first
+ params.update( name => Faraday::UploadIO.new(value, mime_type, as_name ) )
+ end
+
+ c.post path, resource_name => params
+ end
+ end
+end
diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb
new file mode 100644
index 000000000..778bfd06d
--- /dev/null
+++ b/app/services/zip_service.rb
@@ -0,0 +1,55 @@
+class ZipService
+
+ attr_reader :current_entry, :zip_data
+
+ def initialize data
+ @zip_data = data
+ @current_entry = nil
+ end
+
+ class << self
+ def convert_entries entries
+ -> output_stream do
+ entries.each do |e|
+ output_stream.put_next_entry e.name
+ output_stream.write e.get_input_stream.read
+ end
+ end
+ end
+
+ def entries input_stream
+ Enumerator.new do |enum|
+ loop{ enum << input_stream.get_next_entry }
+ end.lazy.take_while{ |e| e }
+ end
+ end
+
+ def entry_groups
+ self.class.entries(input_stream).group_by(&method(:entry_key))
+ end
+
+ def entry_group_streams
+ entry_groups.map(&method(:make_stream)).to_h
+ end
+
+ def entry_key entry
+ entry.name.split('/', -1)[-2]
+ end
+
+ def make_stream pair
+ name, entries = pair
+ [name, make_stream_from( entries )]
+ end
+
+ def make_stream_from entries
+ Zip::OutputStream.write_buffer(&self.class.convert_entries(entries))
+ end
+
+ def next_entry
+ @current_entry = input_stream.get_next_entry
+ end
+
+ def input_stream
+ @__input_stream__ ||= Zip::InputStream.open(StringIO.new(zip_data))
+ end
+end
diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb
index 18d3ae112..d1a381e0c 100644
--- a/app/workers/workbench_import_worker.rb
+++ b/app/workers/workbench_import_worker.rb
@@ -1,6 +1,7 @@
class WorkbenchImportWorker
include Sidekiq::Worker
include Rails.application.routes.url_helpers
+ include Configurable
attr_reader :import, :downloaded
@@ -17,18 +18,22 @@ class WorkbenchImportWorker
path: import_path,
params: {token: import.token_download})
- Tempfile.open( do | tmpfile |
- tmpfile.write zipfile_data
- @downloaded = tmpfile.path
+ path = File.join(config.dir, import.name.gsub(%r{\s+}, '-'))
+ unique_path = FileService.unique_filename path
+ Dir.mkdir unique_path
+ @downloaded = File.join(unique_path, import.name)
+ File.open(downloaded, 'wb') do | file |
+ file.write zipfile_data
end
- if one_entry?
- upload(@downloaded)
+ if single_entry?
+ upload(downloaded)
else
split_zip.each(&method(:upload))
end
end
+
def single_entry?
true
end
@@ -40,6 +45,12 @@ class WorkbenchImportWorker
def upload zip_file
end
+ # Memoized Values
+
+ def dirname
+ @__dirname__ ||= make_unique_dir
+ end
+
def import_host
@__import_host__ ||= Rails.application.config.front_end_host
end