folio_client 0.21.0 → 1.0.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 +4 -4
- data/Gemfile.lock +6 -6
- data/lib/folio_client/version.rb +1 -1
- data/lib/folio_client.rb +187 -135
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7ff536f92f06403a2d47dd9ede2dab90d0f20d8b6ad52f9c2bd047dd7eb0650
|
|
4
|
+
data.tar.gz: 3ba0ff3343cbf79bfb383254d18f8cad2bd0c74b0251e4c76bf69b26d6d75ed4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e5e9f3c4b84168f41b6afaacffebcaba29bc732ea338a3834a01621dec956e568d5863789da54b4df297bda2915e9119164c0fbf3e4de1c703fc5317df0c4fb
|
|
7
|
+
data.tar.gz: c9bde04bd107cb50213b2beb8019251dd1cf2452ce842f926420576202df65ee3d54ea1a665afb441ff5d47a367fab8230de0612d88767b73bc9454a35cd9218
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
folio_client (0.
|
|
4
|
+
folio_client (1.0.0)
|
|
5
5
|
activesupport (>= 4.2)
|
|
6
6
|
deprecation
|
|
7
7
|
dry-monads
|
|
@@ -66,7 +66,7 @@ GEM
|
|
|
66
66
|
faraday-net_http (3.4.2)
|
|
67
67
|
net-http (~> 0.5)
|
|
68
68
|
hashdiff (1.2.1)
|
|
69
|
-
http-cookie (1.1.
|
|
69
|
+
http-cookie (1.1.4)
|
|
70
70
|
domain_name (~> 0.5)
|
|
71
71
|
i18n (1.14.8)
|
|
72
72
|
concurrent-ruby (~> 1.0)
|
|
@@ -93,7 +93,7 @@ GEM
|
|
|
93
93
|
nokogiri (1.19.2-x86_64-linux-gnu)
|
|
94
94
|
racc (~> 1.4)
|
|
95
95
|
ostruct (0.6.3)
|
|
96
|
-
parallel (
|
|
96
|
+
parallel (2.0.1)
|
|
97
97
|
parser (3.3.11.1)
|
|
98
98
|
ast (~> 2.4.1)
|
|
99
99
|
racc
|
|
@@ -129,11 +129,11 @@ GEM
|
|
|
129
129
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
130
130
|
rspec-support (~> 3.13.0)
|
|
131
131
|
rspec-support (3.13.7)
|
|
132
|
-
rubocop (1.86.
|
|
132
|
+
rubocop (1.86.1)
|
|
133
133
|
json (~> 2.3)
|
|
134
134
|
language_server-protocol (~> 3.17.0.2)
|
|
135
135
|
lint_roller (~> 1.1.0)
|
|
136
|
-
parallel (
|
|
136
|
+
parallel (>= 1.10)
|
|
137
137
|
parser (>= 3.3.0.2)
|
|
138
138
|
rainbow (>= 2.2.2, < 4.0)
|
|
139
139
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
@@ -203,4 +203,4 @@ DEPENDENCIES
|
|
|
203
203
|
webmock
|
|
204
204
|
|
|
205
205
|
BUNDLED WITH
|
|
206
|
-
4.0.
|
|
206
|
+
4.0.10
|
data/lib/folio_client/version.rb
CHANGED
data/lib/folio_client.rb
CHANGED
|
@@ -11,45 +11,47 @@ require 'ostruct'
|
|
|
11
11
|
require 'singleton'
|
|
12
12
|
require 'zeitwerk'
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
# Autoload gem internals.
|
|
15
15
|
Zeitwerk::Loader.for_gem.setup
|
|
16
16
|
|
|
17
|
-
# Client for interacting with the Folio API
|
|
18
|
-
# rubocop:disable Metrics/ClassLength
|
|
19
|
-
class FolioClient
|
|
17
|
+
# Client for interacting with the Folio API.
|
|
18
|
+
class FolioClient # rubocop:disable Metrics/ClassLength
|
|
20
19
|
include Singleton
|
|
21
20
|
|
|
22
|
-
# Base class for all FolioClient errors
|
|
21
|
+
# Base class for all FolioClient errors.
|
|
23
22
|
class Error < StandardError; end
|
|
24
23
|
|
|
25
|
-
#
|
|
24
|
+
# Raised when the Folio Auth API returns 401 Unauthorized.
|
|
26
25
|
class UnauthorizedError < Error; end
|
|
27
26
|
|
|
28
|
-
#
|
|
27
|
+
# Raised when the Folio API returns 404 Not Found, or when 0 results are
|
|
28
|
+
# returned where one was expected.
|
|
29
29
|
class ResourceNotFound < Error; end
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# Raised when exactly one resource was expected but multiple were returned.
|
|
32
32
|
class MultipleResourcesFound < Error; end
|
|
33
33
|
|
|
34
|
-
#
|
|
34
|
+
# Raised when the Folio API returns 403 Forbidden.
|
|
35
35
|
class ForbiddenError < Error; end
|
|
36
36
|
|
|
37
|
-
#
|
|
37
|
+
# Raised when the Folio API returns 500-level availability errors.
|
|
38
38
|
class ServiceUnavailable < Error; end
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Raised when the Folio API returns 422 Unprocessable Entity.
|
|
41
41
|
class ValidationError < Error; end
|
|
42
42
|
|
|
43
|
-
#
|
|
43
|
+
# Raised when the Folio API returns 409 Conflict.
|
|
44
44
|
class ConflictError < Error; end
|
|
45
45
|
|
|
46
|
-
#
|
|
46
|
+
# Raised when the Folio API returns 400 Bad Request.
|
|
47
47
|
class BadRequestError < Error; end
|
|
48
48
|
|
|
49
49
|
class << self
|
|
50
50
|
extend Deprecation
|
|
51
51
|
|
|
52
52
|
Config = Struct.new('Config', :url, :login_params, :timeout, :tenant_id, :user_agent) do
|
|
53
|
+
# Build default headers for Folio-bound requests.
|
|
54
|
+
# @return [Hash<Symbol,String>] default request headers
|
|
53
55
|
def headers
|
|
54
56
|
{
|
|
55
57
|
accept: 'application/json, text/plain',
|
|
@@ -60,47 +62,48 @@ class FolioClient
|
|
|
60
62
|
end
|
|
61
63
|
end
|
|
62
64
|
|
|
63
|
-
#
|
|
64
|
-
# @
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
# @
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
# Configure the singleton FolioClient instance.
|
|
66
|
+
# @example
|
|
67
|
+
# FolioClient.configure(
|
|
68
|
+
# url: 'https://folio.example.edu',
|
|
69
|
+
# login_params: { username: 'svc-user', password: 'secret' },
|
|
70
|
+
# tenant_id: 'sul'
|
|
71
|
+
# )
|
|
72
|
+
# @param url [String] Folio API base URL
|
|
73
|
+
# @param login_params [Hash] authentication payload (e.g., +username+, +password+)
|
|
74
|
+
# @param tenant_id [String, nil] Folio tenant identifier
|
|
75
|
+
# @param user_agent [String, nil] user agent string included on outbound requests
|
|
76
|
+
# @param timeout [Integer] request timeout, in seconds
|
|
77
|
+
# @return [Class<FolioClient>] the configured singleton class for chaining
|
|
78
|
+
def configure(url:, login_params:, tenant_id: nil, user_agent: nil, timeout: nil)
|
|
78
79
|
instance.config = Config.new(
|
|
79
80
|
url: url,
|
|
80
81
|
login_params: login_params,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
user_agent: user_agent
|
|
82
|
+
tenant_id: tenant_id,
|
|
83
|
+
timeout: timeout || default_timeout,
|
|
84
|
+
user_agent: user_agent || default_user_agent
|
|
84
85
|
)
|
|
85
86
|
|
|
86
87
|
self
|
|
87
88
|
end
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
# The client is intended to be used as a singleton via {.configure}, but the
|
|
91
|
+
# instance methods are also available on the class itself for convenience.
|
|
92
|
+
# Instead of maintaining a giant list of delegations to the singleton
|
|
93
|
+
# instance, we can just delegate everything. This makes the client easier to
|
|
94
|
+
# extend with additional instance methods without needing to update the
|
|
95
|
+
# delegation list.
|
|
96
|
+
delegate_missing_to :instance
|
|
96
97
|
end
|
|
97
98
|
|
|
99
|
+
# @return [FolioClient::Config, nil] active runtime configuration
|
|
98
100
|
attr_accessor :config
|
|
99
101
|
|
|
100
|
-
# Send an authenticated
|
|
101
|
-
# @param path [String]
|
|
102
|
-
# @param params [Hash]
|
|
103
|
-
# @return [Hash, nil]
|
|
102
|
+
# Send an authenticated GET request.
|
|
103
|
+
# @param path [String] API path relative to configured +url+
|
|
104
|
+
# @param params [Hash] query parameters
|
|
105
|
+
# @return [Hash, Array, nil] parsed JSON body, or +nil+ for empty body
|
|
106
|
+
# @raise [FolioClient::Error] when Folio responds with an unexpected status
|
|
104
107
|
def get(path, params = {})
|
|
105
108
|
response = with_token_refresh_when_unauthorized do
|
|
106
109
|
connection.get(path, params)
|
|
@@ -111,11 +114,14 @@ class FolioClient
|
|
|
111
114
|
JSON.parse(response.body) if response.body.present?
|
|
112
115
|
end
|
|
113
116
|
|
|
114
|
-
# Send an authenticated
|
|
115
|
-
# If
|
|
116
|
-
#
|
|
117
|
-
# @param
|
|
118
|
-
# @
|
|
117
|
+
# Send an authenticated POST request.
|
|
118
|
+
# If +content_type+ is +application/json+, +body+ is serialized with +to_json+.
|
|
119
|
+
# Otherwise +body+ is sent unchanged.
|
|
120
|
+
# @param path [String] API path relative to configured +url+
|
|
121
|
+
# @param body [Hash, String, nil] request payload
|
|
122
|
+
# @param content_type [String] MIME type of request body
|
|
123
|
+
# @return [Hash, Array, nil] parsed JSON body, or +nil+ for empty body
|
|
124
|
+
# @raise [FolioClient::Error] when Folio responds with an unexpected status
|
|
119
125
|
def post(path, body = nil, content_type: 'application/json')
|
|
120
126
|
req_body = content_type == 'application/json' ? body&.to_json : body
|
|
121
127
|
response = with_token_refresh_when_unauthorized do
|
|
@@ -127,11 +133,15 @@ class FolioClient
|
|
|
127
133
|
JSON.parse(response.body) if response.body.present?
|
|
128
134
|
end
|
|
129
135
|
|
|
130
|
-
# Send an authenticated
|
|
131
|
-
# If
|
|
132
|
-
#
|
|
133
|
-
# @param
|
|
134
|
-
# @
|
|
136
|
+
# Send an authenticated PUT request.
|
|
137
|
+
# If +content_type+ is +application/json+, +body+ is serialized with +to_json+.
|
|
138
|
+
# Otherwise +body+ is sent unchanged.
|
|
139
|
+
# @param path [String] API path relative to configured +url+
|
|
140
|
+
# @param body [Hash, String, nil] request payload
|
|
141
|
+
# @param content_type [String] MIME type of request body
|
|
142
|
+
# @param exception_args [Hash] supplemental context forwarded to +UnexpectedResponse+
|
|
143
|
+
# @return [Hash, Array, nil] parsed JSON body, or +nil+ for empty body
|
|
144
|
+
# @raise [FolioClient::Error] when Folio responds with an unexpected status
|
|
135
145
|
def put(path, body = nil, content_type: 'application/json', **exception_args)
|
|
136
146
|
req_body = content_type == 'application/json' ? body&.to_json : body
|
|
137
147
|
response = with_token_refresh_when_unauthorized do
|
|
@@ -143,7 +153,8 @@ class FolioClient
|
|
|
143
153
|
JSON.parse(response.body) if response.body.present?
|
|
144
154
|
end
|
|
145
155
|
|
|
146
|
-
#
|
|
156
|
+
# Build (or memoize) the base Faraday connection.
|
|
157
|
+
# @return [Faraday::Connection] configured HTTP connection
|
|
147
158
|
def connection
|
|
148
159
|
@connection ||= Faraday.new(
|
|
149
160
|
url: config.url,
|
|
@@ -155,174 +166,215 @@ class FolioClient
|
|
|
155
166
|
end
|
|
156
167
|
end
|
|
157
168
|
|
|
169
|
+
# Build (or memoize) the cookie jar used by Faraday to store authentication cookies.
|
|
170
|
+
# @return [HTTP::CookieJar] cookie storage for session-aware requests
|
|
158
171
|
def cookie_jar
|
|
159
172
|
@cookie_jar ||= HTTP::CookieJar.new
|
|
160
173
|
end
|
|
161
174
|
|
|
162
|
-
#
|
|
163
|
-
|
|
175
|
+
# Fetch a Folio HRID by instance identifier or query context.
|
|
164
176
|
# @see Inventory#fetch_hrid
|
|
177
|
+
# @return [Object] delegated return value from +Inventory#fetch_hrid+
|
|
165
178
|
def fetch_hrid(...)
|
|
166
|
-
|
|
167
|
-
.new
|
|
168
|
-
.fetch_hrid(...)
|
|
179
|
+
inventory.fetch_hrid(...)
|
|
169
180
|
end
|
|
170
181
|
|
|
182
|
+
# Fetch the Folio external id for a matching record.
|
|
171
183
|
# @see Inventory#fetch_external_id
|
|
184
|
+
# @return [Object] delegated return value from +Inventory#fetch_external_id+
|
|
172
185
|
def fetch_external_id(...)
|
|
173
|
-
|
|
174
|
-
.new
|
|
175
|
-
.fetch_external_id(...)
|
|
186
|
+
inventory.fetch_external_id(...)
|
|
176
187
|
end
|
|
177
188
|
|
|
189
|
+
# Fetch inventory instance details.
|
|
178
190
|
# @see Inventory#fetch_instance_info
|
|
191
|
+
# @return [Object] delegated return value from +Inventory#fetch_instance_info+
|
|
179
192
|
def fetch_instance_info(...)
|
|
180
|
-
|
|
181
|
-
.new
|
|
182
|
-
.fetch_instance_info(...)
|
|
193
|
+
inventory.fetch_instance_info(...)
|
|
183
194
|
end
|
|
184
195
|
|
|
196
|
+
# Fetch location details from inventory.
|
|
185
197
|
# @see Inventory#fetch_location
|
|
198
|
+
# @return [Object] delegated return value from +Inventory#fetch_location+
|
|
186
199
|
def fetch_location(...)
|
|
187
|
-
|
|
188
|
-
.new
|
|
189
|
-
.fetch_location(...)
|
|
200
|
+
inventory.fetch_location(...)
|
|
190
201
|
end
|
|
191
202
|
|
|
203
|
+
# Fetch holdings associated with a record.
|
|
192
204
|
# @see Inventory#fetch_holdings
|
|
205
|
+
# @return [Object] delegated return value from +Inventory#fetch_holdings+
|
|
193
206
|
def fetch_holdings(...)
|
|
194
|
-
|
|
195
|
-
.new
|
|
196
|
-
.fetch_holdings(...)
|
|
207
|
+
inventory.fetch_holdings(...)
|
|
197
208
|
end
|
|
198
209
|
|
|
210
|
+
# Update an existing holdings record.
|
|
199
211
|
# @see Inventory#update_holdings
|
|
212
|
+
# @return [Object] delegated return value from +Inventory#update_holdings+
|
|
200
213
|
def update_holdings(...)
|
|
201
|
-
|
|
202
|
-
.new
|
|
203
|
-
.update_holdings(...)
|
|
214
|
+
inventory.update_holdings(...)
|
|
204
215
|
end
|
|
205
216
|
|
|
217
|
+
# Create a new holdings record.
|
|
206
218
|
# @see Inventory#create_holdings
|
|
219
|
+
# @return [Object] delegated return value from +Inventory#create_holdings+
|
|
207
220
|
def create_holdings(...)
|
|
208
|
-
|
|
209
|
-
.new
|
|
210
|
-
.create_holdings(...)
|
|
221
|
+
inventory.create_holdings(...)
|
|
211
222
|
end
|
|
212
223
|
|
|
224
|
+
# Fetch MARC data as a Ruby hash.
|
|
213
225
|
# @see SourceStorage#fetch_marc_hash
|
|
226
|
+
# @return [Object] delegated return value from +SourceStorage#fetch_marc_hash+
|
|
214
227
|
def fetch_marc_hash(...)
|
|
215
|
-
|
|
216
|
-
.new
|
|
217
|
-
.fetch_marc_hash(...)
|
|
228
|
+
source_storage.fetch_marc_hash(...)
|
|
218
229
|
end
|
|
219
230
|
|
|
231
|
+
# Fetch MARC data as XML.
|
|
220
232
|
# @see SourceStorage#fetch_marc_xml
|
|
233
|
+
# @return [Object] delegated return value from +SourceStorage#fetch_marc_xml+
|
|
221
234
|
def fetch_marc_xml(...)
|
|
222
|
-
|
|
223
|
-
.new
|
|
224
|
-
.fetch_marc_xml(...)
|
|
235
|
+
source_storage.fetch_marc_xml(...)
|
|
225
236
|
end
|
|
226
237
|
|
|
238
|
+
# Determine whether an instance has the requested status.
|
|
227
239
|
# @see Inventory#has_instance_status?
|
|
240
|
+
# @return [Boolean] delegated predicate result
|
|
228
241
|
def has_instance_status?(...) # rubocop:disable Naming/PredicatePrefix
|
|
229
|
-
|
|
230
|
-
.new
|
|
231
|
-
.has_instance_status?(...)
|
|
242
|
+
inventory.has_instance_status?(...)
|
|
232
243
|
end
|
|
233
244
|
|
|
234
|
-
#
|
|
245
|
+
# Run an inventory data import workflow.
|
|
246
|
+
# @see DataImport#import
|
|
247
|
+
# @return [Object] delegated return value from +DataImport#import+
|
|
235
248
|
def data_import(...)
|
|
236
|
-
|
|
237
|
-
.new
|
|
238
|
-
.import(...)
|
|
249
|
+
data_import_service.import(...)
|
|
239
250
|
end
|
|
240
251
|
|
|
241
|
-
#
|
|
252
|
+
# List available data-import job profiles.
|
|
253
|
+
# @see DataImport#job_profiles
|
|
254
|
+
# @return [Object] delegated return value from +DataImport#job_profiles+
|
|
242
255
|
def job_profiles(...)
|
|
243
|
-
|
|
244
|
-
.new
|
|
245
|
-
.job_profiles(...)
|
|
256
|
+
data_import_service.job_profiles(...)
|
|
246
257
|
end
|
|
247
258
|
|
|
259
|
+
# Edit MARC-in-JSON records.
|
|
248
260
|
# @see RecordsEditor#edit_marc_json
|
|
261
|
+
# @return [Object] delegated return value from +RecordsEditor#edit_marc_json+
|
|
249
262
|
def edit_marc_json(...)
|
|
250
|
-
|
|
251
|
-
.new
|
|
252
|
-
.edit_marc_json(...)
|
|
263
|
+
records_editor.edit_marc_json(...)
|
|
253
264
|
end
|
|
254
265
|
|
|
266
|
+
# List organizations.
|
|
255
267
|
# @see Organizations#fetch_list
|
|
268
|
+
# @return [Object] delegated return value from +Organizations#fetch_list+
|
|
256
269
|
def organizations(...)
|
|
257
|
-
|
|
258
|
-
.new
|
|
259
|
-
.fetch_list(...)
|
|
270
|
+
organizations_service.fetch_list(...)
|
|
260
271
|
end
|
|
261
272
|
|
|
273
|
+
# List interfaces for organizations.
|
|
262
274
|
# @see Organizations#fetch_interface_list
|
|
275
|
+
# @return [Object] delegated return value from +Organizations#fetch_interface_list+
|
|
263
276
|
def organization_interfaces(...)
|
|
264
|
-
|
|
265
|
-
.new
|
|
266
|
-
.fetch_interface_list(...)
|
|
277
|
+
organizations_service.fetch_interface_list(...)
|
|
267
278
|
end
|
|
268
279
|
|
|
280
|
+
# Fetch detailed interface information for an organization interface.
|
|
269
281
|
# @see Organizations#fetch_interface_details
|
|
282
|
+
# @return [Object] delegated return value from +Organizations#fetch_interface_details+
|
|
270
283
|
def interface_details(...)
|
|
271
|
-
|
|
272
|
-
.new
|
|
273
|
-
.fetch_interface_details(...)
|
|
284
|
+
organizations_service.fetch_interface_details(...)
|
|
274
285
|
end
|
|
275
286
|
|
|
287
|
+
# List users.
|
|
276
288
|
# @see Users#fetch_list
|
|
289
|
+
# @return [Object] delegated return value from +Users#fetch_list+
|
|
277
290
|
def users(...)
|
|
278
|
-
|
|
279
|
-
.new
|
|
280
|
-
.fetch_list(...)
|
|
291
|
+
users_service.fetch_list(...)
|
|
281
292
|
end
|
|
282
293
|
|
|
294
|
+
# Fetch details for a user.
|
|
283
295
|
# @see Users#fetch_user_details
|
|
296
|
+
# @return [Object] delegated return value from +Users#fetch_user_details+
|
|
284
297
|
def user_details(...)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
298
|
+
users_service.fetch_user_details(...)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Force a refresh of the current auth token.
|
|
302
|
+
#
|
|
303
|
+
# @return [Object] return value from +Authenticator.refresh_token!+
|
|
304
|
+
def force_token_refresh!
|
|
305
|
+
Authenticator.refresh_token!
|
|
288
306
|
end
|
|
289
307
|
|
|
308
|
+
# Default HTTP timeout in seconds.
|
|
309
|
+
#
|
|
310
|
+
# @return [Integer]
|
|
290
311
|
def default_timeout
|
|
291
312
|
180
|
|
292
313
|
end
|
|
293
314
|
|
|
315
|
+
# Default user-agent string used for outbound requests.
|
|
316
|
+
#
|
|
317
|
+
# @return [String]
|
|
294
318
|
def default_user_agent
|
|
295
|
-
"folio_client #{
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
def force_token_refresh!
|
|
299
|
-
Authenticator.refresh_token!
|
|
319
|
+
"folio_client #{VERSION}"
|
|
300
320
|
end
|
|
301
321
|
|
|
302
322
|
private
|
|
303
323
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
#
|
|
308
|
-
#
|
|
309
|
-
#
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
#
|
|
313
|
-
#
|
|
314
|
-
#
|
|
315
|
-
# expiry to fall in the middle of that related set of HTTP calls).
|
|
324
|
+
STATUSES_REQUIRING_TOKEN_REFRESH = [401, 403].freeze
|
|
325
|
+
private_constant :STATUSES_REQUIRING_TOKEN_REFRESH
|
|
326
|
+
|
|
327
|
+
# Wrap API operations to refresh and retry when auth has expired.
|
|
328
|
+
# @yieldreturn [Faraday::Response] response from a single HTTP request
|
|
329
|
+
# @return [Faraday::Response] original or retried response
|
|
330
|
+
# @note Wrap one HTTP call per block. If auth fails, the entire block is retried.
|
|
331
|
+
# Only the final response yielded by the block is inspected for auth failure.
|
|
332
|
+
# @note Because this class is a Singleton, its token can outlive many client calls.
|
|
333
|
+
# Expiration can occur between any two invocations, even when those calls are
|
|
334
|
+
# logically related from the caller's perspective.
|
|
316
335
|
def with_token_refresh_when_unauthorized
|
|
317
336
|
response = yield
|
|
318
337
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
338
|
+
return response unless STATUSES_REQUIRING_TOKEN_REFRESH.include?(response.status)
|
|
339
|
+
|
|
340
|
+
force_token_refresh!
|
|
341
|
+
|
|
342
|
+
yield
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Build an inventory service object.
|
|
346
|
+
# @return [Inventory]
|
|
347
|
+
def inventory
|
|
348
|
+
Inventory.new
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Build a source-storage service object.
|
|
352
|
+
# @return [SourceStorage]
|
|
353
|
+
def source_storage
|
|
354
|
+
SourceStorage.new
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Build a data-import service object.
|
|
358
|
+
# @return [DataImport]
|
|
359
|
+
def data_import_service
|
|
360
|
+
DataImport.new
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# Build a records-editor service object.
|
|
364
|
+
# @return [RecordsEditor]
|
|
365
|
+
def records_editor
|
|
366
|
+
RecordsEditor.new
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Build an organizations service object.
|
|
370
|
+
# @return [Organizations]
|
|
371
|
+
def organizations_service
|
|
372
|
+
Organizations.new
|
|
373
|
+
end
|
|
324
374
|
|
|
325
|
-
|
|
375
|
+
# Build a users service object.
|
|
376
|
+
# @return [Users]
|
|
377
|
+
def users_service
|
|
378
|
+
Users.new
|
|
326
379
|
end
|
|
327
380
|
end
|
|
328
|
-
# rubocop:enable Metrics/ClassLength
|