aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert2017-07-26 08:13:43 +0200
committerRobert2017-07-26 14:35:42 +0200
commitd385a6da731dc6b3ec0ec5bec1e94eb2dcff5efb (patch)
tree0e2113f5292a7929d3a3e34d06121302b0f70949
parentfe46c7832fa1e0c6af450f0937aea3534c0f6b01 (diff)
downloadchouette-core-d385a6da731dc6b3ec0ec5bec1e94eb2dcff5efb.tar.bz2
Refs: #3507@4h; Finished Basic WorkbenchImportWorker
- speced but missing error treatment
-rw-r--r--app/models/api/v1/api_key.rb22
-rw-r--r--app/models/organisation.rb2
-rw-r--r--app/models/user.rb2
-rw-r--r--app/services/file_service.rb35
-rw-r--r--app/services/http_service.rb11
-rw-r--r--app/workers/workbench_import_worker.rb83
-rw-r--r--spec/models/api/v1/api_key_spec.rb31
-rw-r--r--spec/models/organisation_spec.rb2
-rw-r--r--spec/services/file_service_spec.rb25
-rw-r--r--spec/workers/workbench_import_worker_spec.rb62
10 files changed, 168 insertions, 107 deletions
diff --git a/app/models/api/v1/api_key.rb b/app/models/api/v1/api_key.rb
index 7390db232..e1a7ab5a4 100644
--- a/app/models/api/v1/api_key.rb
+++ b/app/models/api/v1/api_key.rb
@@ -3,9 +3,20 @@ module Api
class ApiKey < ::ActiveRecord::Base
before_create :generate_access_token
belongs_to :referential, :class_name => '::Referential'
+ validates_presence_of :referential
- def self.model_name
- ActiveModel::Name.new self, Api::V1, self.name.demodulize
+ class << self
+ def from(referential, name:)
+ find_or_create_by!(name: name, referential: referential)
+ end
+ def model_name
+ ActiveModel::Name.new Api::V1, self.name.demodulize
+ end
+ def referential_from_token(token)
+ array = token.split('-')
+ return nil unless array.size==2
+ ::Referential.find( array.first)
+ end
end
def eql?(other)
@@ -13,16 +24,11 @@ module Api
other.token == self.token
end
- def self.referential_from_token(token)
- array = token.split('-')
- return nil unless array.size==2
- ::Referential.find( array.first)
- end
private
def generate_access_token
begin
- self.token = "#{referential.id}-#{SecureRandom.hex}"
+ self.token = "#{referential_id}-#{SecureRandom.hex}"
end while self.class.exists?(:token => self.token)
end
end
diff --git a/app/models/organisation.rb b/app/models/organisation.rb
index a3c5da1af..7e571e78d 100644
--- a/app/models/organisation.rb
+++ b/app/models/organisation.rb
@@ -27,7 +27,7 @@ class Organisation < ActiveRecord::Base
conf = Rails.application.config.try(:stif_portail_api)
raise 'Rails.application.config.stif_portail_api configuration is not defined' unless conf
- AF83::HTTPFetcher.get_resource(
+ HTTPService.get_resource(
host: conf[:url],
path: '/api/v1/organizations',
parse_json: true,
diff --git a/app/models/user.rb b/app/models/user.rb
index fbffd96be..1dc5975e1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -66,7 +66,7 @@ class User < ActiveRecord::Base
conf = Rails.application.config.try(:stif_portail_api)
raise 'Rails.application.config.stif_portail_api settings is not defined' unless conf
- AF83::HTTPFetcher.get_resource(
+ HTTPService.get_resource(
host: conf[:url],
path: '/api/v1/users',
parse_json: true,
diff --git a/app/services/file_service.rb b/app/services/file_service.rb
index efccbe24f..3b3ff3561 100644
--- a/app/services/file_service.rb
+++ b/app/services/file_service.rb
@@ -1,23 +1,24 @@
-module FileService extend self
+# TODO: Delete me after stable implementation of #1726
+# 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 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
+# def with_ints(format='%d')
+# (0..Float::INFINITY)
+# .lazy
+# .map{ |n| format % n }
+# end
- private
+# private
- def file_name_maker path
- ->(n){ [path, n].join('_') }
- end
+# def file_name_maker path
+# ->(n){ [path, n].join('_') }
+# end
-end
+# end
diff --git a/app/services/http_service.rb b/app/services/http_service.rb
index a3c4d2569..37f1621d5 100644
--- a/app/services/http_service.rb
+++ b/app/services/http_service.rb
@@ -1,7 +1,4 @@
-class HTTPService
- def self.get_resource(*args)
- new.get_resource(*args)
- end
+module HTTPService extend self
def get_resource(host:, path:, token: nil, params: {}, parse_json: false)
Faraday.new(url: host) do |c|
@@ -17,6 +14,12 @@ class HTTPService
end
end
+ # host: 'http://localhost:3000',
+ # path: '/api/v1/netex_imports.json',
+ # resource_name: 'netex_import',
+ # token: '13-74009c36638f587c9eafb1ce46e95585',
+ # params: {referential_id: 13, workbench_id: 1},
+ # upload: {file: [StringIO.new('howdy'), 'application/zip', 'greeting']})
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
diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb
index d1a381e0c..2973d97c5 100644
--- a/app/workers/workbench_import_worker.rb
+++ b/app/workers/workbench_import_worker.rb
@@ -3,65 +3,88 @@ class WorkbenchImportWorker
include Rails.application.routes.url_helpers
include Configurable
- attr_reader :import, :downloaded
+
+ # Workers
+ # =======
def perform(import_id)
@import = Import.find(import_id)
@downloaded = nil
download
+ @zip_service = ZipService.new(@zipfile_data)
+ upload
end
def download
logger.warn "HTTP GET #{import_url}"
- zipfile_data = AF83::HTTPFetcher.get_resource(
+ @zipfile_data = HTTPService.get_resource(
host: import_host,
path: import_path,
- params: {token: import.token_download})
-
- 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 single_entry?
- upload(downloaded)
- else
- split_zip.each(&method(:upload))
- end
+ params: {token: @import.token_download})
+
+ # TODO: Delete me after stable implementation of #1726
+ # 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
end
- def single_entry?
- true
+ def upload
+ @zip_service.entry_group_streams.each(&method(:upload_entry_group))
end
- def split_zip
- []
+ def upload_entry_group key_pair
+ eg_name, eg_stream = key_pair
+ logger.warn "HTTP POST #{export_url} (for #{complete_entry_group_name(eg_name)})"
+ HTTPService.post_resource(
+ host: export_host,
+ path: export_path,
+ resource_name: 'netex_import',
+ token: token(eg_name),
+ params: params,
+ upload: {file: [eg_stream, 'application/zip', eg_name]})
+ end
+
+
+ # Queries
+ # =======
+
+ def complete_entry_group_name entry_group_name
+ [@import.name, entry_group_name].join("--")
end
- def upload zip_file
+ def token entry_group_name
+ Api::V1::ApiKey.from(@import.referential, name: complete_entry_group_name(entry_group_name)).token
end
- # Memoized Values
+ # Constants
+ # =========
- def dirname
- @__dirname__ ||= make_unique_dir
+ def export_host
+ Rails.application.config.front_end_host
+ end
+ def export_path
+ '/api/v1/netex_imports.json'
+ end
+ def export_url
+ @__export_url__ ||= File.join(export_host, export_path)
end
def import_host
- @__import_host__ ||= Rails.application.config.front_end_host
+ Rails.application.config.front_end_host
end
def import_path
- @__import_path__ ||= File.join(download_workbench_import_path(import.workbench, import))
- end
- def import_uri
- @__import_uri__ ||= URI(import_url)
+ @__import_path__ ||= File.join(download_workbench_import_path(@import.workbench, @import))
end
def import_url
@__import_url__ ||= File.join(import_host, import_path)
end
+ def params
+ @__params__ ||= { referential_id: @import.referential_id, workbench_id: @import.workbench_id }
+ end
end
diff --git a/spec/models/api/v1/api_key_spec.rb b/spec/models/api/v1/api_key_spec.rb
index 8a34c9221..5f39a65e4 100644
--- a/spec/models/api/v1/api_key_spec.rb
+++ b/spec/models/api/v1/api_key_spec.rb
@@ -1,11 +1,34 @@
describe Api::V1::ApiKey, :type => :model do
- let!(:referential){create(:referential)}
- subject { Api::V1::ApiKey.create( :name => "test", :referential => referential)}
- it "test" do
- expect(subject).to be_valid
+ let(:referential){ create :referential }
+
+ subject { described_class.create( :name => "test", :referential => referential)}
+
+ it "validity test" do
+ expect_it.to be_valid
expect(subject.referential).to eq(referential)
+ end
+
+ context 'Creation' do
+ let( :name ){ SecureRandom.urlsafe_base64 }
+
+ it 'can be created from a referential with a name, iff needed' do
+ # 1st time create a new record
+ expect{ described_class.from(referential, name: name) }.to change{ described_class.count }.by(1)
+ expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
+ referential.id, name
+ ])
+
+ # 2nd time get the same record
+ expect{ described_class.from(referential, name: name) }.not_to change{ described_class.count }
+ expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
+ referential.id, name
+ ])
+ end
+ it 'cannot be created without a referential' do
+ expect{ described_class.from(nil, name:name) rescue nil }.not_to change{ described_class.count }
+ end
end
end
diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb
index 1cce7e846..b16324a56 100644
--- a/spec/models/organisation_spec.rb
+++ b/spec/models/organisation_spec.rb
@@ -1,5 +1,3 @@
-require 'spec_helper'
-
describe Organisation, :type => :model do
it { should validate_presence_of(:name) }
it { should validate_uniqueness_of(:code) }
diff --git a/spec/services/file_service_spec.rb b/spec/services/file_service_spec.rb
index 90e164408..4426ee145 100644
--- a/spec/services/file_service_spec.rb
+++ b/spec/services/file_service_spec.rb
@@ -1,16 +1,17 @@
-RSpec.describe FileService do
+# TODO: Delete me after stable implementation of #1726
+# RSpec.describe FileService do
- it 'computes a unique filename' do
- expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( false )
+# it 'computes a unique filename' do
+# expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( false )
- expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_0')
- end
+# expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_0')
+# end
- it 'handles duplicate names by means of a counter' do
- expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( true )
- expect( File ).to receive(:exists?).with('xxx/yyy_1').and_return( true )
- expect( File ).to receive(:exists?).with('xxx/yyy_2').and_return( false )
+# it 'handles duplicate names by means of a counter' do
+# expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( true )
+# expect( File ).to receive(:exists?).with('xxx/yyy_1').and_return( true )
+# expect( File ).to receive(:exists?).with('xxx/yyy_2').and_return( false )
- expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_2')
- end
-end
+# expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_2')
+# end
+# end
diff --git a/spec/workers/workbench_import_worker_spec.rb b/spec/workers/workbench_import_worker_spec.rb
index d227c7610..68e429b60 100644
--- a/spec/workers/workbench_import_worker_spec.rb
+++ b/spec/workers/workbench_import_worker_spec.rb
@@ -2,54 +2,60 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
let( :worker ) { described_class.new }
let( :import ){ build_stubbed :import, token_download: download_token, file: File.open(zip_file) }
+
let( :workbench ){ import.workbench }
let( :referential ){ import.referential }
+ let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{SecureRandom.hex}" }
+ let( :params ){ {referential_id: referential.id, workbench_id: workbench.id} }
# http://www.example.com/workbenches/:workbench_id/imports/:id/download
- let( :url ){ "#{File.join(host, path)}?token=#{download_token}" }
let( :host ){ Rails.configuration.front_end_host }
let( :path ){ download_workbench_import_path(workbench, import) }
- let( :result ){ import.file.read }
+ let( :downloaded_zip ){ double("downloaded zip") }
let( :download_token ){ SecureRandom.urlsafe_base64 }
+ let( :upload_path ) { '/api/v1/netex_imports.json' }
+
+ let( :entry_group_streams ) do
+ 2.times.map{ |i| double( "entry group stream #{i}" ) }
+ end
+ let( :entry_groups ) do
+ 2.times.map do | i |
+ {"entry_group_name#{i}" => entry_group_streams[i] }
+ end
+ end
+
+ let( :zip_service ){ double("zip service") }
+
before do
# That should be `build_stubbed's` job, no?
allow(Import).to receive(:find).with(import.id).and_return(import)
+ allow(Api::V1::ApiKey).to receive(:from).and_return(api_key)
+ allow(ZipService).to receive(:new).with(downloaded_zip).and_return zip_service
+ expect(zip_service).to receive(:entry_group_streams).and_return(entry_groups)
end
- context 'multireferential zipfile' do
+ context 'multireferential zipfile' do
let( :zip_file ){ File.join(fixture_path, 'multiref.zip') }
it 'downloads a zip file' do
- default_headers = {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}
- stub_request(:get, url)
- .with(headers: default_headers)
- .to_return(body: result)
-
- worker.perform import.id
-
- require 'pry'
- binding.pry
- expect( File.read(worker.downloaded) ).to eq( result )
- expect( worker ).not_to be_single_entry
- end
- end
-
- context 'unireferential zipfile' do
- let( :zip_file ){ File.join(fixture_path, 'uniref.zip') }
-
- it 'downloads a zip file' do
- default_headers = {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}
- stub_request(:get, url)
- .with(headers: default_headers)
- .to_return(body: result)
-
+ expect(HTTPService).to receive(:get_resource)
+ .with(host: host, path: path, params: {token: download_token})
+ .and_return( downloaded_zip )
+
+ entry_groups.each do | entry_group_name, entry_group_stream |
+ expect( HTTPService ).to receive(:post_resource)
+ .with(host: host,
+ path: upload_path,
+ resource_name: 'netex_import',
+ token: api_key.token,
+ params: params,
+ upload: {file: [entry_group_stream, 'application/zip', entry_group_name]})
+ end
worker.perform import.id
- expect( File.read(worker.downloaded) ).to eq( result )
- expect( worker ).to be_single_entry
end
end