boxr 1.23.1 → 1.24.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/boxr.gemspec +1 -1
- data/lib/boxr/avatars.rb +33 -0
- data/lib/boxr/chunked_uploads.rb +101 -86
- data/lib/boxr/client.rb +24 -19
- data/lib/boxr/collections.rb +9 -0
- data/lib/boxr/files.rb +40 -29
- data/lib/boxr/version.rb +1 -1
- data/lib/boxr.rb +15 -14
- metadata +6 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 61cea90fb968b5080ce842d650aafd74224bdc6caf7cbe11e168aa0f3ef7c4c3
|
|
4
|
+
data.tar.gz: 9de8543da3e1029de8ea4d9c0c346cfd6a05563a8119f7a3a81356bafd7a6831
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b16ccaec58eaa114cfb7c41f62e10cc05e8d07c45ce3e73c4e03d5ebf9407e022cb381cde5ceab0c88ace21a1d3b27b3564cf3b3b49be6fd8a3955e4006f771
|
|
7
|
+
data.tar.gz: c3eb8f6e86e09ceffd43f6a6eccd6d38f1dac13b32a924fc3ef588168e0dc2d76672bc982a0f2036a362db1bc75431c9df0b851fe41b6040016689b0c2fb9330
|
data/boxr.gemspec
CHANGED
|
@@ -38,5 +38,5 @@ Gem::Specification.new do |spec|
|
|
|
38
38
|
spec.add_runtime_dependency 'addressable', '~> 2.8'
|
|
39
39
|
spec.add_runtime_dependency 'hashie', '>= 3.5', '< 6'
|
|
40
40
|
spec.add_runtime_dependency 'httpclient', '~> 2.8'
|
|
41
|
-
spec.add_runtime_dependency 'jwt', '>= 1.4', '<
|
|
41
|
+
spec.add_runtime_dependency 'jwt', '>= 1.4', '< 4'
|
|
42
42
|
end
|
data/lib/boxr/avatars.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Boxr
|
|
4
|
+
class Client
|
|
5
|
+
def get_user_avatar(user_id)
|
|
6
|
+
user_id = ensure_id(user_id)
|
|
7
|
+
uri = "#{USERS_URI}/#{user_id}/avatar"
|
|
8
|
+
|
|
9
|
+
avatar_data, = get(uri, process_response: false)
|
|
10
|
+
avatar_data
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create_user_avatar(user_id, pic, pic_file_name: nil, pic_content_type: nil)
|
|
14
|
+
user_id = ensure_id(user_id)
|
|
15
|
+
uri = "#{USERS_URI}/#{user_id}/avatar"
|
|
16
|
+
|
|
17
|
+
body = { pic: pic }
|
|
18
|
+
body[:pic_file_name] = pic_file_name unless pic_file_name.nil?
|
|
19
|
+
body[:pic_content_type] = pic_content_type unless pic_content_type.nil?
|
|
20
|
+
|
|
21
|
+
avatar, = post(uri, body, process_body: false, content_type: 'multipart/form-data')
|
|
22
|
+
avatar
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def delete_user_avatar(user_id)
|
|
26
|
+
user_id = ensure_id(user_id)
|
|
27
|
+
uri = "#{USERS_URI}/#{user_id}/avatar"
|
|
28
|
+
|
|
29
|
+
result, = delete(uri)
|
|
30
|
+
result
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/boxr/chunked_uploads.rb
CHANGED
|
@@ -17,7 +17,6 @@ module Boxr
|
|
|
17
17
|
body = { folder_id: parent_id, file_size: io.size, file_name: name }
|
|
18
18
|
session_info, = post(uri, body, content_type: 'application/json',
|
|
19
19
|
success_codes: [200, 201, 202])
|
|
20
|
-
|
|
21
20
|
session_info
|
|
22
21
|
end
|
|
23
22
|
|
|
@@ -35,14 +34,12 @@ module Boxr
|
|
|
35
34
|
body = { file_size: io.size, file_name: name }
|
|
36
35
|
session_info, = post(uri, body, content_type: 'application/json',
|
|
37
36
|
success_codes: [200, 201, 202])
|
|
38
|
-
|
|
39
37
|
session_info
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
def chunked_upload_get_session(session_id)
|
|
43
41
|
uri = "#{UPLOAD_URI}/files/upload_sessions/#{session_id}"
|
|
44
42
|
session_info, = get(uri)
|
|
45
|
-
|
|
46
43
|
session_info
|
|
47
44
|
end
|
|
48
45
|
|
|
@@ -52,20 +49,20 @@ module Boxr
|
|
|
52
49
|
end
|
|
53
50
|
end
|
|
54
51
|
|
|
55
|
-
def chunked_upload_part_from_io(io, session_id, content_range)
|
|
52
|
+
def chunked_upload_part_from_io(io, session_id, content_range) # rubocop:disable Metrics
|
|
56
53
|
io.pos = content_range.min
|
|
57
54
|
part_size = content_range.max - content_range.min + 1
|
|
58
|
-
|
|
55
|
+
body = io.read(part_size)
|
|
59
56
|
io.rewind
|
|
60
57
|
|
|
61
|
-
digest = "sha=#{Digest::SHA1.base64digest(
|
|
58
|
+
digest = "sha=#{Digest::SHA1.base64digest(body)}"
|
|
62
59
|
range = "bytes #{content_range.min}-#{content_range.max}/#{io.size}"
|
|
63
60
|
|
|
64
61
|
uri = "#{UPLOAD_URI}/files/upload_sessions/#{session_id}"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
part_info, = put(
|
|
63
|
+
uri, body, process_body: false, digest: digest, content_type: 'application/octet-stream',
|
|
64
|
+
content_range: range, success_codes: [200, 201, 202]
|
|
65
|
+
)
|
|
69
66
|
part_info.part
|
|
70
67
|
end
|
|
71
68
|
|
|
@@ -75,140 +72,158 @@ module Boxr
|
|
|
75
72
|
query[:limit] = limit unless limit.nil?
|
|
76
73
|
query[:offset] = offset unless offset.nil?
|
|
77
74
|
parts_info, = get(uri, query: query)
|
|
78
|
-
|
|
79
75
|
parts_info.entries
|
|
80
76
|
end
|
|
81
77
|
|
|
82
|
-
def chunked_upload_commit(path_to_file, session_id, parts, content_created_at: nil,
|
|
78
|
+
def chunked_upload_commit(path_to_file, session_id, parts, content_created_at: nil, # rubocop:disable Metrics
|
|
83
79
|
content_modified_at: nil, if_match: nil, if_non_match: nil)
|
|
84
80
|
File.open(path_to_file) do |file|
|
|
85
|
-
chunked_upload_commit_from_io(
|
|
86
|
-
|
|
81
|
+
chunked_upload_commit_from_io(
|
|
82
|
+
file, session_id, parts,
|
|
83
|
+
content_created_at: content_created_at, content_modified_at: content_modified_at,
|
|
84
|
+
if_match: if_match, if_non_match: if_non_match
|
|
85
|
+
)
|
|
87
86
|
end
|
|
88
87
|
end
|
|
89
88
|
|
|
90
|
-
def chunked_upload_commit_from_io(io, session_id, parts, content_created_at: nil,
|
|
89
|
+
def chunked_upload_commit_from_io(io, session_id, parts, content_created_at: nil, # rubocop:disable Metrics
|
|
91
90
|
content_modified_at: nil, if_match: nil, if_non_match: nil)
|
|
92
91
|
io.pos = 0
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
io.rewind
|
|
98
|
-
digest = "sha=#{digest.base64digest}"
|
|
92
|
+
cca = content_created_at
|
|
93
|
+
cma = content_modified_at
|
|
94
|
+
digest = "sha=#{calculate_chunked_upload_digest(io).base64digest}"
|
|
99
95
|
|
|
100
96
|
attributes = {}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
content_created_at.to_datetime.rfc3339
|
|
104
|
-
end
|
|
105
|
-
unless content_modified_at.nil?
|
|
106
|
-
attributes[:content_modified_at] =
|
|
107
|
-
content_modified_at.to_datetime.rfc3339
|
|
108
|
-
end
|
|
97
|
+
attributes[:content_created_at] = cca.to_datetime.rfc3339 if cca
|
|
98
|
+
attributes[:content_modified_at] = cma.to_datetime.rfc3339 if cma
|
|
109
99
|
|
|
110
100
|
uri = "#{UPLOAD_URI}/files/upload_sessions/#{session_id}/commit"
|
|
111
|
-
body = {
|
|
112
|
-
parts: parts,
|
|
113
|
-
attributes: attributes
|
|
114
|
-
}
|
|
115
|
-
commit_info, = post(uri, body, process_body: true, digest: digest,
|
|
116
|
-
content_type: 'application/json', if_match: if_match, if_non_match: if_non_match, success_codes: [200, 201, 202])
|
|
101
|
+
body = { parts: parts, attributes: attributes }
|
|
117
102
|
|
|
118
|
-
|
|
103
|
+
loop do
|
|
104
|
+
commit_info, response = post(
|
|
105
|
+
uri, body,
|
|
106
|
+
process_body: true, digest: digest, content_type: 'application/json',
|
|
107
|
+
if_match: if_match, if_non_match: if_non_match, success_codes: [200, 201, 202]
|
|
108
|
+
)
|
|
109
|
+
return commit_info if response.status != 202
|
|
110
|
+
|
|
111
|
+
sleep response.header['Retry-After'][0].to_i
|
|
112
|
+
end
|
|
119
113
|
end
|
|
120
114
|
|
|
121
115
|
def chunked_upload_abort_session(session_id)
|
|
122
116
|
uri = "#{UPLOAD_URI}/files/upload_sessions/#{session_id}"
|
|
123
117
|
abort_info, = delete(uri)
|
|
124
|
-
|
|
125
118
|
abort_info
|
|
119
|
+
rescue BoxrError # Ignore errors from aborting session
|
|
120
|
+
nil
|
|
126
121
|
end
|
|
127
122
|
|
|
128
|
-
def chunked_upload_file(path_to_file, parent, name: nil, n_threads: 1,
|
|
129
|
-
content_modified_at: nil)
|
|
123
|
+
def chunked_upload_file(path_to_file, parent, name: nil, n_threads: 1, # rubocop:disable Metrics
|
|
124
|
+
content_created_at: nil, content_modified_at: nil)
|
|
130
125
|
filename = name || File.basename(path_to_file)
|
|
131
126
|
|
|
132
127
|
File.open(path_to_file) do |file|
|
|
133
|
-
chunked_upload_file_from_io(
|
|
134
|
-
|
|
128
|
+
chunked_upload_file_from_io(
|
|
129
|
+
file, parent, filename,
|
|
130
|
+
n_threads: n_threads, content_created_at: content_created_at,
|
|
131
|
+
content_modified_at: content_modified_at
|
|
132
|
+
)
|
|
135
133
|
end
|
|
136
134
|
end
|
|
137
135
|
|
|
138
|
-
def chunked_upload_file_from_io(io, parent, name, n_threads: 1,
|
|
139
|
-
content_modified_at: nil)
|
|
140
|
-
session = nil
|
|
141
|
-
file_info = nil
|
|
142
|
-
|
|
136
|
+
def chunked_upload_file_from_io(io, parent, name, n_threads: 1, # rubocop:disable Metrics
|
|
137
|
+
content_created_at: nil, content_modified_at: nil)
|
|
143
138
|
session = chunked_upload_create_session_new_file_from_io(io, parent, name)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
chunked_upload_abort_session(session.id) if file_info.nil? && !session.nil?
|
|
139
|
+
chunked_upload_to_session_from_io(
|
|
140
|
+
io, session,
|
|
141
|
+
n_threads: n_threads, content_created_at: content_created_at,
|
|
142
|
+
content_modified_at: content_modified_at
|
|
143
|
+
)
|
|
150
144
|
end
|
|
151
145
|
|
|
152
|
-
def chunked_upload_new_version_of_file(path_to_file, file, name: nil, n_threads: 1,
|
|
146
|
+
def chunked_upload_new_version_of_file(path_to_file, file, name: nil, n_threads: 1, # rubocop:disable Metrics
|
|
153
147
|
content_created_at: nil, content_modified_at: nil)
|
|
154
148
|
filename = name || File.basename(path_to_file)
|
|
155
149
|
|
|
156
150
|
File.open(path_to_file) do |io|
|
|
157
|
-
chunked_upload_new_version_of_file_from_io(
|
|
158
|
-
|
|
151
|
+
chunked_upload_new_version_of_file_from_io(
|
|
152
|
+
io, file, filename,
|
|
153
|
+
n_threads: n_threads, content_created_at: content_created_at,
|
|
154
|
+
content_modified_at: content_modified_at
|
|
155
|
+
)
|
|
159
156
|
end
|
|
160
157
|
end
|
|
161
158
|
|
|
162
|
-
def chunked_upload_new_version_of_file_from_io(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
file_info = nil
|
|
166
|
-
|
|
159
|
+
def chunked_upload_new_version_of_file_from_io( # rubocop:disable Metrics
|
|
160
|
+
io, file, name, n_threads: 1, content_created_at: nil, content_modified_at: nil
|
|
161
|
+
)
|
|
167
162
|
session = chunked_upload_create_session_new_version_from_io(io, file, name)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
chunked_upload_abort_session(session.id) if file_info.nil? && !session.nil?
|
|
163
|
+
chunked_upload_to_session_from_io(
|
|
164
|
+
io, session,
|
|
165
|
+
n_threads: n_threads, content_created_at: content_created_at,
|
|
166
|
+
content_modified_at: content_modified_at
|
|
167
|
+
)
|
|
174
168
|
end
|
|
175
169
|
|
|
176
170
|
private
|
|
177
171
|
|
|
178
172
|
PARALLEL_GEM_REQUIREMENT = Gem::Requirement.create('~> 1.0').freeze
|
|
179
173
|
|
|
180
|
-
def chunked_upload_to_session_from_io(io, session, n_threads: 1,
|
|
181
|
-
content_modified_at: nil)
|
|
174
|
+
def chunked_upload_to_session_from_io(io, session, n_threads: 1, # rubocop:disable Metrics
|
|
175
|
+
content_created_at: nil, content_modified_at: nil)
|
|
182
176
|
content_ranges = []
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
177
|
+
start_offset = 0
|
|
178
|
+
part_size = session.part_size
|
|
179
|
+
file_size = io.size
|
|
180
|
+
commit_info = nil
|
|
181
|
+
|
|
182
|
+
while start_offset < file_size
|
|
183
|
+
end_offset = [start_offset + part_size, file_size].min - 1
|
|
184
|
+
content_ranges << (start_offset..end_offset)
|
|
185
|
+
start_offset += part_size
|
|
190
186
|
end
|
|
191
187
|
|
|
192
188
|
parts =
|
|
193
189
|
if n_threads > 1
|
|
194
|
-
|
|
195
|
-
raise BoxrError.new(boxr_message: "parallel chunked uploads requires gem parallel (#{PARALLEL_GEM_REQUIREMENT}) to be loaded")
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
Parallel.map(content_ranges, in_threads: n_threads) do |content_range|
|
|
199
|
-
File.open(io.path) do |io_dup|
|
|
200
|
-
chunked_upload_part_from_io(io_dup, session.id, content_range)
|
|
201
|
-
end
|
|
202
|
-
end
|
|
190
|
+
threaded_chunked_upload_part_from_io(io, session.id, content_ranges, n_threads)
|
|
203
191
|
else
|
|
192
|
+
# Single thread
|
|
204
193
|
content_ranges.map do |content_range|
|
|
205
194
|
chunked_upload_part_from_io(io, session.id, content_range)
|
|
206
195
|
end
|
|
207
196
|
end
|
|
208
197
|
|
|
209
|
-
commit_info = chunked_upload_commit_from_io(
|
|
210
|
-
|
|
198
|
+
commit_info = chunked_upload_commit_from_io(
|
|
199
|
+
io, session.id, parts,
|
|
200
|
+
content_created_at: content_created_at, content_modified_at: content_modified_at
|
|
201
|
+
)
|
|
211
202
|
commit_info.entries[0]
|
|
203
|
+
ensure
|
|
204
|
+
chunked_upload_abort_session(session.id) if commit_info.nil? && session
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def threaded_chunked_upload_part_from_io(io, session_id, content_ranges, n_threads)
|
|
208
|
+
unless gem_parallel_available?
|
|
209
|
+
msg = "parallel chunked uploads requires gem 'parallel'"
|
|
210
|
+
raise BoxrError.new(boxr_message: msg)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
Parallel.map(content_ranges, in_threads: n_threads) do |content_range|
|
|
214
|
+
File.open(io.path) do |io_dup|
|
|
215
|
+
chunked_upload_part_from_io(io_dup, session_id, content_range)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def calculate_chunked_upload_digest(io)
|
|
221
|
+
digest = Digest::SHA1.new
|
|
222
|
+
while (buf = io.read(8 * 1024**2)) && buf.size.positive?
|
|
223
|
+
digest.update(buf)
|
|
224
|
+
end
|
|
225
|
+
io.rewind
|
|
226
|
+
digest
|
|
212
227
|
end
|
|
213
228
|
|
|
214
229
|
def gem_parallel_available?
|
data/lib/boxr/client.rb
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Boxr
|
|
4
|
-
class Client
|
|
4
|
+
class Client # rubocop:disable Metrics/ClassLength
|
|
5
5
|
attr_reader :access_token, :refresh_token, :client_id, :client_secret, :identifier, :as_user_id
|
|
6
6
|
|
|
7
|
-
# API_URI = "https://wcheng.inside-box.net/api/2.0"
|
|
8
|
-
# UPLOAD_URI = "https://upload.wcheng.inside-box.net/api/2.0"
|
|
9
|
-
|
|
10
7
|
API_URI = 'https://api.box.com/2.0'
|
|
11
8
|
AUTH_URI = 'https://api.box.com/oauth2/token'
|
|
12
9
|
REVOKE_AUTH_URI = 'https://api.box.com/oauth2/revoke'
|
|
13
10
|
UPLOAD_URI = 'https://upload.box.com/api/2.0'
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
FOLDERS_URI = "#{API_URI}/folders"
|
|
17
|
-
USERS_URI = "#{API_URI}/users"
|
|
18
|
-
GROUPS_URI = "#{API_URI}/groups"
|
|
19
|
-
GROUP_MEMBERSHIPS_URI = "#{API_URI}/group_memberships"
|
|
11
|
+
|
|
12
|
+
ARCHIVES_URI = "#{API_URI}/archives"
|
|
20
13
|
COLLABORATIONS_URI = "#{API_URI}/collaborations"
|
|
21
14
|
COLLECTIONS_URI = "#{API_URI}/collections"
|
|
22
15
|
COMMENTS_URI = "#{API_URI}/comments"
|
|
23
|
-
|
|
24
|
-
TASKS_URI = "#{API_URI}/tasks"
|
|
25
|
-
TASK_ASSIGNMENTS_URI = "#{API_URI}/task_assignments"
|
|
26
|
-
SHARED_ITEMS_URI = "#{API_URI}/shared_items"
|
|
16
|
+
EVENTS_URI = "#{API_URI}/events"
|
|
27
17
|
FILE_METADATA_URI = "#{API_URI}/files"
|
|
18
|
+
FILES_UPLOAD_URI = "#{UPLOAD_URI}/files/content"
|
|
19
|
+
FILES_URI = "#{API_URI}/files"
|
|
28
20
|
FOLDER_METADATA_URI = "#{API_URI}/folders"
|
|
21
|
+
FOLDERS_URI = "#{API_URI}/folders"
|
|
22
|
+
GROUP_MEMBERSHIPS_URI = "#{API_URI}/group_memberships"
|
|
23
|
+
GROUPS_URI = "#{API_URI}/groups"
|
|
29
24
|
METADATA_TEMPLATES_URI = "#{API_URI}/metadata_templates"
|
|
30
|
-
|
|
25
|
+
SEARCH_URI = "#{API_URI}/search"
|
|
26
|
+
SHARED_ITEMS_URI = "#{API_URI}/shared_items"
|
|
27
|
+
TASK_ASSIGNMENTS_URI = "#{API_URI}/task_assignments"
|
|
28
|
+
TASKS_URI = "#{API_URI}/tasks"
|
|
29
|
+
USERS_URI = "#{API_URI}/users"
|
|
31
30
|
WEB_LINKS_URI = "#{API_URI}/web_links"
|
|
32
31
|
WEBHOOKS_URI = "#{API_URI}/webhooks"
|
|
33
32
|
ZIP_DOWNLOADS_URI = "#{API_URI}/zip_downloads"
|
|
34
33
|
|
|
34
|
+
BOX_VERSION_HEADER_2025 = { 'box-version' => '2025.0' }.freeze
|
|
35
|
+
|
|
35
36
|
DEFAULT_LIMIT = 100
|
|
36
37
|
FOLDER_ITEMS_LIMIT = 1000
|
|
37
38
|
|
|
@@ -101,13 +102,14 @@ module Boxr
|
|
|
101
102
|
private
|
|
102
103
|
|
|
103
104
|
def get(uri, query: nil, success_codes: [200], process_response: true, if_match: nil,
|
|
104
|
-
box_api_header: nil, follow_redirect: true)
|
|
105
|
+
box_api_header: nil, follow_redirect: true, extra_headers: nil)
|
|
105
106
|
uri = Addressable::URI.encode(uri)
|
|
106
107
|
|
|
107
108
|
res = with_auto_token_refresh do
|
|
108
109
|
headers = standard_headers
|
|
109
110
|
headers['If-Match'] = if_match unless if_match.nil?
|
|
110
111
|
headers['BoxApi'] = box_api_header unless box_api_header.nil?
|
|
112
|
+
headers.merge!(extra_headers) unless extra_headers.nil?
|
|
111
113
|
|
|
112
114
|
BOX_CLIENT.get(uri, query: query, header: headers, follow_redirect: follow_redirect)
|
|
113
115
|
end
|
|
@@ -151,7 +153,7 @@ module Boxr
|
|
|
151
153
|
end
|
|
152
154
|
|
|
153
155
|
def post(uri, body, query: nil, success_codes: [201], process_body: true, digest: nil,
|
|
154
|
-
content_md5: nil, content_type: nil, if_match: nil, if_non_match: nil)
|
|
156
|
+
content_md5: nil, content_type: nil, if_match: nil, if_non_match: nil, extra_headers: nil)
|
|
155
157
|
uri = Addressable::URI.encode(uri)
|
|
156
158
|
body = JSON.dump(body) if process_body
|
|
157
159
|
|
|
@@ -162,6 +164,7 @@ module Boxr
|
|
|
162
164
|
headers['Content-MD5'] = content_md5 unless content_md5.nil?
|
|
163
165
|
headers['Content-Type'] = content_type unless content_type.nil?
|
|
164
166
|
headers['Digest'] = digest unless digest.nil?
|
|
167
|
+
headers.merge!(extra_headers) unless extra_headers.nil?
|
|
165
168
|
|
|
166
169
|
BOX_CLIENT.post(uri, body: body, query: query, header: headers)
|
|
167
170
|
end
|
|
@@ -172,7 +175,7 @@ module Boxr
|
|
|
172
175
|
end
|
|
173
176
|
|
|
174
177
|
def put(uri, body, query: nil, success_codes: [200, 201], process_body: true,
|
|
175
|
-
content_type: nil, content_range: nil, digest: nil, if_match: nil)
|
|
178
|
+
content_type: nil, content_range: nil, digest: nil, if_match: nil, extra_headers: nil)
|
|
176
179
|
uri = Addressable::URI.encode(uri)
|
|
177
180
|
body = JSON.dump(body) if process_body
|
|
178
181
|
|
|
@@ -182,6 +185,7 @@ module Boxr
|
|
|
182
185
|
headers['Content-Type'] = content_type unless content_type.nil?
|
|
183
186
|
headers['Content-Range'] = content_range unless content_range.nil?
|
|
184
187
|
headers['Digest'] = digest unless digest.nil?
|
|
188
|
+
headers.merge!(extra_headers) unless extra_headers.nil?
|
|
185
189
|
|
|
186
190
|
BOX_CLIENT.put(uri, body: body, query: query, header: headers)
|
|
187
191
|
end
|
|
@@ -191,12 +195,13 @@ module Boxr
|
|
|
191
195
|
processed_response(res)
|
|
192
196
|
end
|
|
193
197
|
|
|
194
|
-
def delete(uri, query: nil, success_codes: [204], if_match: nil)
|
|
198
|
+
def delete(uri, query: nil, success_codes: [204], if_match: nil, extra_headers: nil)
|
|
195
199
|
uri = Addressable::URI.encode(uri)
|
|
196
200
|
|
|
197
201
|
res = with_auto_token_refresh do
|
|
198
202
|
headers = standard_headers
|
|
199
203
|
headers['If-Match'] = if_match unless if_match.nil?
|
|
204
|
+
headers.merge!(extra_headers) unless extra_headers.nil?
|
|
200
205
|
|
|
201
206
|
BOX_CLIENT.delete(uri, query: query, header: headers)
|
|
202
207
|
end
|
data/lib/boxr/collections.rb
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Boxr
|
|
4
4
|
class Client
|
|
5
|
+
def collection_from_id(collection_id)
|
|
6
|
+
collection_id = ensure_id(collection_id)
|
|
7
|
+
uri = "#{COLLECTIONS_URI}/#{collection_id}"
|
|
8
|
+
|
|
9
|
+
collection, = get(uri)
|
|
10
|
+
collection
|
|
11
|
+
end
|
|
12
|
+
alias collection collection_from_id
|
|
13
|
+
|
|
5
14
|
def collections
|
|
6
15
|
get_all_with_pagination(COLLECTIONS_URI, offset: 0, limit: DEFAULT_LIMIT)
|
|
7
16
|
end
|
data/lib/boxr/files.rb
CHANGED
|
@@ -34,8 +34,8 @@ module Boxr
|
|
|
34
34
|
alias preview_url embed_url
|
|
35
35
|
alias preview_link embed_url
|
|
36
36
|
|
|
37
|
-
def update_file(file, name: nil, description: nil, parent: nil,
|
|
38
|
-
lock: nil, if_match: nil)
|
|
37
|
+
def update_file(file, name: nil, description: nil, parent: nil, # rubocop:disable Metrics
|
|
38
|
+
shared_link: nil, tags: nil, lock: nil, if_match: nil)
|
|
39
39
|
file_id = ensure_id(file)
|
|
40
40
|
parent_id = ensure_id(parent)
|
|
41
41
|
uri = "#{FILES_URI}/#{file_id}"
|
|
@@ -73,14 +73,18 @@ module Boxr
|
|
|
73
73
|
update_file(file, parent: new_parent, name: name, if_match: if_match)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
def download_file(file, version: nil, follow_redirect: true)
|
|
76
|
+
def download_file(file, version: nil, follow_redirect: true) # rubocop:disable Metrics
|
|
77
77
|
file_id = ensure_id(file)
|
|
78
|
+
uri = "#{FILES_URI}/#{file_id}/content"
|
|
79
|
+
query = {}
|
|
80
|
+
query[:version] = version unless version.nil?
|
|
78
81
|
|
|
79
82
|
loop do
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
# Don't automatically follow the redirect
|
|
84
|
+
_, response = get(uri, query: query, success_codes: [302, 202],
|
|
85
|
+
process_response: false, follow_redirect: false)
|
|
86
|
+
|
|
87
|
+
# By default, Box always returns a 302
|
|
84
88
|
if response.status == 302
|
|
85
89
|
location = response.header['Location'][0]
|
|
86
90
|
return location unless follow_redirect
|
|
@@ -88,13 +92,9 @@ module Boxr
|
|
|
88
92
|
file_content, = get(location, process_response: false)
|
|
89
93
|
return file_content
|
|
90
94
|
|
|
91
|
-
# simply return the url
|
|
92
|
-
|
|
93
95
|
elsif response.status == 202
|
|
94
|
-
|
|
95
|
-
sleep retry_after_seconds.to_i
|
|
96
|
+
sleep response.header['Retry-After'][0].to_i
|
|
96
97
|
end
|
|
97
|
-
break if file_content
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -102,18 +102,21 @@ module Boxr
|
|
|
102
102
|
download_file(file, version: version, follow_redirect: false)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
def upload_file(path_to_file, parent, name: nil, content_created_at: nil,
|
|
106
|
-
preflight_check: true, send_content_md5: true)
|
|
105
|
+
def upload_file(path_to_file, parent, name: nil, content_created_at: nil, # rubocop:disable Metrics
|
|
106
|
+
content_modified_at: nil, preflight_check: true, send_content_md5: true)
|
|
107
107
|
filename = name || File.basename(path_to_file)
|
|
108
108
|
|
|
109
109
|
File.open(path_to_file) do |file|
|
|
110
|
-
upload_file_from_io(
|
|
111
|
-
|
|
110
|
+
upload_file_from_io(
|
|
111
|
+
file, parent, name: filename, content_created_at: content_created_at,
|
|
112
|
+
content_modified_at: content_modified_at, preflight_check: preflight_check,
|
|
113
|
+
send_content_md5: send_content_md5
|
|
114
|
+
)
|
|
112
115
|
end
|
|
113
116
|
end
|
|
114
117
|
|
|
115
|
-
def upload_file_from_io(io, parent, name:, content_created_at: nil,
|
|
116
|
-
preflight_check: true, send_content_md5: true)
|
|
118
|
+
def upload_file_from_io(io, parent, name:, content_created_at: nil, # rubocop:disable Metrics
|
|
119
|
+
content_modified_at: nil, preflight_check: true, send_content_md5: true)
|
|
117
120
|
parent_id = ensure_id(parent)
|
|
118
121
|
|
|
119
122
|
preflight_check(io, name, parent_id) if preflight_check
|
|
@@ -141,18 +144,25 @@ module Boxr
|
|
|
141
144
|
file_info.entries[0]
|
|
142
145
|
end
|
|
143
146
|
|
|
144
|
-
def upload_new_version_of_file(
|
|
145
|
-
|
|
147
|
+
def upload_new_version_of_file( # rubocop:disable Metrics
|
|
148
|
+
path_to_file, file, content_modified_at: nil,
|
|
149
|
+
send_content_md5: true, preflight_check: true, if_match: nil, name: nil
|
|
150
|
+
)
|
|
146
151
|
filename = name || File.basename(path_to_file)
|
|
147
152
|
|
|
148
153
|
File.open(path_to_file) do |io|
|
|
149
|
-
upload_new_version_of_file_from_io(
|
|
150
|
-
|
|
154
|
+
upload_new_version_of_file_from_io(
|
|
155
|
+
io, file,
|
|
156
|
+
name: filename, content_modified_at: content_modified_at,
|
|
157
|
+
preflight_check: preflight_check, send_content_md5: send_content_md5, if_match: if_match
|
|
158
|
+
)
|
|
151
159
|
end
|
|
152
160
|
end
|
|
153
161
|
|
|
154
|
-
def upload_new_version_of_file_from_io(
|
|
155
|
-
|
|
162
|
+
def upload_new_version_of_file_from_io( # rubocop:disable Metrics
|
|
163
|
+
io, file, name: nil, content_modified_at: nil,
|
|
164
|
+
send_content_md5: true, preflight_check: true, if_match: nil
|
|
165
|
+
)
|
|
156
166
|
name || file.name
|
|
157
167
|
|
|
158
168
|
file_id = ensure_id(file)
|
|
@@ -173,8 +183,9 @@ module Boxr
|
|
|
173
183
|
|
|
174
184
|
body = { attributes: JSON.dump(attributes), file: io }
|
|
175
185
|
|
|
176
|
-
file_info, = post(
|
|
177
|
-
|
|
186
|
+
file_info, = post(
|
|
187
|
+
uri, body, process_body: false, content_md5: content_md5, if_match: if_match
|
|
188
|
+
)
|
|
178
189
|
|
|
179
190
|
file_info.entries[0]
|
|
180
191
|
end
|
|
@@ -225,7 +236,7 @@ module Boxr
|
|
|
225
236
|
new_file
|
|
226
237
|
end
|
|
227
238
|
|
|
228
|
-
def thumbnail(file, min_height: nil, min_width: nil, max_height: nil, max_width: nil)
|
|
239
|
+
def thumbnail(file, min_height: nil, min_width: nil, max_height: nil, max_width: nil) # rubocop:disable Metrics
|
|
229
240
|
file_id = ensure_id(file)
|
|
230
241
|
uri = "#{FILES_URI}/#{file_id}/thumbnail.png"
|
|
231
242
|
query = {}
|
|
@@ -246,8 +257,8 @@ module Boxr
|
|
|
246
257
|
thumbnail
|
|
247
258
|
end
|
|
248
259
|
|
|
249
|
-
def create_shared_link_for_file(file, access: nil, unshared_at: nil,
|
|
250
|
-
can_preview: nil, password: nil)
|
|
260
|
+
def create_shared_link_for_file(file, access: nil, unshared_at: nil, # rubocop:disable Metrics
|
|
261
|
+
can_download: nil, can_preview: nil, password: nil)
|
|
251
262
|
file_id = ensure_id(file)
|
|
252
263
|
uri = "#{FILES_URI}/#{file_id}"
|
|
253
264
|
create_shared_link(uri, file_id, access, unshared_at, can_download, can_preview, password)
|
data/lib/boxr/version.rb
CHANGED
data/lib/boxr.rb
CHANGED
|
@@ -7,27 +7,28 @@ require 'addressable/template'
|
|
|
7
7
|
require 'jwt'
|
|
8
8
|
require 'securerandom'
|
|
9
9
|
|
|
10
|
-
require 'boxr/
|
|
11
|
-
require 'boxr/
|
|
12
|
-
require 'boxr/client'
|
|
13
|
-
require 'boxr/shared_items'
|
|
14
|
-
require 'boxr/folders'
|
|
15
|
-
require 'boxr/files'
|
|
10
|
+
require 'boxr/auth'
|
|
11
|
+
require 'boxr/avatars'
|
|
16
12
|
require 'boxr/chunked_uploads'
|
|
17
|
-
require 'boxr/
|
|
18
|
-
require 'boxr/users'
|
|
19
|
-
require 'boxr/groups'
|
|
13
|
+
require 'boxr/client'
|
|
20
14
|
require 'boxr/collaborations'
|
|
21
15
|
require 'boxr/collections'
|
|
16
|
+
require 'boxr/comments'
|
|
17
|
+
require 'boxr/errors'
|
|
18
|
+
require 'boxr/events'
|
|
19
|
+
require 'boxr/files'
|
|
20
|
+
require 'boxr/folders'
|
|
21
|
+
require 'boxr/groups'
|
|
22
|
+
require 'boxr/metadata'
|
|
22
23
|
require 'boxr/search'
|
|
24
|
+
require 'boxr/shared_items'
|
|
23
25
|
require 'boxr/tasks'
|
|
24
|
-
require 'boxr/
|
|
25
|
-
require 'boxr/
|
|
26
|
-
require 'boxr/auth'
|
|
27
|
-
require 'boxr/web_links'
|
|
26
|
+
require 'boxr/users'
|
|
27
|
+
require 'boxr/version'
|
|
28
28
|
require 'boxr/watermarking'
|
|
29
|
-
require 'boxr/
|
|
29
|
+
require 'boxr/web_links'
|
|
30
30
|
require 'boxr/webhook_validator'
|
|
31
|
+
require 'boxr/webhooks'
|
|
31
32
|
require 'boxr/zip_downloads'
|
|
32
33
|
|
|
33
34
|
# Simple wrapper around Array
|
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: boxr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.24.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chad Burnette
|
|
8
8
|
- Xavier Hocquet
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: awesome_print
|
|
@@ -250,7 +249,7 @@ dependencies:
|
|
|
250
249
|
version: '1.4'
|
|
251
250
|
- - "<"
|
|
252
251
|
- !ruby/object:Gem::Version
|
|
253
|
-
version: '
|
|
252
|
+
version: '4'
|
|
254
253
|
type: :runtime
|
|
255
254
|
prerelease: false
|
|
256
255
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -260,7 +259,7 @@ dependencies:
|
|
|
260
259
|
version: '1.4'
|
|
261
260
|
- - "<"
|
|
262
261
|
- !ruby/object:Gem::Version
|
|
263
|
-
version: '
|
|
262
|
+
version: '4'
|
|
264
263
|
description: ''
|
|
265
264
|
email:
|
|
266
265
|
- chadburnette@me.com
|
|
@@ -293,6 +292,7 @@ files:
|
|
|
293
292
|
- examples/user_events.rb
|
|
294
293
|
- lib/boxr.rb
|
|
295
294
|
- lib/boxr/auth.rb
|
|
295
|
+
- lib/boxr/avatars.rb
|
|
296
296
|
- lib/boxr/chunked_uploads.rb
|
|
297
297
|
- lib/boxr/client.rb
|
|
298
298
|
- lib/boxr/collaborations.rb
|
|
@@ -318,7 +318,6 @@ homepage: https://github.com/cburnette/boxr
|
|
|
318
318
|
licenses:
|
|
319
319
|
- MIT
|
|
320
320
|
metadata: {}
|
|
321
|
-
post_install_message:
|
|
322
321
|
rdoc_options: []
|
|
323
322
|
require_paths:
|
|
324
323
|
- lib
|
|
@@ -333,8 +332,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
333
332
|
- !ruby/object:Gem::Version
|
|
334
333
|
version: '0'
|
|
335
334
|
requirements: []
|
|
336
|
-
rubygems_version:
|
|
337
|
-
signing_key:
|
|
335
|
+
rubygems_version: 4.0.3
|
|
338
336
|
specification_version: 4
|
|
339
337
|
summary: A Ruby client library for the Box V2 Content API.
|
|
340
338
|
test_files: []
|