mass-client 1.0.38 → 1.0.39
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/lib/base-line/profile.rb +145 -15
- data/lib/mass-client.rb +24 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2f41c23dfa363362e8822c9c590dd0feb49fa8d7a0b46a4404289b3aaf36521d
|
|
4
|
+
data.tar.gz: d0378de6d177de59b594a0b40ad32a66ffc95ffaff456316843ee7ce7dd6b994
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40c38809a571acd66f9418892ebe4c4eaca23f01b78beed63faa9e1333b197a2a8e6575c6985f7186868d8d999efb419de5f70066b98fad9f64805dd8914e018
|
|
7
|
+
data.tar.gz: 78d3f81da07f724a42bbce1d53dfd2329a53a8c0c4874e8d728e7dba7a517087bedd20609a0fe77ac1916acee6ecda0248d0ce9fa7748a5b6100bf016a3d5cb2
|
data/lib/base-line/profile.rb
CHANGED
|
@@ -28,25 +28,35 @@ module Mass
|
|
|
28
28
|
|
|
29
29
|
# Function to upload a file to Amazon S3 and get its public URL
|
|
30
30
|
def upload_file_to_s3(file_path, s3_key)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
if @s3
|
|
32
|
+
# Upload the file
|
|
33
|
+
Mass.s3.put_object(
|
|
34
|
+
bucket: Mass.s3_bucket,
|
|
35
|
+
key: s3_key,
|
|
36
|
+
body: File.open(file_path)
|
|
37
|
+
)
|
|
38
|
+
# Generate the public URL
|
|
39
|
+
public_url = "https://#{Mass.s3_bucket}.s3.amazonaws.com/#{s3_key}"
|
|
40
|
+
# return
|
|
41
|
+
return public_url
|
|
42
|
+
elsif Mass.my_s3_api_key && Mass.my_s3_url
|
|
43
|
+
my_s3_upload_file(file_path, s3_key)
|
|
44
|
+
return my_s3_public_url_for(s3_key)
|
|
45
|
+
end
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
# Function to create a folder in S3
|
|
44
49
|
def create_s3_folder(folder_name)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
if @s3
|
|
51
|
+
Mass.s3.put_object(
|
|
52
|
+
bucket: Mass.s3_bucket,
|
|
53
|
+
key: "#{folder_name}/"
|
|
54
|
+
)
|
|
55
|
+
return true
|
|
56
|
+
elsif Mass.my_s3_api_key && Mass.my_s3_url
|
|
57
|
+
ensure_my_s3_path_exists(folder_name)
|
|
58
|
+
return true
|
|
59
|
+
end
|
|
50
60
|
end
|
|
51
61
|
|
|
52
62
|
#
|
|
@@ -273,5 +283,125 @@ module Mass
|
|
|
273
283
|
[]
|
|
274
284
|
end # def connectioncheck
|
|
275
285
|
|
|
286
|
+
class MyS3Error < StandardError; end
|
|
287
|
+
|
|
288
|
+
private
|
|
289
|
+
|
|
290
|
+
def ensure_my_s3_path_exists(path)
|
|
291
|
+
sanitized = path.to_s.strip.gsub(%r{^/+|/+$}, '')
|
|
292
|
+
return true if sanitized.empty?
|
|
293
|
+
|
|
294
|
+
current = ''
|
|
295
|
+
sanitized.split('/').each do |segment|
|
|
296
|
+
parent = current
|
|
297
|
+
begin
|
|
298
|
+
my_s3_json_post('/create_folder.json', {
|
|
299
|
+
path: parent,
|
|
300
|
+
folder_name: segment
|
|
301
|
+
})
|
|
302
|
+
rescue MyS3Error => e
|
|
303
|
+
raise unless e.message =~ /folder already exists/i
|
|
304
|
+
end
|
|
305
|
+
current = parent.empty? ? segment : [parent, segment].join('/').gsub(%r{/+}, '/').sub(%r{^/+}, '')
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
true
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def my_s3_upload_file(local_path, remote_path)
|
|
312
|
+
raise MyS3Error, 'Local file not found' unless File.file?(local_path)
|
|
313
|
+
|
|
314
|
+
relative_path = File.dirname(remote_path.to_s)
|
|
315
|
+
relative_path = '' if relative_path == '.'
|
|
316
|
+
filename = File.basename(remote_path.to_s).to_s
|
|
317
|
+
raise MyS3Error, 'Remote filename is required' if filename.strip.empty?
|
|
318
|
+
|
|
319
|
+
uri = my_s3_uri_for('/upload.json')
|
|
320
|
+
boundary = "----MassMyS3#{SecureRandom.hex(12)}"
|
|
321
|
+
request = Net::HTTP::Post.new(uri)
|
|
322
|
+
request['X-API-Key'] = my_s3_api_key!
|
|
323
|
+
request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
|
|
324
|
+
request.body = build_my_s3_multipart(boundary, relative_path, filename, local_path)
|
|
325
|
+
|
|
326
|
+
response = my_s3_http(uri).request(request)
|
|
327
|
+
json = parse_my_s3_json(response.body)
|
|
328
|
+
return json if response.is_a?(Net::HTTPSuccess) && json['success']
|
|
329
|
+
|
|
330
|
+
message = json.dig('error', 'message') || response.body
|
|
331
|
+
raise MyS3Error, message
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def my_s3_public_url_for(remote_path)
|
|
335
|
+
dir = File.dirname(remote_path.to_s)
|
|
336
|
+
dir = '' if dir == '.'
|
|
337
|
+
filename = File.basename(remote_path.to_s)
|
|
338
|
+
raise MyS3Error, 'Filename is required for public URL generation' if filename.to_s.strip.empty?
|
|
339
|
+
|
|
340
|
+
response = my_s3_json_post('/get_public_url.json', {
|
|
341
|
+
path: dir,
|
|
342
|
+
filename: filename
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
response['public_url']
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def build_my_s3_multipart(boundary, relative_path, filename, local_path)
|
|
349
|
+
body = []
|
|
350
|
+
body << "--#{boundary}\r\n"
|
|
351
|
+
body << "Content-Disposition: form-data; name=\"path\"\r\n\r\n"
|
|
352
|
+
body << "#{relative_path}\r\n"
|
|
353
|
+
body << "--#{boundary}\r\n"
|
|
354
|
+
body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{filename}\"\r\n"
|
|
355
|
+
body << "Content-Type: application/octet-stream\r\n\r\n"
|
|
356
|
+
body << File.binread(local_path)
|
|
357
|
+
body << "\r\n--#{boundary}--\r\n"
|
|
358
|
+
body.join
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def my_s3_json_post(endpoint, payload)
|
|
362
|
+
uri = my_s3_uri_for(endpoint)
|
|
363
|
+
request = Net::HTTP::Post.new(uri)
|
|
364
|
+
request['Content-Type'] = 'application/json'
|
|
365
|
+
request['X-API-Key'] = my_s3_api_key!
|
|
366
|
+
request.body = JSON.generate(payload)
|
|
367
|
+
|
|
368
|
+
response = my_s3_http(uri).request(request)
|
|
369
|
+
json = parse_my_s3_json(response.body)
|
|
370
|
+
return json if response.is_a?(Net::HTTPSuccess) && json['success']
|
|
371
|
+
|
|
372
|
+
message = json.dig('error', 'message') || response.body
|
|
373
|
+
raise MyS3Error, message
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def parse_my_s3_json(body)
|
|
377
|
+
return {} if body.nil? || body.strip.empty?
|
|
378
|
+
JSON.parse(body)
|
|
379
|
+
rescue JSON::ParserError
|
|
380
|
+
raise MyS3Error, "Invalid JSON response: #{body}"
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def my_s3_uri_for(endpoint)
|
|
384
|
+
normalized = my_s3_base_url!
|
|
385
|
+
URI.join(normalized, endpoint.to_s.sub(%r{^/+}, ''))
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def my_s3_http(uri)
|
|
389
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
390
|
+
http.use_ssl = uri.scheme == 'https'
|
|
391
|
+
http
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def my_s3_base_url!
|
|
395
|
+
base = Mass.my_s3_url.to_s.strip
|
|
396
|
+
raise MyS3Error, 'Mass.my_s3_url is not configured' if base.empty?
|
|
397
|
+
base.end_with?('/') ? base : "#{base}/"
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def my_s3_api_key!
|
|
401
|
+
key = Mass.my_s3_api_key.to_s.strip
|
|
402
|
+
raise MyS3Error, 'Mass.my_s3_api_key is not configured' if key.empty?
|
|
403
|
+
key
|
|
404
|
+
end
|
|
405
|
+
|
|
276
406
|
end # class Profile
|
|
277
407
|
end # module Mass
|
data/lib/mass-client.rb
CHANGED
|
@@ -17,12 +17,17 @@ module Mass
|
|
|
17
17
|
@@drownload_path
|
|
18
18
|
@@api_client
|
|
19
19
|
|
|
20
|
+
# DEPRECATED
|
|
20
21
|
@@s3_bucket
|
|
21
22
|
@@s3_region
|
|
22
23
|
@@s3_access_key_id
|
|
23
24
|
@@s3_secret_access_key
|
|
24
25
|
@@s3
|
|
25
26
|
|
|
27
|
+
# https://github.com/MassProspecting/developer-documentation/issues/828
|
|
28
|
+
@@my_s3_api_key
|
|
29
|
+
@@my_s3_url
|
|
30
|
+
|
|
26
31
|
# set the MassProspecting API client
|
|
27
32
|
#
|
|
28
33
|
# Parameters:
|
|
@@ -54,10 +59,15 @@ module Mass
|
|
|
54
59
|
js_path: nil,
|
|
55
60
|
download_path: [],
|
|
56
61
|
|
|
62
|
+
# DEPRECATED
|
|
57
63
|
s3_region: nil,
|
|
58
64
|
s3_access_key_id: nil,
|
|
59
65
|
s3_secret_access_key: nil,
|
|
60
|
-
s3_bucket: nil
|
|
66
|
+
s3_bucket: nil,
|
|
67
|
+
|
|
68
|
+
# https://github.com/MassProspecting/developer-documentation/issues/828
|
|
69
|
+
my_s3_api_key: nil,
|
|
70
|
+
my_s3_url: nil
|
|
61
71
|
)
|
|
62
72
|
# call the master to get the URL and port of the subaccount.
|
|
63
73
|
BlackStack::API.set_client(
|
|
@@ -101,6 +111,7 @@ module Mass
|
|
|
101
111
|
@@js_path = js_path
|
|
102
112
|
@@download_path = download_path
|
|
103
113
|
|
|
114
|
+
@@s3 = nil
|
|
104
115
|
@@s3_region = s3_region
|
|
105
116
|
@@s3_access_key_id = s3_access_key_id
|
|
106
117
|
@@s3_secret_access_key = s3_secret_access_key
|
|
@@ -119,6 +130,10 @@ module Mass
|
|
|
119
130
|
secret_access_key: @@s3_secret_access_key
|
|
120
131
|
)
|
|
121
132
|
end
|
|
133
|
+
|
|
134
|
+
# Initialize My.S3 API key
|
|
135
|
+
@@my_s3_api_key = my_s3_api_key
|
|
136
|
+
@@my_s3_url = my_s3_url
|
|
122
137
|
end
|
|
123
138
|
|
|
124
139
|
def self.download_path
|
|
@@ -149,6 +164,14 @@ module Mass
|
|
|
149
164
|
@@s3
|
|
150
165
|
end
|
|
151
166
|
|
|
167
|
+
def self.my_s3_api_key
|
|
168
|
+
@@my_s3_api_key
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.my_s3_url
|
|
172
|
+
@@my_s3_url
|
|
173
|
+
end
|
|
174
|
+
|
|
152
175
|
end # module Mass
|
|
153
176
|
|
|
154
177
|
# base classes
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mass-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.39
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Leandro Daniel Sardi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-02-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: timeout
|