activestorage 6.1.3.2 → 7.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activestorage might be problematic. Click here for more details.

Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +132 -182
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +25 -11
  5. data/app/assets/javascripts/activestorage.esm.js +844 -0
  6. data/app/assets/javascripts/activestorage.js +257 -376
  7. data/app/controllers/active_storage/base_controller.rb +1 -10
  8. data/app/controllers/active_storage/blobs/proxy_controller.rb +14 -4
  9. data/app/controllers/active_storage/blobs/redirect_controller.rb +6 -4
  10. data/app/controllers/active_storage/representations/base_controller.rb +18 -0
  11. data/app/controllers/active_storage/representations/proxy_controller.rb +7 -11
  12. data/app/controllers/active_storage/representations/redirect_controller.rb +7 -7
  13. data/app/controllers/concerns/active_storage/set_blob.rb +6 -2
  14. data/app/controllers/concerns/active_storage/set_current.rb +3 -3
  15. data/app/controllers/concerns/active_storage/streaming.rb +65 -0
  16. data/app/javascript/activestorage/ujs.js +1 -1
  17. data/app/models/active_storage/attachment.rb +36 -3
  18. data/app/models/active_storage/blob/representable.rb +8 -6
  19. data/app/models/active_storage/blob.rb +27 -28
  20. data/app/models/active_storage/current.rb +12 -2
  21. data/app/models/active_storage/preview.rb +6 -4
  22. data/app/models/active_storage/record.rb +1 -1
  23. data/app/models/active_storage/variant.rb +4 -7
  24. data/app/models/active_storage/variant_record.rb +2 -0
  25. data/app/models/active_storage/variant_with_record.rb +10 -6
  26. data/app/models/active_storage/variation.rb +2 -2
  27. data/config/routes.rb +10 -10
  28. data/db/migrate/20170806125915_create_active_storage_tables.rb +29 -8
  29. data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +15 -2
  30. data/lib/active_storage/analyzer/audio_analyzer.rb +65 -0
  31. data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +39 -0
  32. data/lib/active_storage/analyzer/image_analyzer/vips.rb +49 -0
  33. data/lib/active_storage/analyzer/image_analyzer.rb +2 -30
  34. data/lib/active_storage/analyzer/video_analyzer.rb +26 -11
  35. data/lib/active_storage/analyzer.rb +8 -4
  36. data/lib/active_storage/attached/changes/create_many.rb +7 -3
  37. data/lib/active_storage/attached/changes/create_one.rb +1 -1
  38. data/lib/active_storage/attached/changes/create_one_of_many.rb +1 -1
  39. data/lib/active_storage/attached/changes/delete_many.rb +1 -1
  40. data/lib/active_storage/attached/changes/delete_one.rb +1 -1
  41. data/lib/active_storage/attached/changes/detach_many.rb +18 -0
  42. data/lib/active_storage/attached/changes/detach_one.rb +24 -0
  43. data/lib/active_storage/attached/changes/purge_many.rb +27 -0
  44. data/lib/active_storage/attached/changes/purge_one.rb +27 -0
  45. data/lib/active_storage/attached/changes.rb +7 -1
  46. data/lib/active_storage/attached/many.rb +27 -15
  47. data/lib/active_storage/attached/model.rb +31 -5
  48. data/lib/active_storage/attached/one.rb +32 -27
  49. data/lib/active_storage/downloader.rb +2 -2
  50. data/lib/active_storage/engine.rb +29 -1
  51. data/lib/active_storage/errors.rb +3 -0
  52. data/lib/active_storage/fixture_set.rb +76 -0
  53. data/lib/active_storage/gem_version.rb +4 -4
  54. data/lib/active_storage/previewer/video_previewer.rb +1 -1
  55. data/lib/active_storage/previewer.rb +14 -5
  56. data/lib/active_storage/reflection.rb +12 -2
  57. data/lib/active_storage/service/azure_storage_service.rb +1 -1
  58. data/lib/active_storage/service/configurator.rb +1 -1
  59. data/lib/active_storage/service/disk_service.rb +13 -18
  60. data/lib/active_storage/service/gcs_service.rb +91 -7
  61. data/lib/active_storage/service/mirror_service.rb +1 -1
  62. data/lib/active_storage/service/registry.rb +1 -1
  63. data/lib/active_storage/service/s3_service.rb +4 -4
  64. data/lib/active_storage/service.rb +3 -3
  65. data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
  66. data/lib/active_storage/transformers/transformer.rb +1 -1
  67. data/lib/active_storage.rb +5 -1
  68. data/lib/tasks/activestorage.rake +5 -1
  69. metadata +35 -25
  70. data/app/controllers/concerns/active_storage/set_headers.rb +0 -12
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  gem "google-cloud-storage", "~> 1.11"
4
+ require "google/apis/iamcredentials_v1"
4
5
  require "google/cloud/storage"
5
6
 
6
7
  module ActiveStorage
7
8
  # Wraps the Google Cloud Storage as an Active Storage service. See ActiveStorage::Service for the generic API
8
9
  # documentation that applies to all services.
9
10
  class Service::GCSService < Service
11
+ class MetadataServerError < ActiveStorage::Error; end
12
+ class MetadataServerNotFoundError < ActiveStorage::Error; end
13
+
10
14
  def initialize(public: false, **config)
11
15
  @config = config
12
16
  @public = public
@@ -19,7 +23,7 @@ module ActiveStorage
19
23
  # binary and attachment when the file's content type requires it. The only way to force them is to
20
24
  # store them as object's metadata.
21
25
  content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
22
- bucket.create_file(io, key, md5: checksum, content_type: content_type, content_disposition: content_disposition)
26
+ bucket.create_file(io, key, md5: checksum, cache_control: @config[:cache_control], content_type: content_type, content_disposition: content_disposition)
23
27
  rescue Google::Cloud::InvalidArgumentError
24
28
  raise ActiveStorage::IntegrityError
25
29
  end
@@ -84,7 +88,31 @@ module ActiveStorage
84
88
 
85
89
  def url_for_direct_upload(key, expires_in:, checksum:, **)
86
90
  instrument :url, key: key do |payload|
87
- generated_url = bucket.signed_url key, method: "PUT", expires: expires_in, content_md5: checksum
91
+ headers = {}
92
+ version = :v2
93
+
94
+ if @config[:cache_control].present?
95
+ headers["Cache-Control"] = @config[:cache_control]
96
+ # v2 signing doesn't support non `x-goog-` headers. Only switch to v4 signing
97
+ # if necessary for back-compat; v4 limits the expiration of the URL to 7 days
98
+ # whereas v2 has no limit
99
+ version = :v4
100
+ end
101
+
102
+ args = {
103
+ content_md5: checksum,
104
+ expires: expires_in,
105
+ headers: headers,
106
+ method: "PUT",
107
+ version: version,
108
+ }
109
+
110
+ if @config[:iam]
111
+ args[:issuer] = issuer
112
+ args[:signer] = signer
113
+ end
114
+
115
+ generated_url = bucket.signed_url(key, **args)
88
116
 
89
117
  payload[:url] = generated_url
90
118
 
@@ -95,15 +123,31 @@ module ActiveStorage
95
123
  def headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, **)
96
124
  content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
97
125
 
98
- { "Content-MD5" => checksum, "Content-Disposition" => content_disposition }
126
+ headers = { "Content-MD5" => checksum, "Content-Disposition" => content_disposition }
127
+
128
+ if @config[:cache_control].present?
129
+ headers["Cache-Control"] = @config[:cache_control]
130
+ end
131
+
132
+ headers
99
133
  end
100
134
 
101
135
  private
102
136
  def private_url(key, expires_in:, filename:, content_type:, disposition:, **)
103
- file_for(key).signed_url expires: expires_in, query: {
104
- "response-content-disposition" => content_disposition_with(type: disposition, filename: filename),
105
- "response-content-type" => content_type
137
+ args = {
138
+ expires: expires_in,
139
+ query: {
140
+ "response-content-disposition" => content_disposition_with(type: disposition, filename: filename),
141
+ "response-content-type" => content_type
142
+ }
106
143
  }
144
+
145
+ if @config[:iam]
146
+ args[:issuer] = issuer
147
+ args[:signer] = signer
148
+ end
149
+
150
+ file_for(key).signed_url(**args)
107
151
  end
108
152
 
109
153
  def public_url(key, **)
@@ -137,7 +181,47 @@ module ActiveStorage
137
181
  end
138
182
 
139
183
  def client
140
- @client ||= Google::Cloud::Storage.new(**config.except(:bucket))
184
+ @client ||= Google::Cloud::Storage.new(**config.except(:bucket, :cache_control, :iam, :gsa_email))
185
+ end
186
+
187
+ def issuer
188
+ @issuer ||= if @config[:gsa_email]
189
+ @config[:gsa_email]
190
+ else
191
+ uri = URI.parse("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email")
192
+ http = Net::HTTP.new(uri.host, uri.port)
193
+ request = Net::HTTP::Get.new(uri.request_uri)
194
+ request["Metadata-Flavor"] = "Google"
195
+
196
+ begin
197
+ response = http.request(request)
198
+ rescue SocketError
199
+ raise MetadataServerNotFoundError
200
+ end
201
+
202
+ if response.is_a?(Net::HTTPSuccess)
203
+ response.body
204
+ else
205
+ raise MetadataServerError
206
+ end
207
+ end
208
+ end
209
+
210
+ def signer
211
+ # https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage/Project.html#signed_url-instance_method
212
+ lambda do |string_to_sign|
213
+ iam_client = Google::Apis::IamcredentialsV1::IAMCredentialsService.new
214
+
215
+ scopes = ["https://www.googleapis.com/auth/iam"]
216
+ iam_client.authorization = Google::Auth.get_application_default(scopes)
217
+
218
+ request = Google::Apis::IamcredentialsV1::SignBlobRequest.new(
219
+ payload: string_to_sign
220
+ )
221
+ resource = "projects/-/serviceAccounts/#{issuer}"
222
+ response = iam_client.sign_service_account_blob(resource, request)
223
+ response.signed_blob
224
+ end
141
225
  end
142
226
  end
143
227
  end
@@ -17,7 +17,7 @@ module ActiveStorage
17
17
  :url_for_direct_upload, :headers_for_direct_upload, :path_for, to: :primary
18
18
 
19
19
  # Stitch together from named services.
20
- def self.build(primary:, mirrors:, name:, configurator:, **options) #:nodoc:
20
+ def self.build(primary:, mirrors:, name:, configurator:, **options) # :nodoc:
21
21
  new(
22
22
  primary: configurator.build(primary),
23
23
  mirrors: mirrors.collect { |mirror_name| configurator.build mirror_name }
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorage
4
- class Service::Registry #:nodoc:
4
+ class Service::Registry # :nodoc:
5
5
  def initialize(configurations)
6
6
  @configurations = configurations.deep_symbolize_keys
7
7
  @services = {}
@@ -96,14 +96,14 @@ module ActiveStorage
96
96
  end
97
97
 
98
98
  private
99
- def private_url(key, expires_in:, filename:, disposition:, content_type:, **)
99
+ def private_url(key, expires_in:, filename:, disposition:, content_type:, **client_opts)
100
100
  object_for(key).presigned_url :get, expires_in: expires_in.to_i,
101
101
  response_content_disposition: content_disposition_with(type: disposition, filename: filename),
102
- response_content_type: content_type
102
+ response_content_type: content_type, **client_opts
103
103
  end
104
104
 
105
- def public_url(key, **)
106
- object_for(key).public_url
105
+ def public_url(key, **client_opts)
106
+ object_for(key).public_url(**client_opts)
107
107
  end
108
108
 
109
109
 
@@ -35,8 +35,8 @@ module ActiveStorage
35
35
  # can configure the service to use like this:
36
36
  #
37
37
  # ActiveStorage::Blob.service = ActiveStorage::Service.configure(
38
- # :Disk,
39
- # root: Pathname("/foo/bar/storage")
38
+ # :local,
39
+ # { local: {service: "Disk", root: Pathname("/tmp/foo/storage") } }
40
40
  # )
41
41
  class Service
42
42
  extend ActiveSupport::Autoload
@@ -57,7 +57,7 @@ module ActiveStorage
57
57
  # Passes the configurator and all of the service's config as keyword args.
58
58
  #
59
59
  # See MirrorService for an example.
60
- def build(configurator:, name:, service: nil, **service_config) #:nodoc:
60
+ def build(configurator:, name:, service: nil, **service_config) # :nodoc:
61
61
  new(**service_config).tap do |service_instance|
62
62
  service_instance.name = name
63
63
  end
@@ -31,7 +31,7 @@ module ActiveStorage
31
31
  if name.to_s == "combine_options"
32
32
  raise ArgumentError, <<~ERROR.squish
33
33
  Active Storage's ImageProcessing transformer doesn't support :combine_options,
34
- as it always generates a single ImageMagick command.
34
+ as it always generates a single command.
35
35
  ERROR
36
36
  end
37
37
 
@@ -31,7 +31,7 @@ module ActiveStorage
31
31
  private
32
32
  # Returns an open Tempfile containing a transformed image in the given +format+.
33
33
  # All subclasses implement this method.
34
- def process(file, format:) #:doc:
34
+ def process(file, format:) # :doc:
35
35
  raise NotImplementedError
36
36
  end
37
37
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2017-2020 David Heinemeier Hansson, Basecamp
4
+ # Copyright (c) 2017-2021 David Heinemeier Hansson, Basecamp
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -37,6 +37,7 @@ module ActiveStorage
37
37
  extend ActiveSupport::Autoload
38
38
 
39
39
  autoload :Attached
40
+ autoload :FixtureSet
40
41
  autoload :Service
41
42
  autoload :Previewer
42
43
  autoload :Analyzer
@@ -59,6 +60,7 @@ module ActiveStorage
59
60
  mattr_accessor :content_types_allowed_inline, default: []
60
61
 
61
62
  mattr_accessor :service_urls_expire_in, default: 5.minutes
63
+ mattr_accessor :urls_expire_in
62
64
 
63
65
  mattr_accessor :routes_prefix, default: "/rails/active_storage"
64
66
  mattr_accessor :draw_routes, default: true
@@ -67,6 +69,8 @@ module ActiveStorage
67
69
  mattr_accessor :replace_on_assign_to_many, default: false
68
70
  mattr_accessor :track_variants, default: false
69
71
 
72
+ mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
73
+
70
74
  module Transformers
71
75
  extend ActiveSupport::Autoload
72
76
 
@@ -17,6 +17,10 @@ namespace :active_storage do
17
17
  task update: :environment do
18
18
  ENV["MIGRATIONS_PATH"] = "db/update_migrate"
19
19
 
20
- Rake::Task["active_storage:install"].invoke
20
+ if Rake::Task.task_defined?("active_storage:install")
21
+ Rake::Task["active_storage:install"].invoke
22
+ else
23
+ Rake::Task["app:active_storage:install"].invoke
24
+ end
21
25
  end
22
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activestorage
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.3.2
4
+ version: 7.0.0.alpha2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-05 00:00:00.000000000 Z
11
+ date: 2021-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.1.3.2
19
+ version: 7.0.0.alpha2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.1.3.2
26
+ version: 7.0.0.alpha2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 6.1.3.2
33
+ version: 7.0.0.alpha2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 6.1.3.2
40
+ version: 7.0.0.alpha2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activejob
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 6.1.3.2
47
+ version: 7.0.0.alpha2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 6.1.3.2
54
+ version: 7.0.0.alpha2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activerecord
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 6.1.3.2
61
+ version: 7.0.0.alpha2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 6.1.3.2
68
+ version: 7.0.0.alpha2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: marcel
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: mini_mime
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 1.0.2
89
+ version: 1.1.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 1.0.2
96
+ version: 1.1.0
97
97
  description: Attach cloud and local files in Rails applications.
98
98
  email: david@loudthinking.com
99
99
  executables: []
@@ -103,18 +103,20 @@ files:
103
103
  - CHANGELOG.md
104
104
  - MIT-LICENSE
105
105
  - README.md
106
+ - app/assets/javascripts/activestorage.esm.js
106
107
  - app/assets/javascripts/activestorage.js
107
108
  - app/controllers/active_storage/base_controller.rb
108
109
  - app/controllers/active_storage/blobs/proxy_controller.rb
109
110
  - app/controllers/active_storage/blobs/redirect_controller.rb
110
111
  - app/controllers/active_storage/direct_uploads_controller.rb
111
112
  - app/controllers/active_storage/disk_controller.rb
113
+ - app/controllers/active_storage/representations/base_controller.rb
112
114
  - app/controllers/active_storage/representations/proxy_controller.rb
113
115
  - app/controllers/active_storage/representations/redirect_controller.rb
114
116
  - app/controllers/concerns/active_storage/file_server.rb
115
117
  - app/controllers/concerns/active_storage/set_blob.rb
116
118
  - app/controllers/concerns/active_storage/set_current.rb
117
- - app/controllers/concerns/active_storage/set_headers.rb
119
+ - app/controllers/concerns/active_storage/streaming.rb
118
120
  - app/javascript/activestorage/blob_record.js
119
121
  - app/javascript/activestorage/blob_upload.js
120
122
  - app/javascript/activestorage/direct_upload.js
@@ -147,7 +149,10 @@ files:
147
149
  - db/update_migrate/20191206030411_create_active_storage_variant_records.rb
148
150
  - lib/active_storage.rb
149
151
  - lib/active_storage/analyzer.rb
152
+ - lib/active_storage/analyzer/audio_analyzer.rb
150
153
  - lib/active_storage/analyzer/image_analyzer.rb
154
+ - lib/active_storage/analyzer/image_analyzer/image_magick.rb
155
+ - lib/active_storage/analyzer/image_analyzer/vips.rb
151
156
  - lib/active_storage/analyzer/null_analyzer.rb
152
157
  - lib/active_storage/analyzer/video_analyzer.rb
153
158
  - lib/active_storage/attached.rb
@@ -157,12 +162,17 @@ files:
157
162
  - lib/active_storage/attached/changes/create_one_of_many.rb
158
163
  - lib/active_storage/attached/changes/delete_many.rb
159
164
  - lib/active_storage/attached/changes/delete_one.rb
165
+ - lib/active_storage/attached/changes/detach_many.rb
166
+ - lib/active_storage/attached/changes/detach_one.rb
167
+ - lib/active_storage/attached/changes/purge_many.rb
168
+ - lib/active_storage/attached/changes/purge_one.rb
160
169
  - lib/active_storage/attached/many.rb
161
170
  - lib/active_storage/attached/model.rb
162
171
  - lib/active_storage/attached/one.rb
163
172
  - lib/active_storage/downloader.rb
164
173
  - lib/active_storage/engine.rb
165
174
  - lib/active_storage/errors.rb
175
+ - lib/active_storage/fixture_set.rb
166
176
  - lib/active_storage/gem_version.rb
167
177
  - lib/active_storage/log_subscriber.rb
168
178
  - lib/active_storage/previewer.rb
@@ -187,11 +197,11 @@ licenses:
187
197
  - MIT
188
198
  metadata:
189
199
  bug_tracker_uri: https://github.com/rails/rails/issues
190
- changelog_uri: https://github.com/rails/rails/blob/v6.1.3.2/activestorage/CHANGELOG.md
191
- documentation_uri: https://api.rubyonrails.org/v6.1.3.2/
200
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.0.alpha2/activestorage/CHANGELOG.md
201
+ documentation_uri: https://api.rubyonrails.org/v7.0.0.alpha2/
192
202
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
193
- source_code_uri: https://github.com/rails/rails/tree/v6.1.3.2/activestorage
194
- post_install_message:
203
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.0.alpha2/activestorage
204
+ post_install_message:
195
205
  rdoc_options: []
196
206
  require_paths:
197
207
  - lib
@@ -199,15 +209,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
199
209
  requirements:
200
210
  - - ">="
201
211
  - !ruby/object:Gem::Version
202
- version: 2.5.0
212
+ version: 2.7.0
203
213
  required_rubygems_version: !ruby/object:Gem::Requirement
204
214
  requirements:
205
- - - ">="
215
+ - - ">"
206
216
  - !ruby/object:Gem::Version
207
- version: '0'
217
+ version: 1.3.1
208
218
  requirements: []
209
- rubygems_version: 3.1.2
210
- signing_key:
219
+ rubygems_version: 3.1.6
220
+ signing_key:
211
221
  specification_version: 4
212
222
  summary: Local and cloud file storage framework.
213
223
  test_files: []