uploadcare-ruby 4.3.6 → 4.4.1

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: 274b1a99804055c03bbd9642e79b3ae718ad95711a3a0066a95199929c6d42ea
4
- data.tar.gz: 15240af810033c45a69c96dfde93b949654d55fbf370bb3b046122d17a6b0dd1
3
+ metadata.gz: 1cd6e50f0d12bc1cd65c531fa7e5656e41149433c042aedeb5d8899425ae6e53
4
+ data.tar.gz: baa9f7cc358eba65895e608073d2ad188bc68ff1b5a44b8c51e6d5b2e72fc8bb
5
5
  SHA512:
6
- metadata.gz: '0487759949cdbbf23e9b5d61b6e49bd005a6e895d42a37ddd2c24852537a594ae740c14c073079a22c19674c184fb50f55f5e1b2234e4e3f90b54f5fc5ae46a8'
7
- data.tar.gz: fbd9198af4353d674df9795294c38cd486dab631b1de3824f5b02368d081fc199ba981092b6f074d06752d99f9b1574737005d0087b4c956ddd86af1562f8f87
6
+ metadata.gz: eab5bac3add563b090d18e7f82e2c7c852e95ff0d99530f8a3d25ec2d9eb47f1d146d38fc3dec9335af3bb9cebb74079b5fb27d3f46c7c1971d892185607df06
7
+ data.tar.gz: 2edc0a691512ac31210f5fada71d7515c59ac8305c5a522e04f2f90924af313cdba4707860e8bb6d1aaeec4053cff0869f0f5f14a458d33832c57587d3ab9822
@@ -16,17 +16,17 @@ jobs:
16
16
  strategy:
17
17
  matrix:
18
18
  ruby-version:
19
- - 2.7
20
19
  - 3.0
21
20
  - 3.1
22
21
  - 3.2
22
+ - 3.3
23
23
 
24
24
  steps:
25
25
  - uses: actions/checkout@v3
26
26
  - name: Set up Ruby
27
27
  uses: ruby/setup-ruby@v1
28
28
  with:
29
- bundler: 2.4
29
+ bundler: latest
30
30
  ruby-version: ${{ matrix.ruby-version }}
31
31
  bundler-cache: true
32
32
  - name: Run tests
@@ -41,8 +41,7 @@ jobs:
41
41
  strategy:
42
42
  matrix:
43
43
  ruby-version:
44
- - 2.7
45
- - 3.2
44
+ - 3.3
46
45
  steps:
47
46
  - uses: actions/checkout@v3
48
47
  - name: Set up Ruby
data/.rubocop.yml CHANGED
@@ -1,9 +1,11 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
- TargetRubyVersion: 2.7
3
+ TargetRubyVersion: 3.0
4
4
 
5
5
  Layout/LineLength:
6
6
  Max: 120
7
+ Exclude:
8
+ - 'spec/**/*'
7
9
 
8
10
  Lint/IneffectiveAccessModifier:
9
11
  Enabled: false
@@ -14,16 +16,16 @@ Style/HashTransformKeys:
14
16
  - 'lib/uploadcare/client/conversion/video_conversion_client.rb'
15
17
  - 'lib/uploadcare/entity/file.rb'
16
18
 
17
- Gemspec/RequiredRubyVersion:
18
- Exclude:
19
- - 'uploadcare-ruby.gemspec'
20
-
21
19
  Metrics/BlockLength:
22
20
  Exclude:
23
21
  - 'bin/'
24
22
  - 'spec/**/*'
25
23
  - 'uploadcare-ruby.gemspec'
26
24
 
25
+ Metrics/ModuleLength:
26
+ Exclude:
27
+ - 'spec/**/*'
28
+
27
29
  Metrics/MethodLength:
28
30
  Max: 20
29
31
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.4.1 — 2024-04-27
4
+
5
+ ### Added
6
+ * Added `AWS Rekognition Moderation` Add-On.
7
+ * Added an optional `wildcard` boolean parameter to the `generate_url` method of `AkamaiGenerator`.
8
+
9
+ ### Changed
10
+ * File attribute `datetime_stored` is deprecated and will warn on usage from `File` object properties.
11
+
12
+ ### Fixed
13
+
14
+ * Throw `AuthError` if current public key or secret key config are empty when accessing any of the APIs.
15
+ * `AmakaiGenerator` has been renamed to `AkamaiGenerator` to fix typo in class name.
16
+
17
+ ## 4.4.0 — 2024-03-09
18
+
19
+ ### Breaking
20
+
21
+ * Drop support of unmaintainable Ruby versions < 3.x.
22
+
23
+ ### Fixed
24
+
25
+ * Update locations where Dry::Monads structure has changed.
26
+ * Sign URL uploads if configured (#139).
27
+ * Start returning proper error message when raising RequestError in poll_upload_response, to hint to users what is going on. Fixes #141.
28
+ * When polling, raise if an error is returned (#142).
29
+ * Fix documentation about original file url on simple file upload.
30
+
31
+ ### Changed
32
+ * Support params in Rest client and in file info method, to allow passing custom params like "include=appdata" in `Uploadcare::File.file` calls. Closes #132.
33
+
34
+
3
35
  ## 4.3.6 — 2023-11-18
4
36
 
5
37
  ### Fixed
@@ -50,7 +82,7 @@ Add support of new ruby versions
50
82
  ### Breaking Сhanges
51
83
 
52
84
  - Drop support of unmaintainable Ruby versions (2.4, 2.5, 2.6).
53
- - Replace unmaintainable `api_struct` with `uploadcare-api_struct`
85
+ - Replace unmaintainable `api_struct` with `uploadcare-api_struct`
54
86
 
55
87
  ### Added
56
88
 
data/Gemfile CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'byebug', '~> 11.1'
6
- gem 'rake', '~> 13.0'
7
- gem 'rspec', '~> 3.0'
8
- gem 'rubocop', '~> 1.48'
9
- gem 'vcr', '~> 6.1'
10
- gem 'webmock', '~> 3.18'
5
+ gem 'byebug'
6
+ gem 'rake'
7
+ gem 'rspec'
8
+ gem 'rubocop'
9
+ gem 'vcr'
10
+ gem 'webmock'
11
11
 
12
12
  # Specify your gem's dependencies in uploadcare-ruby.gemspec
13
13
  gemspec
data/README.md CHANGED
@@ -34,7 +34,7 @@ wrapping Upload and REST APIs.
34
34
  * [Useful links](#useful-links)
35
35
 
36
36
  ## Requirements
37
- * ruby 2.7+
37
+ * ruby 3.0+
38
38
 
39
39
  ## Compatibility
40
40
 
@@ -95,23 +95,25 @@ Using Uploadcare is simple, and here are the basics of handling files.
95
95
  ```ruby
96
96
  @file_to_upload = File.open("your-file.png")
97
97
 
98
- @uc_file = Uploadcare::Uploader.upload(@file_to_upload)
98
+ @uc_file = Uploadcare::Uploader.upload(@file_to_upload, store: "auto")
99
99
 
100
100
  @uc_file.uuid
101
101
  # => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
102
102
 
103
103
  # URL for the file, can be used with your website or app right away
104
- @uc_file.url
105
- # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/"
104
+ @uc_file.original_file_url
105
+ # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/your-file.png"
106
106
  ```
107
107
 
108
- Your might then want to store or delete the uploaded file. Storing files could
109
- be crucial if you aren't using the “Automatic file storing” option for your
110
- Uploadcare project. If not stored manually or automatically, files get deleted
111
- within a 24-hour period.
108
+ The `store` option can have these possible values:
109
+ - `true`: mark the uploaded file as stored.
110
+ - `false`: do not mark the uploaded file as stored and remove it after 24 hours.
111
+ - `"auto"`: defers the choice of storage behavior to the [auto-store setting](https://app.uploadcare.com/projects/-/settings/#storage) for your Uploadcare project. This is the default behavior.
112
+
113
+ Your might then want to store or delete the uploaded file.
112
114
 
113
115
  ```ruby
114
- # that's how you store a file
116
+ # that's how you store a file, if you have uploaded the file using store: false and changed your mind later
115
117
  @uc_file.store
116
118
  # => #<Uploadcare::Api::File ...
117
119
 
@@ -128,16 +130,16 @@ Uploadcare supports multiple ways to upload files:
128
130
  # Smart upload - detects type of passed object and picks appropriate upload method
129
131
  # If you have a large file (more than 100Mb / 10485760 bytes), the uploader will automatically process it with a multipart upload
130
132
 
131
- Uploadcare::Uploader.upload("https://placekitten.com/96/139")
133
+ Uploadcare::Uploader.upload("https://placekitten.com/96/139", store: "auto")
132
134
  ```
133
135
 
134
136
  There are explicit ways to select upload type:
135
137
 
136
138
  ```ruby
137
- files = [File.open("1.jpg"), File.open("1.jpg"]
138
- Uploadcare::Uploader.upload_files(files)
139
+ files = [File.open("1.jpg"), File.open("1.jpg")]
140
+ Uploadcare::Uploader.upload_files(files, store: 'auto')
139
141
 
140
- Uploadcare::Uploader.upload_from_url("https://placekitten.com/96/139")
142
+ Uploadcare::Uploader.upload_from_url("https://placekitten.com/96/139", store: "auto")
141
143
  ```
142
144
  It is possible to track progress of the upload-from-URL process. To do that, you should specify the `async` option and get a token:
143
145
 
@@ -188,11 +190,12 @@ Options available in a block:
188
190
 
189
191
  #### Uploading options
190
192
 
191
- You can override global [`:autostore`](#initialization) option for each upload request:
193
+ You can override [auto-store setting](https://app.uploadcare.com/projects/-/settings/#storage) from your Uploadcare project for each upload request:
192
194
 
193
195
  ```ruby
194
- @api.upload(files, store: true)
195
- @api.upload_from_url(url, store: :auto)
196
+ @api.upload(files, store: true) # mark the uploaded file as stored.
197
+ @api.upload(files, store: false) # do not mark the uploaded file as stored and remove it after 24 hours.
198
+ @api.upload_from_url(url, store: "auto") # defers the choice of storage behavior to the auto-store setting.
196
199
  ```
197
200
 
198
201
  You can upload file with custom metadata, for example `subsystem` and `pet`:
@@ -208,10 +211,10 @@ Entities are representations of objects in Uploadcare cloud.
208
211
 
209
212
  #### File
210
213
 
211
- File entity contains its metadata.
214
+ File entity contains its metadata. It also supports `include` param to include additional fields to the file object, such as: "appdata".
212
215
 
213
216
  ```ruby
214
- @file = Uploadcare::File.file("FILE_ID_IN_YOUR_PROJECT")
217
+ @file = Uploadcare::File.file("FILE_UUID", include: "appdata")
215
218
  {
216
219
  "datetime_removed"=>nil,
217
220
  "datetime_stored"=>"2018-11-26T12:49:10.477888Z",
@@ -219,11 +222,11 @@ File entity contains its metadata.
219
222
  "is_image"=>true,
220
223
  "is_ready"=>true,
221
224
  "mime_type"=>"image/jpeg",
222
- "original_file_url"=>"https://ucarecdn.com/FILE_ID_IN_YOUR_PROJECT/pineapple.jpg",
225
+ "original_file_url"=>"https://ucarecdn.com/FILE_UUID/pineapple.jpg",
223
226
  "original_filename"=>"pineapple.jpg",
224
227
  "size"=>642,
225
- "url"=>"https://api.uploadcare.com/files/FILE_ID_IN_YOUR_PROJECT/",
226
- "uuid"=>"FILE_ID_IN_YOUR_PROJECT",
228
+ "url"=>"https://api.uploadcare.com/files/FILE_UUID/",
229
+ "uuid"=>"FILE_UUID",
227
230
  "variations"=>nil,
228
231
  "content_info"=>{
229
232
  "mime"=>{
@@ -322,7 +325,7 @@ File entity contains its metadata.
322
325
  The File object is also can be converted if it is a document or a video file. Imagine, you have a document file:
323
326
 
324
327
  ```ruby
325
- @file = Uploadcare::File.file("FILE_ID_IN_YOUR_PROJECT")
328
+ @file = Uploadcare::File.file("FILE_UUID")
326
329
  ```
327
330
 
328
331
  To convert it to an another file, just do:
@@ -437,16 +440,16 @@ As an example, you could store unique file identifier from your system.
437
440
 
438
441
  ```ruby
439
442
  # Get file's metadata keys and values.
440
- Uploadcare::FileMetadata.index('FILE_ID_IN_YOUR_PROJECT')
443
+ Uploadcare::FileMetadata.index('FILE_UUID')
441
444
 
442
445
  # Get the value of a single metadata key.
443
- Uploadcare::FileMetadata.show('FILE_ID_IN_YOUR_PROJECT', 'KEY')
446
+ Uploadcare::FileMetadata.show('FILE_UUID', 'KEY')
444
447
 
445
448
  # Update the value of a single metadata key. If the key does not exist, it will be created.
446
- Uploadcare::FileMetadata.update('FILE_ID_IN_YOUR_PROJECT', 'KEY', 'VALUE')
449
+ Uploadcare::FileMetadata.update('FILE_UUID', 'KEY', 'VALUE')
447
450
 
448
451
  # Delete a file's metadata key.
449
- Uploadcare::FileMetadata.delete('FILE_ID_IN_YOUR_PROJECT', 'KEY')
452
+ Uploadcare::FileMetadata.delete('FILE_UUID', 'KEY')
450
453
  ```
451
454
 
452
455
  #### Group
@@ -470,6 +473,7 @@ Uploadcare::Group.rest_info(group.id)
470
473
 
471
474
  # group can be deleted by group ID.
472
475
  Uploadcare::Group.delete(group.id)
476
+ # Note: This operation only removes the group object itself. All the files that were part of the group are left as is.
473
477
  ```
474
478
 
475
479
  #### GroupList
@@ -552,37 +556,50 @@ An `Add-On` is an application implemented by Uploadcare that accepts uploaded fi
552
556
  ##### AWS Rekognition
553
557
 
554
558
  ```ruby
555
- # Execute AWS Rekognition Add-On for a given target to detect labels in an image. Note: Detected labels are stored in the file's appdata.
556
- Uploadcare::Addons.ws_rekognition_detect_labels('FILE_ID_IN_YOUR_PROJECT')
559
+ # Execute AWS Rekognition Add-On for a given target to detect labels in an image.
560
+ # Note: Detected labels are stored in the file's appdata.
561
+ Uploadcare::Addons.ws_rekognition_detect_labels('FILE_UUID')
557
562
 
558
563
  # Check the status of AWS Rekognition.
559
564
  Uploadcare::Addons.ws_rekognition_detect_labels_status('RETURNED_ID_FROM_WS_REKOGNITION_DETECT_LABELS')
560
565
  ```
561
566
 
567
+ ##### AWS Rekognition Moderation
568
+
569
+ ```ruby
570
+ # Execute AWS Rekognition Moderation Add-On for a given target to detect moderation labels in an image.
571
+ # Note: Detected moderation labels are stored in the file's appdata.
572
+
573
+ Uploadcare::Addons.ws_rekognition_detect_moderation_labels('FILE_UUID')
574
+
575
+ # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
576
+ Uploadcare::Addons.ws_rekognition_detect_moderation_labels_status('RETURNED_ID_FROM_WS_REKOGNITION_DETECT_MODERATION_LABELS')
577
+ ```
578
+
562
579
  ##### ClamAV
563
580
 
564
581
  ```ruby
565
582
  # ClamAV virus checking Add-On for a given target.
566
- Uploadcare::Addons.uc_clamav_virus_scan('FILE_ID_IN_YOUR_PROJECT')
583
+ Uploadcare::Addons.uc_clamav_virus_scan('FILE_UUID')
567
584
 
568
- # Checking and purge infected file.
569
- Uploadcare::Addons.uc_clamav_virus_scan('FILE_ID_IN_YOUR_PROJECT', purge_infected: true )
585
+ # Check and purge infected file.
586
+ Uploadcare::Addons.uc_clamav_virus_scan('FILE_UUID', purge_infected: true )
570
587
 
571
- # Check the status ClamAV virus scan.
588
+ # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
572
589
  Uploadcare::Addons.uc_clamav_virus_scan_status('RETURNED_ID_FROM_UC_CLAMAV_VIRUS_SCAN')
573
590
  ```
574
591
 
575
592
  ##### Remove.bg
576
593
 
577
594
  ```ruby
578
- # Remove background image removal Add-On for a given target.
579
- Uploadcare::Addons.remove_bg('FILE_ID_IN_YOUR_PROJECT')
595
+ # Execute remove.bg background image removal Add-On for a given target.
596
+ Uploadcare::Addons.remove_bg('FILE_UUID')
580
597
 
581
598
  # You can pass optional parameters.
582
599
  # See the full list of parameters here: https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/removeBgExecute
583
- Uploadcare::Addons.remove_bg('FILE_ID_IN_YOUR_PROJECT', crop: true, type_level: '2')
600
+ Uploadcare::Addons.remove_bg('FILE_UUID', crop: true, type_level: '2')
584
601
 
585
- # Check the status of background image removal.
602
+ # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
586
603
  Uploadcare::Addons.remove_bg_status('RETURNED_ID_FROM_REMOVE_BG')
587
604
  ```
588
605
 
@@ -821,15 +838,29 @@ More examples and options can be found [here](https://uploadcare.com/docs/transf
821
838
 
822
839
  You can use custom domain and CDN provider to deliver files with authenticated URLs (see [original documentation](https://uploadcare.com/docs/security/secure_delivery/)).
823
840
 
824
- To generate authenticated URL from the library, you should choose `Uploadcare::SignedUrlGenerators::AmakaiGenerator` (or create your generator implementation):
841
+ To generate authenticated URL from the library, you should choose `Uploadcare::SignedUrlGenerators::AkamaiGenerator` (or create your own generator implementation):
842
+
825
843
  ```ruby
826
- generator = Uploadcare::SignedUrlGenerators::AmakaiGenerator.new(cdn_host: 'example.com', secret_key: 'secret_key'). Optional parameters: ttl: 300, algorithm: 'sha256'
844
+ generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(cdn_host: 'example.com', secret_key: 'secret_key')
845
+ # Optional parameters: ttl: 300, algorithm: 'sha256'
827
846
  generator.generate_url(uuid, acl = optional)
828
847
 
829
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3") ->
830
- https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/~hmac=a989cae5342f17013677f5a0e6577fc5594cc4e238fb4c95eda36634eb47018b
831
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", '/*/') ->
832
- https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/*/~hmac=3ce1152c6af8864b36d4dc721f08ca3cf0b3a20278d7f849e82c6c930d48ccc1
848
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
849
+ # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/~hmac=a989cae5342f17013677f5a0e6577fc5594cc4e238fb4c95eda36634eb47018b
850
+
851
+ # You can pass in ACL as a second parameter to generate_url. See https://uploadcare.com/docs/security/secure-delivery/#authenticated-urls for supported acl formats
852
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", '/*/')
853
+ # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/*/~hmac=3ce1152c6af8864b36d4dc721f08ca3cf0b3a20278d7f849e82c6c930d48ccc1
854
+
855
+ # Optionally you can use wildcard: true to generate a wildcard acl token
856
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", wildcard: true)
857
+ # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1714233449~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/*~hmac=a568ee2a85dd90a8a8a1ef35ea0cc0ef0acb84fe81990edd3a06eacf10a52b4e
858
+
859
+ # You can also pass in a custom ttl and algorithm to AkamaiGenerator
860
+ generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(cdn_host: 'example.com', secret_key: 'secret_key', ttl: 10)
861
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
862
+ # This generates a URL that expires in 10 seconds
863
+ # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1714233277~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/~hmac=f25343104aeced3004d2cc4d49807d8d7c732300b54b154c319da5283a871a71
833
864
  ```
834
865
  ## Useful links
835
866
 
@@ -46,6 +46,19 @@ module Uploadcare
46
46
  get(uri: "/addons/remove_bg/execute/status/#{query_params(uuid)}")
47
47
  end
48
48
 
49
+ # Execute AWS Rekognition Moderation Add-On for a given target to detect labels in an image.
50
+ # @see https://uploadcare.com/api-refs/rest-api/v0.7.0/#tag/Add-Ons/operation/awsRekognitionDetectModerationLabelsExecute
51
+ def ws_rekognition_detect_moderation_labels(uuid)
52
+ content = { target: uuid }.to_json
53
+ post(uri: '/addons/aws_rekognition_detect_moderation_labels/execute/', content: content)
54
+ end
55
+
56
+ # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
57
+ # @see https://uploadcare.com/api-refs/rest-api/v0.7.0/#tag/Add-Ons/operation/awsRekognitionDetectModerationLabelsExecutionStatus
58
+ def ws_rekognition_detect_moderation_labels_status(uuid)
59
+ get(uri: "/addons/aws_rekognition_detect_moderation_labels/execute/status/#{query_params(uuid)}")
60
+ end
61
+
49
62
  private
50
63
 
51
64
  def query_params(uuid)
@@ -37,9 +37,9 @@ module Uploadcare
37
37
 
38
38
  parsed_body = JSON.parse(response_body, symbolize_names: true)
39
39
  errors = parsed_body[:error] || parsed_body[:problems]
40
- return Dry::Monads::Failure(errors) unless errors.nil? || errors.empty?
40
+ return Dry::Monads::Result::Failure.call(errors) unless errors.nil? || errors.empty?
41
41
 
42
- Dry::Monads::Success(parsed_body)
42
+ Dry::Monads::Result::Success.call(parsed_body)
43
43
  end
44
44
 
45
45
  # Prepares body for convert_many method
@@ -16,8 +16,8 @@ module Uploadcare
16
16
 
17
17
  # Acquire file info
18
18
  # @see https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/fileInfo
19
- def info(uuid)
20
- get(uri: "/files/#{uuid}/")
19
+ def info(uuid, params = {})
20
+ get(uri: "/files/#{uuid}/", params: params)
21
21
  end
22
22
  alias file info
23
23
 
@@ -27,8 +27,11 @@ module Uploadcare
27
27
  request_headers = Param::AuthenticationHeader.call(method: method.upcase, uri: uri,
28
28
  content_type: headers[:'Content-Type'], **options)
29
29
  handle_throttling do
30
- send("api_struct_#{method.downcase}", path: remove_trailing_slash(uri),
31
- headers: request_headers, body: options[:content])
30
+ send("api_struct_#{method.downcase}",
31
+ path: remove_trailing_slash(uri),
32
+ headers: request_headers,
33
+ body: options[:content],
34
+ params: options[:params])
32
35
  end
33
36
  end
34
37
 
@@ -17,7 +17,7 @@ module Uploadcare
17
17
  end
18
18
  end
19
19
 
20
- Dry::Monads::Success(nil)
20
+ Dry::Monads::Result::Success.call(nil)
21
21
  end
22
22
 
23
23
  # Get a file group by its ID.
@@ -3,6 +3,7 @@
3
3
  require_relative 'upload_client'
4
4
  require 'retries'
5
5
  require 'param/upload/upload_params_generator'
6
+ require 'param/upload/signature_generator'
6
7
 
7
8
  module Uploadcare
8
9
  module Client
@@ -42,7 +43,7 @@ module Uploadcare
42
43
  uploaded_response = poll_upload_response(token_response.success[:token])
43
44
  return uploaded_response if uploaded_response.success[:status] == 'error'
44
45
 
45
- Dry::Monads::Success(files: [uploaded_response.success])
46
+ Dry::Monads::Result::Success.call(files: [uploaded_response.success])
46
47
  end
47
48
 
48
49
  # Check upload status
@@ -75,12 +76,22 @@ module Uploadcare
75
76
  def poll_upload_response(token)
76
77
  with_retries(max_tries: Uploadcare.config.max_request_tries,
77
78
  base_sleep_seconds: Uploadcare.config.base_request_sleep,
78
- max_sleep_seconds: Uploadcare.config.max_request_sleep) do
79
+ max_sleep_seconds: Uploadcare.config.max_request_sleep,
80
+ rescue: RetryError) do
79
81
  response = get_upload_from_url_status(token)
80
- raise RequestError if %w[progress waiting unknown].include?(response.success[:status])
82
+ handle_polling_response(response)
83
+ end
84
+ end
81
85
 
82
- response
86
+ def handle_polling_response(response)
87
+ case response.success[:status]
88
+ when 'error'
89
+ raise RequestError, response.success[:error]
90
+ when 'progress', 'waiting', 'unknown'
91
+ raise RetryError, response.success[:error] || 'Upload is taking longer than expected. Try increasing the max_request_tries config if you know your file uploads will take more time.' # rubocop:disable Layout/LineLength
83
92
  end
93
+
94
+ response
84
95
  end
85
96
 
86
97
  # Prepares body for upload_many method
@@ -96,13 +107,13 @@ module Uploadcare
96
107
 
97
108
  # Prepare upload_from_url initial request body
98
109
  def upload_from_url_body(url, options = {})
99
- HTTP::FormData::Multipart.new(
100
- options.merge(
101
- 'pub_key' => Uploadcare.config.public_key,
102
- 'source_url' => url,
103
- 'store' => store_value(options[:store])
104
- )
105
- )
110
+ opts = {
111
+ 'pub_key' => Uploadcare.config.public_key,
112
+ 'source_url' => url,
113
+ 'store' => store_value(options[:store])
114
+ }
115
+ opts.merge!(Param::Upload::SignatureGenerator.call) if Uploadcare.config.sign_uploads
116
+ HTTP::FormData::Multipart.new(options.merge(opts))
106
117
  end
107
118
 
108
119
  def store_value(store)
@@ -9,7 +9,7 @@ module Uploadcare
9
9
  class << self
10
10
  # Converts files
11
11
  #
12
- # @param doc_params [Array] of hashes with params or [Hash]
12
+ # @param params [Array] of hashes with params or [Hash]
13
13
  # @option options [Boolean] :store whether to store file on servers.
14
14
  def convert(params, options = {})
15
15
  files_params = params.is_a?(Hash) ? [params] : params
@@ -15,6 +15,11 @@ module Uploadcare
15
15
 
16
16
  attr_entity(*RESPONSE_PARAMS)
17
17
 
18
+ def datetime_stored
19
+ Uploadcare.config.logger&.warn 'datetime_stored property has been deprecated, and will be removed without a replacement in future.' # rubocop:disable Layout/LineLength
20
+ @entity.datetime_stored
21
+ end
22
+
18
23
  # gets file's uuid - even if it's only initialized with url
19
24
  # @returns [String]
20
25
  def uuid
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Exception
5
+ # Invalid Auth configuration error
6
+ class AuthError < StandardError; end
7
+ end
8
+ end
@@ -3,7 +3,6 @@
3
3
  module Uploadcare
4
4
  module Exception
5
5
  # Standard error for invalid API responses
6
- class RequestError < StandardError
7
- end
6
+ class RequestError < StandardError; end
8
7
  end
9
8
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uploadcare
4
+ module Exception
5
+ # Standard error to raise when needing to retry a request
6
+ class RetryError < StandardError; end
7
+ end
8
+ end
@@ -11,6 +11,7 @@ module Uploadcare
11
11
  class AuthenticationHeader
12
12
  # @see https://uploadcare.com/docs/api_reference/rest/requests_auth/#auth-uploadcare
13
13
  def self.call(options = {})
14
+ validate_auth_config
14
15
  case Uploadcare.config.auth_type
15
16
  when 'Uploadcare'
16
17
  SecureAuthHeader.call(options)
@@ -20,6 +21,17 @@ module Uploadcare
20
21
  raise ArgumentError, "Unknown auth_scheme: '#{Uploadcare.config.auth_type}'"
21
22
  end
22
23
  end
24
+
25
+ def self.validate_auth_config
26
+ raise AuthError, 'Public Key is blank.' if is_blank?(Uploadcare.config.public_key)
27
+ raise AuthError, 'Secret Key is blank.' if is_blank?(Uploadcare.config.secret_key)
28
+ end
29
+
30
+ # rubocop:disable Naming/PredicateName
31
+ def self.is_blank?(value)
32
+ value.nil? || value.empty?
33
+ end
34
+ # rubocop:enable Naming/PredicateName
23
35
  end
24
36
  end
25
37
  end
@@ -1,26 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'digest/md5'
4
+ require 'addressable/uri'
4
5
 
5
6
  module Uploadcare
6
7
  module Param
7
8
  # This object returns headers needed for authentication
8
9
  # This authentication method is more secure, but more tedious
9
10
  class SecureAuthHeader
10
- # @see https://uploadcare.com/docs/api_reference/rest/requests_auth/#auth-uploadcare
11
- def self.call(options = {})
12
- @method = options[:method]
13
- @body = options[:content] || ''
14
- @content_type = options[:content_type]
15
- @uri = options[:uri]
16
- @date_for_header = timestamp
17
- {
18
- Date: @date_for_header,
19
- Authorization: "Uploadcare #{Uploadcare.config.public_key}:#{signature}"
20
- }
21
- end
22
-
23
11
  class << self
12
+ # @see https://uploadcare.com/docs/api_reference/rest/requests_auth/#auth-uploadcare
13
+ def call(options = {})
14
+ @method = options[:method]
15
+ @body = options[:content] || ''
16
+ @content_type = options[:content_type]
17
+ @uri = make_uri(options)
18
+
19
+ @date_for_header = timestamp
20
+ {
21
+ Date: @date_for_header,
22
+ Authorization: "Uploadcare #{Uploadcare.config.public_key}:#{signature}"
23
+ }
24
+ end
25
+
24
26
  def signature
25
27
  content_md5 = Digest::MD5.hexdigest(@body)
26
28
  sign_string = [@method, content_md5, @content_type, @date_for_header, @uri].join("\n")
@@ -31,6 +33,18 @@ module Uploadcare
31
33
  def timestamp
32
34
  Time.now.gmtime.strftime('%a, %d %b %Y %H:%M:%S GMT')
33
35
  end
36
+
37
+ private
38
+
39
+ def make_uri(options)
40
+ if options[:params] && !options[:params].empty?
41
+ uri = Addressable::URI.parse options[:uri]
42
+ uri.query_values = uri.query_values(Array).to_a.concat(options[:params].to_a)
43
+ uri.to_s
44
+ else
45
+ options[:uri]
46
+ end
47
+ end
34
48
  end
35
49
  end
36
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uploadcare
4
- VERSION = '4.3.6'
4
+ VERSION = '4.4.1'
5
5
  end
@@ -4,20 +4,21 @@ require_relative 'base_generator'
4
4
 
5
5
  module Uploadcare
6
6
  module SignedUrlGenerators
7
- class AmakaiGenerator < Uploadcare::SignedUrlGenerators::BaseGenerator
7
+ class AkamaiGenerator < Uploadcare::SignedUrlGenerators::BaseGenerator
8
8
  UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}'
9
9
  TEMPLATE = 'https://{cdn_host}/{uuid}/?token=exp={expiration}{delimiter}acl={acl}{delimiter}hmac={token}'
10
10
 
11
- def generate_url(uuid, acl = uuid)
11
+ def generate_url(uuid, acl = uuid, wildcard: false)
12
12
  raise ArgumentError, 'Must contain valid UUID' unless valid?(uuid)
13
13
 
14
+ formatted_acl = build_acl(uuid, acl, wildcard: wildcard)
14
15
  expire = build_expire
15
- signature = build_signature(expire, acl)
16
+ signature = build_signature(expire, formatted_acl)
16
17
 
17
18
  TEMPLATE.gsub('{delimiter}', delimiter)
18
19
  .sub('{cdn_host}', sanitized_string(cdn_host))
19
20
  .sub('{uuid}', sanitized_string(uuid))
20
- .sub('{acl}', "/#{sanitized_string(acl)}/")
21
+ .sub('{acl}', formatted_acl)
21
22
  .sub('{expiration}', expire)
22
23
  .sub('{token}', signature)
23
24
  end
@@ -32,13 +33,22 @@ module Uploadcare
32
33
  '~'
33
34
  end
34
35
 
36
+ def build_acl(uuid, acl, wildcard: false)
37
+ if wildcard
38
+ "/#{sanitized_string(uuid)}/*"
39
+ else
40
+ "/#{sanitized_string(acl)}/"
41
+ end
42
+ end
43
+
35
44
  def build_expire
36
45
  (Time.now.to_i + ttl).to_s
37
46
  end
38
47
 
39
48
  def build_signature(expire, acl)
40
- signature = ["exp=#{expire}", "acl=/#{sanitized_string(acl)}/"].join(delimiter)
41
- OpenSSL::HMAC.hexdigest(algorithm, secret_key, signature)
49
+ signature = ["exp=#{expire}", "acl=#{acl}"].join(delimiter)
50
+ secret_key_bin = Array(secret_key.gsub(/\s/, '')).pack('H*')
51
+ OpenSSL::HMAC.hexdigest(algorithm, secret_key_bin, signature)
42
52
  end
43
53
 
44
54
  # rubocop:disable Style/SlicingWithRange
data/lib/uploadcare.rb CHANGED
@@ -6,6 +6,8 @@ require 'ruby/version'
6
6
  # Exceptions
7
7
  require 'exception/throttle_error'
8
8
  require 'exception/request_error'
9
+ require 'exception/retry_error'
10
+ require 'exception/auth_error'
9
11
 
10
12
  # Entities
11
13
  require 'entity/entity'
@@ -24,7 +26,7 @@ require 'param/webhook_signature_verifier'
24
26
  require 'api/api'
25
27
 
26
28
  # SignedUrlGenerators
27
- require 'signed_url_generators/amakai_generator'
29
+ require 'signed_url_generators/akamai_generator'
28
30
  require 'signed_url_generators/base_generator'
29
31
 
30
32
  # Ruby wrapper for Uploadcare API
@@ -33,18 +35,6 @@ require 'signed_url_generators/base_generator'
33
35
  module Uploadcare
34
36
  extend Dry::Configurable
35
37
 
36
- # NOTE: The dry-configurable gem has introduced the `default` keyword argument
37
- # and deprecated the positional default argument in v0.13.0, which requires
38
- # Ruby >= 2.6.0. In order to provide backwards compatibility and not disable
39
- # deprecation warnings, we override the dry-configurable's `setting` DSL method.
40
- def self.setting(name, default:, **options, &block)
41
- if RUBY_VERSION < '2.6'
42
- super name, default, &block
43
- else
44
- super
45
- end
46
- end
47
-
48
38
  setting :public_key, default: ENV.fetch('UPLOADCARE_PUBLIC_KEY', '')
49
39
  setting :secret_key, default: ENV.fetch('UPLOADCARE_SECRET_KEY', '')
50
40
  setting :auth_type, default: 'Uploadcare'
@@ -60,4 +50,5 @@ module Uploadcare
60
50
  setting :upload_threads, default: 2 # used for multiupload only ATM
61
51
  setting :framework_data, default: ''
62
52
  setting :file_chunk_size, default: 100
53
+ setting :logger, default: Logger.new($stdout)
63
54
  end
@@ -43,6 +43,8 @@ Gem::Specification.new do |spec|
43
43
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
44
44
  spec.require_paths = ['lib', 'lib/uploadcare', 'lib/uploadcare/rest']
45
45
 
46
+ spec.required_ruby_version = '>= 3.0'
47
+
46
48
  spec.add_dependency 'mimemagic', '~> 0.4'
47
49
  spec.add_dependency 'parallel', '~> 1.22'
48
50
  spec.add_dependency 'retries', '~> 0.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uploadcare-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.6
4
+ version: 4.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@dmitrijivanchenko (Dmitrij Ivanchenko), @T0mbery (Andrey Aksenov)"
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-11-18 00:00:00.000000000 Z
12
+ date: 2024-04-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mimemagic
@@ -130,8 +130,10 @@ files:
130
130
  - lib/uploadcare/entity/project.rb
131
131
  - lib/uploadcare/entity/uploader.rb
132
132
  - lib/uploadcare/entity/webhook.rb
133
+ - lib/uploadcare/exception/auth_error.rb
133
134
  - lib/uploadcare/exception/conversion_error.rb
134
135
  - lib/uploadcare/exception/request_error.rb
136
+ - lib/uploadcare/exception/retry_error.rb
135
137
  - lib/uploadcare/exception/throttle_error.rb
136
138
  - lib/uploadcare/param/authentication_header.rb
137
139
  - lib/uploadcare/param/conversion/document/processing_job_url_builder.rb
@@ -144,7 +146,7 @@ files:
144
146
  - lib/uploadcare/param/user_agent.rb
145
147
  - lib/uploadcare/param/webhook_signature_verifier.rb
146
148
  - lib/uploadcare/ruby/version.rb
147
- - lib/uploadcare/signed_url_generators/amakai_generator.rb
149
+ - lib/uploadcare/signed_url_generators/akamai_generator.rb
148
150
  - lib/uploadcare/signed_url_generators/base_generator.rb
149
151
  - uploadcare-ruby.gemspec
150
152
  homepage: https://uploadcare.com/
@@ -168,14 +170,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
170
  requirements:
169
171
  - - ">="
170
172
  - !ruby/object:Gem::Version
171
- version: '0'
173
+ version: '3.0'
172
174
  required_rubygems_version: !ruby/object:Gem::Requirement
173
175
  requirements:
174
176
  - - ">="
175
177
  - !ruby/object:Gem::Version
176
178
  version: '0'
177
179
  requirements: []
178
- rubygems_version: 3.4.10
180
+ rubygems_version: 3.5.9
179
181
  signing_key:
180
182
  specification_version: 4
181
183
  summary: Ruby wrapper for uploadcare API