sdr-client 0.16.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6d44bbb8b087e0045328a2b8625654ad9f7eaadf7c968c5ee5402683dc04d26
4
- data.tar.gz: 9808626f7cad4548ccce883253245c80fc18fac9cd14353dcb008cb8c1cf365a
3
+ metadata.gz: 1ae3d332b62dd4908555f961ffa5f9ebc12e0388836f36f855672731d8b940a1
4
+ data.tar.gz: 97c3c18fc7e4ed98b5577ea24390eef9f2ecbf8c24970c92fd3d3097a13b5492
5
5
  SHA512:
6
- metadata.gz: e14bf4032db046e886a7ef02cc1183fab23806bf0b450527ad8e33f396d3cac1f2d254644e9f9e2179d38c04d200a4cdf09eb07515aabf0e8a7a2c7ad9367fd1
7
- data.tar.gz: 39e311b8bb036dd2abff468086103be8e55516b1490d219c4c34e5b68b0c80322af47efd0dcc198ee11e3e24e484d7d206102f20e415ccfa171abd7d61d6fde5
6
+ metadata.gz: f03baa42607cd68d3b814e46df38dda0567ca78082292faaf5ec47dfe518b68e0399f25305a89bed835bf68cde2e680f553646b4c921490ae06c7e426a812c5f
7
+ data.tar.gz: d392e1bfda994e6266ca4e6e1834036e76a5cfd37008c6ceda87ed6c20d4cbae9becef1fe8f47e3631f824dae7ae883735e0718dec7161488763d891f9d57121
@@ -13,6 +13,7 @@ Layout/LineLength:
13
13
  Metrics/BlockLength:
14
14
  Exclude:
15
15
  - 'spec/**/*'
16
+ - 'sdr-client.gemspec'
16
17
  ExcludedMethods:
17
18
  - 'OptionParser.new'
18
19
 
@@ -2,13 +2,17 @@
2
2
 
3
3
  require 'dry/monads'
4
4
  require 'faraday'
5
+ require 'active_support'
6
+ require 'active_support/core_ext/object/json'
5
7
 
6
8
  require 'sdr_client/version'
7
9
  require 'sdr_client/deposit'
10
+ require 'sdr_client/model_deposit'
8
11
  require 'sdr_client/credentials'
9
12
  require 'sdr_client/login'
10
13
  require 'sdr_client/login_prompt'
11
14
  require 'sdr_client/cli'
15
+ require 'sdr_client/connection'
12
16
 
13
17
  module SdrClient
14
18
  class Error < StandardError; end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ # The connection to the server
5
+ class Connection
6
+ def initialize(url:, token: Credentials.read)
7
+ @url = url
8
+ @token = token
9
+ end
10
+
11
+ def connection
12
+ @connection ||= Faraday.new(url: url) do |conn|
13
+ conn.authorization :Bearer, token
14
+ conn.adapter :net_http
15
+ end
16
+ end
17
+
18
+ delegate :put, :post, to: :connection
19
+
20
+ private
21
+
22
+ attr_reader :url, :token
23
+ end
24
+ end
@@ -25,8 +25,6 @@ module SdrClient
25
25
  files_metadata: {},
26
26
  grouping_strategy: SingleFileGroupingStrategy,
27
27
  logger: Logger.new(STDOUT))
28
- token = Credentials.read
29
-
30
28
  augmented_metadata = FileMetadataBuilder.build(files: files, files_metadata: files_metadata)
31
29
  metadata = Request.new(label: label,
32
30
  type: type,
@@ -41,7 +39,8 @@ module SdrClient
41
39
  embargo_access: embargo_access,
42
40
  viewing_direction: viewing_direction,
43
41
  files_metadata: augmented_metadata)
44
- Process.new(metadata: metadata, url: url, token: token, files: files,
42
+ connection = Connection.new(url: url)
43
+ Process.new(metadata: metadata, connection: connection, files: files,
45
44
  grouping_strategy: grouping_strategy, logger: logger).run
46
45
  end
47
46
  # rubocop:enable Metrics/MethodLength
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module SdrClient
6
+ module Deposit
7
+ # The process for doing a deposit from a Cocina Model
8
+ class ModelProcess
9
+ DRO_PATH = '/v1/resources'
10
+ # @param [Cocina::Model::RequestDRO] request_dro for depositing
11
+ # @param [String] url the server to send to
12
+ # @param [String] token the bearer auth token for the server
13
+ # @param [Array<String>] files a list of file names to upload
14
+ # @param [Logger] logger the logger to use
15
+ def initialize(request_dro:, url:,
16
+ token:, files: [], logger: Logger.new(STDOUT))
17
+ @files = files
18
+ @url = url
19
+ @token = token
20
+ @request_dro = request_dro
21
+ @logger = logger
22
+ end
23
+
24
+ def run
25
+ check_files_exist
26
+ child_files_match
27
+
28
+ upload_responses = UploadFiles.new(files: files,
29
+ logger: logger,
30
+ connection: connection,
31
+ mime_types: mime_types).run
32
+ new_request_dro = with_external_identifiers(upload_responses)
33
+ upload_request_dro(new_request_dro.to_json)
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :request_dro, :files, :url, :token, :logger
39
+
40
+ def check_files_exist
41
+ logger.info('checking to see if files exist')
42
+ files.each do |file_name|
43
+ raise Errno::ENOENT, file_name unless ::File.exist?(file_name)
44
+ end
45
+ end
46
+
47
+ def child_files_match
48
+ # Files without request files.
49
+ files.each do |filepath|
50
+ filename = ::File.basename(filepath)
51
+
52
+ raise "Request file not provided for #{filepath}" if request_files[filename].nil?
53
+ end
54
+
55
+ # Request files without files
56
+ filenames = files.map { |filepath| ::File.basename(filepath) }
57
+ request_files.keys.each do |request_filename|
58
+ raise "File not provided for request file #{request_filename}" unless filenames.include?(request_filename)
59
+ end
60
+ end
61
+
62
+ # @return [Hash<Symbol,String>] the result of the metadata call
63
+ def upload_request_dro(request_json)
64
+ logger.info("Starting upload metadata: #{request_json}")
65
+ response = connection.post(DRO_PATH, request_json, 'Content-Type' => 'application/json')
66
+ unexpected_response(response) unless response.status == 201
67
+
68
+ logger.info("Response from server: #{response.body}")
69
+
70
+ { druid: JSON.parse(response.body)['druid'], background_job: response.headers['Location'] }
71
+ end
72
+
73
+ def unexpected_response(response)
74
+ raise "There was an error with your request: #{response.body}" if response.status == 400
75
+ raise 'There was an error with your credentials. Perhaps they have expired?' if response.status == 401
76
+
77
+ raise "unexpected response: #{response.status} #{response.body}"
78
+ end
79
+
80
+ def connection
81
+ @connection ||= Faraday.new(url: url) do |conn|
82
+ conn.authorization :Bearer, token
83
+ conn.adapter :net_http
84
+ end
85
+ end
86
+
87
+ # Map of filenames to mimetypes
88
+ def mime_types
89
+ @mime_types ||=
90
+ Hash[
91
+ request_files.map do |filename, file|
92
+ [filename, file.hasMimeType || 'application/octet-stream']
93
+ end
94
+ ]
95
+ end
96
+
97
+ # Map of filenames to request files
98
+ def request_files
99
+ @request_files ||=
100
+ Hash[
101
+ request_dro.structural.contains.map do |file_set|
102
+ file_set.structural.contains.map do |file|
103
+ [file.filename, file]
104
+ end
105
+ end.flatten(1)
106
+ ]
107
+ end
108
+
109
+ def with_external_identifiers(upload_responses)
110
+ signed_id_map = Hash[upload_responses.map { |response| [response.filename, response.signed_id] }]
111
+
112
+ # Manipulating request_dro as hash since immutable
113
+ request_dro_hash = request_dro.to_h
114
+ request_dro_hash[:structural][:contains].each do |file_set|
115
+ file_set[:structural][:contains].each do |file|
116
+ file[:externalIdentifier] = signed_id_map[file[:filename]]
117
+ end
118
+ end
119
+
120
+ Cocina::Models::RequestDRO.new(request_dro_hash)
121
+ end
122
+ end
123
+ end
124
+ end
@@ -9,28 +9,24 @@ module SdrClient
9
9
  DRO_PATH = '/v1/resources'
10
10
  # @param [Request] metadata information about the object
11
11
  # @param [Class] grouping_strategy class whose run method groups an array of uploads
12
- # @param [String] url the server to send to
13
- # @param [String] token the bearer auth token for the server
12
+ # @param [String] connection the server connection to use
14
13
  # @param [Array<String>] files a list of file names to upload
15
14
  # @param [Logger] logger the logger to use
16
- # rubocop:disable Metrics/ParameterLists
17
- def initialize(metadata:, grouping_strategy: SingleFileGroupingStrategy, url:,
18
- token:, files: [], logger: Logger.new(STDOUT))
15
+ def initialize(metadata:, grouping_strategy: SingleFileGroupingStrategy,
16
+ connection:, files: [], logger: Logger.new(STDOUT))
19
17
  @files = files
20
- @url = url
21
- @token = token
18
+ @connection = connection
22
19
  @metadata = metadata
23
20
  @logger = logger
24
21
  @grouping_strategy = grouping_strategy
25
22
  end
26
- # rubocop:enable Metrics/ParameterLists
27
23
 
28
24
  def run
29
25
  check_files_exist
30
26
  upload_responses = UploadFiles.new(files: files,
31
27
  logger: logger,
32
28
  connection: connection,
33
- metadata: metadata).run
29
+ mime_types: mime_types).run
34
30
  metadata_builder = MetadataBuilder.new(metadata: metadata,
35
31
  grouping_strategy: grouping_strategy,
36
32
  logger: logger)
@@ -40,7 +36,7 @@ module SdrClient
40
36
 
41
37
  private
42
38
 
43
- attr_reader :metadata, :files, :url, :token, :logger, :grouping_strategy
39
+ attr_reader :metadata, :files, :connection, :logger, :grouping_strategy
44
40
 
45
41
  def check_files_exist
46
42
  logger.info('checking to see if files exist')
@@ -68,11 +64,14 @@ module SdrClient
68
64
  raise "unexpected response: #{response.status} #{response.body}"
69
65
  end
70
66
 
71
- def connection
72
- @connection ||= Faraday.new(url: url) do |conn|
73
- conn.authorization :Bearer, token
74
- conn.adapter :net_http
75
- end
67
+ def mime_types
68
+ @mime_types ||=
69
+ Hash[
70
+ files.map do |filepath|
71
+ filename = ::File.basename(filepath)
72
+ [filename, metadata.for(filename)['mime_type']]
73
+ end
74
+ ]
76
75
  end
77
76
  end
78
77
  end
@@ -7,13 +7,13 @@ module SdrClient
7
7
  # The file uploading part of a deposit
8
8
  class UploadFiles
9
9
  BLOB_PATH = '/v1/direct_uploads'
10
- # @param [Array<String>] files a list of file names to upload
10
+ # @param [Array<String>] files a list of filepaths to upload
11
11
  # @param [Logger] logger the logger to use
12
- # @param [Faraday::Connection] connection
13
- # @param [Request] metadata information about the object
14
- def initialize(files:, metadata:, logger:, connection:)
12
+ # @param [Connection] connection
13
+ # @param [Hash<String,String] mime_types a map of filenames to mime types
14
+ def initialize(files:, mime_types:, logger:, connection:)
15
15
  @files = files
16
- @metadata = metadata
16
+ @mime_types = mime_types
17
17
  @logger = logger
18
18
  @connection = connection
19
19
  end
@@ -28,14 +28,14 @@ module SdrClient
28
28
 
29
29
  private
30
30
 
31
- attr_reader :files, :metadata, :logger, :connection
31
+ attr_reader :files, :mime_types, :logger, :connection
32
32
 
33
33
  def collect_file_metadata
34
34
  files.each_with_object({}) do |path, obj|
35
35
  file_name = ::File.basename(path)
36
36
  obj[path] = Files::DirectUploadRequest.from_file(path,
37
37
  file_name: file_name,
38
- content_type: metadata.for(file_name)['mime_type'])
38
+ content_type: mime_types[file_name])
39
39
  end
40
40
  end
41
41
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module SdrClient
6
+ # The namespace for the "deposit" command
7
+ module Deposit
8
+ def self.model_run(request_dro:,
9
+ files: [],
10
+ url:,
11
+ logger: Logger.new(STDOUT))
12
+ token = Credentials.read
13
+
14
+ ModelProcess.new(request_dro: request_dro, url: url, token: token, files: files, logger: logger).run
15
+ end
16
+ end
17
+ end
18
+ require 'sdr_client/deposit/model_process'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SdrClient
4
- VERSION = '0.16.1'
4
+ VERSION = '0.19.0'
5
5
  end
@@ -27,6 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ['lib']
29
29
 
30
+ spec.add_dependency 'activesupport'
31
+ spec.add_dependency 'cocina-models', '~> 0.29.0'
30
32
  spec.add_dependency 'dry-monads'
31
33
  spec.add_dependency 'faraday', '>= 0.16'
32
34
 
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdr-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.1
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-09 00:00:00.000000000 Z
11
+ date: 2020-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cocina-models
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.29.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.29.0
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: dry-monads
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -161,6 +189,7 @@ files:
161
189
  - lib/sdr-client.rb
162
190
  - lib/sdr_client.rb
163
191
  - lib/sdr_client/cli.rb
192
+ - lib/sdr_client/connection.rb
164
193
  - lib/sdr_client/credentials.rb
165
194
  - lib/sdr_client/deposit.rb
166
195
  - lib/sdr_client/deposit/file.rb
@@ -173,12 +202,14 @@ files:
173
202
  - lib/sdr_client/deposit/files/direct_upload_response.rb
174
203
  - lib/sdr_client/deposit/matching_file_grouping_strategy.rb
175
204
  - lib/sdr_client/deposit/metadata_builder.rb
205
+ - lib/sdr_client/deposit/model_process.rb
176
206
  - lib/sdr_client/deposit/process.rb
177
207
  - lib/sdr_client/deposit/request.rb
178
208
  - lib/sdr_client/deposit/single_file_grouping_strategy.rb
179
209
  - lib/sdr_client/deposit/upload_files.rb
180
210
  - lib/sdr_client/login.rb
181
211
  - lib/sdr_client/login_prompt.rb
212
+ - lib/sdr_client/model_deposit.rb
182
213
  - lib/sdr_client/version.rb
183
214
  - sdr-client.gemspec
184
215
  homepage: https://github.com/sul-dlss/sdr-client