sdr-client 0.21.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dab3e033cd3f0fd0eae7045c3565f7c24300d99ebcd7141777eb0d005847497
4
- data.tar.gz: 25a76561f9aafdcc4a575030ca9bb750e8cdf036b60c14cc92f413bbde4668d2
3
+ metadata.gz: 4ba412736744579cc3c7730354944d6357027106ca021c60e7363071a441ac21
4
+ data.tar.gz: 808952a65481516130017e8215656062e06ed9386fbab4486eb2b00bf1e977a1
5
5
  SHA512:
6
- metadata.gz: fa6080f541ce480fc8ca31f5f063404090235e8edce6849aa10c4f50f1a00ef83a166ea1c97ad579e094fbf9b5d8f24df73debc68ce567e1a7886dc7a491b643
7
- data.tar.gz: a915029ed2f58221fe4c2418e8fef194f11eb6bde24af289dc9f52da438841a4bab90fec7a95a94eeaa22334e2e72897a6047f01c5909ed995d371473b1c0295
6
+ metadata.gz: dbc1f0cb2fd1edf1b3af487cb585aab7304600cae177791d0861eeacfed8ba15caf8e59fd222def840e2e102656868e73869ec739fcc499fc40c0807b17ddaf8
7
+ data.tar.gz: 22a5983f2c7b3d77b70efbaab7a6e0280e9057cec80697c80759c4b6efd25fddfcd52c1b8b51c5bc4b819a42b9cabd09ecbb8abcb2522ba6ae2a25dfce2f97a7
@@ -1,16 +1,17 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2020-03-02 15:54:47 -0600 using RuboCop version 0.79.0.
3
+ # on 2020-04-27 08:24:29 -0400 using RuboCop version 0.82.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
9
+ # Offense count: 2
10
+ # Configuration parameters: IgnoredMethods.
10
11
  Metrics/AbcSize:
11
12
  Max: 16
12
13
 
13
- # Offense count: 4
14
+ # Offense count: 7
14
15
  # Configuration parameters: CountComments, ExcludedMethods.
15
16
  Metrics/MethodLength:
16
- Max: 14
17
+ Max: 15
data/README.md CHANGED
@@ -21,8 +21,15 @@ Log in:
21
21
  sdr --service-url http://sdr-api-server:3000 login
22
22
  ```
23
23
 
24
+ Register a new object:
25
+ ```
26
+ sdr --service-url https://sdr-api-server:3000 register --label 'hey there' \
27
+ --admin-policy 'druid:bk123gh4567' \
28
+ --collection 'druid:gh456kw9876' \
29
+ --source-id 'googlebooks:stanford_12345' file1.png file2.png
30
+ ```
24
31
 
25
- Deposit a new object:
32
+ Deposit (register + accession) a new object:
26
33
  ```
27
34
  sdr --service-url https://sdr-api-server:3000 deposit --label 'hey there' \
28
35
  --admin-policy 'druid:bk123gh4567' \
data/exe/sdr CHANGED
@@ -27,7 +27,10 @@ global = OptionParser.new do |opts|
27
27
 
28
28
  COMMANDS
29
29
  deposit
30
- deposit files to the SDR
30
+ accession object into the SDR
31
+
32
+ register
33
+ create a draft object in SDR
31
34
 
32
35
  login
33
36
  Will prompt for email & password and exchange it for an login token, which it saves in ~/.sdr/token
@@ -40,77 +43,80 @@ end
40
43
  global.order!
41
44
  command = ARGV.shift
42
45
 
43
- subcommands = {
44
- 'deposit' => OptionParser.new do |opts|
45
- opts.on('--label LABEL', 'The object label') do |label|
46
- options[:label] = label
47
- end
46
+ deposit_options = OptionParser.new do |opts|
47
+ opts.on('--label LABEL', 'The object label') do |label|
48
+ options[:label] = label
49
+ end
48
50
 
49
- opts.on('--admin-policy ADMIN_POLICY', 'The druid identifier of the admin policy object') do |apo|
50
- options[:apo] = apo
51
- end
51
+ opts.on('--admin-policy ADMIN_POLICY', 'The druid identifier of the admin policy object') do |apo|
52
+ options[:apo] = apo
53
+ end
52
54
 
53
- opts.on('--type TYPE', 'The object type to create. ' \
54
- 'One of: "image", "book", "document", "map", "manuscript", "media", ' \
55
- '"three_dimensional", "collection", or "admin_policy"') do |type|
56
- if %w[image book document map manuscript media three_dimensional collection admin_policy].include?(type)
57
- options[:type] = "http://cocina.sul.stanford.edu/models/#{type}.jsonld"
58
- end
55
+ opts.on('--type TYPE', 'The object type to create. ' \
56
+ 'One of: "image", "book", "document", "map", "manuscript", "media", ' \
57
+ '"three_dimensional", "collection", or "admin_policy"') do |type|
58
+ if %w[image book document map manuscript media three_dimensional collection admin_policy].include?(type)
59
+ options[:type] = "http://cocina.sul.stanford.edu/models/#{type}.jsonld"
59
60
  end
61
+ end
60
62
 
61
- opts.on('--collection COLLECTION', 'The druid identifier of the collection object') do |collection|
62
- options[:collection] = collection
63
- end
63
+ opts.on('--collection COLLECTION', 'The druid identifier of the collection object') do |collection|
64
+ options[:collection] = collection
65
+ end
64
66
 
65
- opts.on('--catkey CATKEY', 'The catkey for this item') do |catkey|
66
- options[:catkey] = catkey
67
- end
67
+ opts.on('--catkey CATKEY', 'The catkey for this item') do |catkey|
68
+ options[:catkey] = catkey
69
+ end
68
70
 
69
- opts.on('--source-id SOURCE_ID', 'The source id for this object') do |source_id|
70
- options[:source_id] = source_id
71
- end
71
+ opts.on('--source-id SOURCE_ID', 'The source id for this object') do |source_id|
72
+ options[:source_id] = source_id
73
+ end
72
74
 
73
- opts.on('--copyright COPYRIGHT', 'The copyright statement') do |copyright|
74
- options[:copyright] = copyright
75
- end
75
+ opts.on('--copyright COPYRIGHT', 'The copyright statement') do |copyright|
76
+ options[:copyright] = copyright
77
+ end
76
78
 
77
- opts.on('--use-statement STATEMENT', 'The use and reproduction statement') do |use_statement|
78
- options[:use_statement] = use_statement
79
- end
79
+ opts.on('--use-statement STATEMENT', 'The use and reproduction statement') do |use_statement|
80
+ options[:use_statement] = use_statement
81
+ end
80
82
 
81
- opts.on('--viewing-direction DIRECTION', 'The viewing direction (if a book). ' \
82
- 'Either "left-to-right" or "right-to-left"') do |viewing_direction|
83
- options[:viewing_direction] = viewing_direction if %w[left-to-right right-to-left].include?(viewing_direction)
84
- end
83
+ opts.on('--viewing-direction DIRECTION', 'The viewing direction (if a book). ' \
84
+ 'Either "left-to-right" or "right-to-left"') do |viewing_direction|
85
+ options[:viewing_direction] = viewing_direction if %w[left-to-right right-to-left].include?(viewing_direction)
86
+ end
85
87
 
86
- opts.on('--access LEVEL', 'The access level for this object. ' \
87
- 'Either "world", "stanford", "location-based", "citation-only" or "dark"') do |level|
88
- options[:access] = level if %w[world stanford location-based citation-only dark].include?(level)
89
- end
88
+ opts.on('--access LEVEL', 'The access level for this object. ' \
89
+ 'Either "world", "stanford", "location-based", "citation-only" or "dark"') do |level|
90
+ options[:access] = level if %w[world stanford location-based citation-only dark].include?(level)
91
+ end
90
92
 
91
- opts.on('--files-metadata FILES_METADATA', 'A JSON object representing per-file metadata') do |files_metadata|
92
- options[:files_metadata] = JSON.parse(files_metadata)
93
- end
93
+ opts.on('--files-metadata FILES_METADATA', 'A JSON object representing per-file metadata') do |files_metadata|
94
+ options[:files_metadata] = JSON.parse(files_metadata)
95
+ end
94
96
 
95
- opts.on('--strategy STRATEGY',
96
- 'The strategy to use for distributing files into filesets. Either "default" or "filename"') do |strategy|
97
- strategy_class = case strategy
98
- when 'filename'
99
- SdrClient::Deposit::MatchingFileGroupingStrategy
100
- when 'default'
101
- SdrClient::Deposit::SingleFileGroupingStrategy
102
- else
103
- warn "Unknown strategy #{strategy}"
104
- exit(1)
105
- end
106
- options[:grouping_strategy] = strategy_class
107
- end
97
+ opts.on('--strategy STRATEGY',
98
+ 'The strategy to use for distributing files into filesets. Either "default" or "filename"') do |strategy|
99
+ strategy_class = case strategy
100
+ when 'filename'
101
+ SdrClient::Deposit::MatchingFileGroupingStrategy
102
+ when 'default'
103
+ SdrClient::Deposit::SingleFileGroupingStrategy
104
+ else
105
+ warn "Unknown strategy #{strategy}"
106
+ exit(1)
107
+ end
108
+ options[:grouping_strategy] = strategy_class
109
+ end
108
110
 
109
- opts.on('-h', '--help', 'Display this screen') do
110
- puts opts
111
- exit
112
- end
113
- end,
111
+ opts.on('-h', '--help', 'Display this screen') do
112
+ puts opts
113
+ exit
114
+ end
115
+ end
116
+
117
+ subcommands = {
118
+ 'deposit' => deposit_options,
119
+ 'register' => deposit_options,
114
120
  'login' => OptionParser.new
115
121
  }
116
122
 
@@ -6,7 +6,9 @@ module SdrClient
6
6
  def self.start(command, options)
7
7
  case command
8
8
  when 'deposit'
9
- SdrClient::Deposit.run(options)
9
+ SdrClient::Deposit.run(accession: true, **options)
10
+ when 'register'
11
+ SdrClient::Deposit.run(accession: false, **options)
10
12
  when 'login'
11
13
  status = SdrClient::Login.run(options)
12
14
  puts status.value if status.failure?
@@ -12,6 +12,7 @@ module SdrClient
12
12
  type: BOOK_TYPE,
13
13
  viewing_direction: nil,
14
14
  access: 'dark',
15
+ download: 'none',
15
16
  use_statement: nil,
16
17
  copyright: nil,
17
18
  apo:,
@@ -23,12 +24,14 @@ module SdrClient
23
24
  url:,
24
25
  files: [],
25
26
  files_metadata: {},
27
+ accession: false,
26
28
  grouping_strategy: SingleFileGroupingStrategy,
27
29
  logger: Logger.new(STDOUT))
28
30
  augmented_metadata = FileMetadataBuilder.build(files: files, files_metadata: files_metadata)
29
31
  metadata = Request.new(label: label,
30
32
  type: type,
31
33
  access: access,
34
+ download: download,
32
35
  apo: apo,
33
36
  use_statement: use_statement,
34
37
  copyright: copyright,
@@ -41,7 +44,9 @@ module SdrClient
41
44
  files_metadata: augmented_metadata)
42
45
  connection = Connection.new(url: url)
43
46
  Process.new(metadata: metadata, connection: connection, files: files,
44
- grouping_strategy: grouping_strategy, logger: logger).run
47
+ grouping_strategy: grouping_strategy,
48
+ accession: accession,
49
+ logger: logger).run
45
50
  end
46
51
  # rubocop:enable Metrics/MethodLength
47
52
  # rubocop:enable Metrics/ParameterLists
@@ -56,6 +61,7 @@ require 'sdr_client/deposit/file'
56
61
  require 'sdr_client/deposit/file_metadata_builder'
57
62
  require 'sdr_client/deposit/file_set'
58
63
  require 'sdr_client/deposit/request'
59
- require 'sdr_client/deposit/upload_files'
60
64
  require 'sdr_client/deposit/metadata_builder'
61
65
  require 'sdr_client/deposit/process'
66
+ require 'sdr_client/deposit/upload_files'
67
+ require 'sdr_client/deposit/upload_resource'
@@ -6,7 +6,7 @@ module SdrClient
6
6
  class File
7
7
  # rubocop:disable Metrics/ParameterLists
8
8
  def initialize(external_identifier:, label:, filename:,
9
- access: 'dark', preserve: false, shelve: false,
9
+ access: 'world', preserve: true, shelve: true,
10
10
  mime_type: nil, md5: nil, sha1: nil, use: nil)
11
11
  @external_identifier = external_identifier
12
12
  @label = label
@@ -6,16 +6,18 @@ module SdrClient
6
6
  module Deposit
7
7
  # The process for doing a deposit from a Cocina Model
8
8
  class ModelProcess
9
- DRO_PATH = '/v1/resources'
10
9
  # @param [Cocina::Model::RequestDRO] request_dro for depositing
11
10
  # @param [Connection] connection the connection to use
12
11
  # @param [Array<String>] files a list of file names to upload
12
+ # @param [Boolean] accession should the accessionWF be started
13
13
  # @param [Logger] logger the logger to use
14
- def initialize(request_dro:, connection:, files: [], logger: Logger.new(STDOUT))
14
+ def initialize(request_dro:, connection:,
15
+ files: [], accession:, logger: Logger.new(STDOUT))
15
16
  @files = files
16
17
  @connection = connection
17
18
  @request_dro = request_dro
18
19
  @logger = logger
20
+ @accession = accession
19
21
  end
20
22
 
21
23
  def run
@@ -27,7 +29,10 @@ module SdrClient
27
29
  connection: connection,
28
30
  mime_types: mime_types).run
29
31
  new_request_dro = with_external_identifiers(upload_responses)
30
- upload_request_dro(new_request_dro.to_json)
32
+ UploadResource.run(accession: @accession,
33
+ metadata: new_request_dro.to_json,
34
+ logger: logger,
35
+ connection: connection)
31
36
  end
32
37
 
33
38
  private
@@ -56,24 +61,6 @@ module SdrClient
56
61
  end
57
62
  end
58
63
 
59
- # @return [Hash<Symbol,String>] the result of the metadata call
60
- def upload_request_dro(request_json)
61
- logger.info("Starting upload metadata: #{request_json}")
62
- response = connection.post(DRO_PATH, request_json, 'Content-Type' => 'application/json')
63
- unexpected_response(response) unless response.status == 201
64
-
65
- logger.info("Response from server: #{response.body}")
66
-
67
- { druid: JSON.parse(response.body)['druid'], background_job: response.headers['Location'] }
68
- end
69
-
70
- def unexpected_response(response)
71
- raise "There was an error with your request: #{response.body}" if response.status == 400
72
- raise 'There was an error with your credentials. Perhaps they have expired?' if response.status == 401
73
-
74
- raise "unexpected response: #{response.status} #{response.body}"
75
- end
76
-
77
64
  # Map of filenames to mimetypes
78
65
  def mime_types
79
66
  @mime_types ||=
@@ -6,20 +6,24 @@ module SdrClient
6
6
  module Deposit
7
7
  # The process for doing a deposit
8
8
  class Process
9
- DRO_PATH = '/v1/resources'
10
9
  # @param [Request] metadata information about the object
11
10
  # @param [Class] grouping_strategy class whose run method groups an array of uploads
12
11
  # @param [String] connection the server connection to use
13
12
  # @param [Array<String>] files a list of file names to upload
13
+ # @param [Boolean] accession should the accessionWF be started
14
14
  # @param [Logger] logger the logger to use
15
+ #
16
+ # rubocop:disable Metrics/ParameterLists
15
17
  def initialize(metadata:, grouping_strategy: SingleFileGroupingStrategy,
16
- connection:, files: [], logger: Logger.new(STDOUT))
18
+ connection:, files: [], accession:, logger: Logger.new(STDOUT))
17
19
  @files = files
18
20
  @connection = connection
19
21
  @metadata = metadata
20
22
  @logger = logger
21
23
  @grouping_strategy = grouping_strategy
24
+ @accession = accession
22
25
  end
26
+ # rubocop:enable Metrics/ParameterLists
23
27
 
24
28
  # rubocop:disable Metrics/AbcSize
25
29
  def run
@@ -33,7 +37,10 @@ module SdrClient
33
37
  logger: logger)
34
38
  request = metadata_builder.with_uploads(upload_responses)
35
39
  model = Cocina::Models.build_request(request.as_json.with_indifferent_access)
36
- upload_metadata(model.to_h)
40
+ UploadResource.run(accession: @accession,
41
+ metadata: JSON.generate(model.to_h),
42
+ logger: logger,
43
+ connection: connection)
37
44
  end
38
45
  # rubocop:enable Metrics/AbcSize
39
46
 
@@ -48,25 +55,6 @@ module SdrClient
48
55
  end
49
56
  end
50
57
 
51
- # @return [Hash<Symbol,String>] the result of the metadata call
52
- def upload_metadata(metadata)
53
- logger.info("Starting upload metadata: #{metadata}")
54
- request_json = JSON.generate(metadata)
55
- response = connection.post(DRO_PATH, request_json, 'Content-Type' => 'application/json')
56
- unexpected_response(response) unless response.status == 201
57
-
58
- logger.info("Response from server: #{response.body}")
59
-
60
- { druid: JSON.parse(response.body)['druid'], background_job: response.headers['Location'] }
61
- end
62
-
63
- def unexpected_response(response)
64
- raise "There was an error with your request: #{response.body}" if response.status == 400
65
- raise 'There was an error with your credentials. Perhaps they have expired?' if response.status == 401
66
-
67
- raise "unexpected response: #{response.status} #{response.body}"
68
- end
69
-
70
58
  def mime_types
71
59
  @mime_types ||=
72
60
  Hash[
@@ -14,6 +14,7 @@ module SdrClient
14
14
  # rubocop:disable Metrics/ParameterLists
15
15
  def initialize(label: nil,
16
16
  access: 'dark',
17
+ download: 'none',
17
18
  use_statement: nil,
18
19
  copyright: nil,
19
20
  apo:,
@@ -34,6 +35,7 @@ module SdrClient
34
35
  @embargo_release_date = embargo_release_date
35
36
  @embargo_access = embargo_access
36
37
  @access = access
38
+ @download = download
37
39
  @use_statement = use_statement
38
40
  @copyright = copyright
39
41
  @apo = apo
@@ -59,6 +61,7 @@ module SdrClient
59
61
  def with_file_sets(file_sets)
60
62
  Request.new(label: label,
61
63
  access: access,
64
+ download: download,
62
65
  apo: apo,
63
66
  collection: collection,
64
67
  copyright: copyright,
@@ -85,7 +88,7 @@ module SdrClient
85
88
 
86
89
  attr_reader :access, :label, :file_sets, :source_id, :catkey, :apo, :collection,
87
90
  :files_metadata, :embargo_release_date, :embargo_access,
88
- :viewing_direction, :use_statement, :copyright
91
+ :viewing_direction, :use_statement, :copyright, :download
89
92
 
90
93
  def administrative
91
94
  {
@@ -108,7 +111,10 @@ module SdrClient
108
111
  end
109
112
 
110
113
  def access_struct
111
- { access: access }.tap do |json|
114
+ {
115
+ access: access,
116
+ download: download
117
+ }.tap do |json|
112
118
  json[:useAndReproductionStatement] = use_statement if use_statement
113
119
  json[:copyright] = copyright if copyright
114
120
 
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ module Deposit
5
+ # Uploads a resource (metadata) to the server
6
+ class UploadResource
7
+ DRO_PATH = '/v1/resources'
8
+
9
+ def self.run(accession:, metadata:, logger:, connection:)
10
+ new(accession: accession, metadata: metadata, logger: logger, connection: connection).run
11
+ end
12
+
13
+ # @param [Boolean] accession should the accessionWF be started
14
+ # @param [String] metadata
15
+ # @param [Hash<Symbol,String>] the result of the metadata call
16
+ def initialize(accession:, metadata:, logger:, connection:)
17
+ @accession = accession
18
+ @metadata = metadata
19
+ @logger = logger
20
+ @connection = connection
21
+ end
22
+
23
+ # @param [Hash<Symbol,String>] the result of the metadata call
24
+ # @return [Hash<Symbol,String>] the result of the metadata call
25
+ def run
26
+ response = metadata_request
27
+ unexpected_response(response) unless response.status == 201
28
+
29
+ logger.info("Response from server: #{response.body}")
30
+
31
+ { druid: JSON.parse(response.body)['druid'], background_job: response.headers['Location'] }
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :metadata, :logger, :connection
37
+
38
+ def metadata_request
39
+ logger.debug("Starting upload metadata: #{metadata}")
40
+
41
+ connection.post(path, metadata, 'Content-Type' => 'application/json')
42
+ end
43
+
44
+ def unexpected_response(response)
45
+ raise "There was an error with your request: #{response.body}" if response.status == 400
46
+ raise 'There was an error with your credentials. Perhaps they have expired?' if response.status == 401
47
+
48
+ raise "unexpected response: #{response.status} #{response.body}"
49
+ end
50
+
51
+ def accession?
52
+ @accession
53
+ end
54
+
55
+ def path
56
+ path = DRO_PATH
57
+ path += '?accession=true' if accession?
58
+ path
59
+ end
60
+ end
61
+ end
62
+ end
@@ -8,9 +8,14 @@ module SdrClient
8
8
  def self.model_run(request_dro:,
9
9
  files: [],
10
10
  url:,
11
+ accession:,
11
12
  logger: Logger.new(STDOUT))
12
13
  connection = Connection.new(url: url)
13
- ModelProcess.new(request_dro: request_dro, connection: connection, files: files, logger: logger).run
14
+ ModelProcess.new(request_dro: request_dro,
15
+ connection: connection,
16
+ files: files,
17
+ logger: logger,
18
+ accession: accession).run
14
19
  end
15
20
  end
16
21
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SdrClient
4
- VERSION = '0.21.0'
4
+ VERSION = '0.25.0'
5
5
  end
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  spec.add_dependency 'activesupport'
31
- spec.add_dependency 'cocina-models', '~> 0.31.0'
31
+ spec.add_dependency 'cocina-models', '~> 0.32.0'
32
32
  spec.add_dependency 'dry-monads'
33
33
  spec.add_dependency 'faraday', '>= 0.16'
34
34
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdr-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.25.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-31 00:00:00.000000000 Z
11
+ date: 2020-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.31.0
33
+ version: 0.32.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.31.0
40
+ version: 0.32.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dry-monads
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -207,6 +207,7 @@ files:
207
207
  - lib/sdr_client/deposit/request.rb
208
208
  - lib/sdr_client/deposit/single_file_grouping_strategy.rb
209
209
  - lib/sdr_client/deposit/upload_files.rb
210
+ - lib/sdr_client/deposit/upload_resource.rb
210
211
  - lib/sdr_client/login.rb
211
212
  - lib/sdr_client/login_prompt.rb
212
213
  - lib/sdr_client/model_deposit.rb