activestorage 5.2.1 → 5.2.1.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/app/controllers/active_storage/disk_controller.rb +3 -3
- data/app/models/active_storage/blob.rb +27 -3
- data/app/models/active_storage/blob/identifiable.rb +8 -1
- data/lib/active_storage.rb +2 -0
- data/lib/active_storage/engine.rb +14 -0
- data/lib/active_storage/gem_version.rb +1 -1
- data/lib/active_storage/service.rb +7 -1
- data/lib/active_storage/service/azure_storage_service.rb +1 -1
- data/lib/active_storage/service/disk_service.rb +16 -10
- data/lib/active_storage/service/gcs_service.rb +16 -8
- data/lib/active_storage/service/mirror_service.rb +2 -2
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91213c28f24de81bd5f9fb70fc824cebab2a78b4a9a7e7181dab0073241e10df
|
4
|
+
data.tar.gz: be7321827bdee9da52fb288c8625c1d06c13efcea0e7e38115294cc7c87f1629
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 020ebe643211ff9093027c6ec35a0626e565779a0f0d9a27723cb452b1c66cf9c1b10df89aec84cf068ef1d24ddb90ef8b844054eaaa497bc41b59e42a0f0514
|
7
|
+
data.tar.gz: 9c3e51fbe837f60c86eb993d9ba1d85b66362a298fb432629f1dca0b79bdbd500c86fb6640d99d023636d4f8094867367b7cb2bd5d2b6616fe93fa9a8dea6a13
|
data/CHANGELOG.md
CHANGED
@@ -11,10 +11,10 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController
|
|
11
11
|
|
12
12
|
def show
|
13
13
|
if key = decode_verified_key
|
14
|
-
response.headers["Content-Type"] =
|
15
|
-
response.headers["Content-Disposition"] =
|
14
|
+
response.headers["Content-Type"] = key[:content_type] || DEFAULT_SEND_FILE_TYPE
|
15
|
+
response.headers["Content-Disposition"] = key[:disposition] || DEFAULT_SEND_FILE_DISPOSITION
|
16
16
|
|
17
|
-
disk_service.download key do |chunk|
|
17
|
+
disk_service.download key[:key] do |chunk|
|
18
18
|
response.stream.write chunk
|
19
19
|
end
|
20
20
|
else
|
@@ -120,8 +120,8 @@ class ActiveStorage::Blob < ActiveRecord::Base
|
|
120
120
|
def service_url(expires_in: service.url_expires_in, disposition: :inline, filename: nil, **options)
|
121
121
|
filename = ActiveStorage::Filename.wrap(filename || self.filename)
|
122
122
|
|
123
|
-
service.url key, expires_in: expires_in, filename: filename, content_type:
|
124
|
-
disposition:
|
123
|
+
service.url key, expires_in: expires_in, filename: filename, content_type: content_type_for_service_url,
|
124
|
+
disposition: forced_disposition_for_service_url || disposition, **options
|
125
125
|
end
|
126
126
|
|
127
127
|
# Returns a URL that can be used to directly upload a file for this blob on the service. This URL is intended to be
|
@@ -152,7 +152,7 @@ class ActiveStorage::Blob < ActiveRecord::Base
|
|
152
152
|
self.byte_size = io.size
|
153
153
|
self.identified = true
|
154
154
|
|
155
|
-
service.upload
|
155
|
+
service.upload key, io, checksum: checksum, **service_metadata
|
156
156
|
end
|
157
157
|
|
158
158
|
# Downloads the file associated with this blob. If no block is given, the entire file is read into memory and returned.
|
@@ -203,5 +203,29 @@ class ActiveStorage::Blob < ActiveRecord::Base
|
|
203
203
|
ActiveStorage.content_types_to_serve_as_binary.include?(content_type)
|
204
204
|
end
|
205
205
|
|
206
|
+
def allowed_inline?
|
207
|
+
ActiveStorage.content_types_allowed_inline.include?(content_type)
|
208
|
+
end
|
209
|
+
|
210
|
+
def content_type_for_service_url
|
211
|
+
forcibly_serve_as_binary? ? ActiveStorage.binary_content_type : content_type
|
212
|
+
end
|
213
|
+
|
214
|
+
def forced_disposition_for_service_url
|
215
|
+
if forcibly_serve_as_binary? || !allowed_inline?
|
216
|
+
:attachment
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def service_metadata
|
221
|
+
if forcibly_serve_as_binary?
|
222
|
+
{ content_type: ActiveStorage.binary_content_type, disposition: :attachment, filename: filename }
|
223
|
+
elsif !allowed_inline?
|
224
|
+
{ content_type: content_type, disposition: :attachment, filename: filename }
|
225
|
+
else
|
226
|
+
{ content_type: content_type }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
206
230
|
ActiveSupport.run_load_hooks(:active_storage_blob, self)
|
207
231
|
end
|
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
module ActiveStorage::Blob::Identifiable
|
4
4
|
def identify
|
5
|
-
|
5
|
+
unless identified?
|
6
|
+
update! content_type: identify_content_type, identified: true
|
7
|
+
update_service_metadata
|
8
|
+
end
|
6
9
|
end
|
7
10
|
|
8
11
|
def identified?
|
@@ -17,4 +20,8 @@ module ActiveStorage::Blob::Identifiable
|
|
17
20
|
def download_identifiable_chunk
|
18
21
|
service.download_chunk key, 0...4.kilobytes
|
19
22
|
end
|
23
|
+
|
24
|
+
def update_service_metadata
|
25
|
+
service.update_metadata key, service_metadata if service_metadata.any?
|
26
|
+
end
|
20
27
|
end
|
data/lib/active_storage.rb
CHANGED
@@ -48,4 +48,6 @@ module ActiveStorage
|
|
48
48
|
mattr_accessor :paths, default: {}
|
49
49
|
mattr_accessor :variable_content_types, default: []
|
50
50
|
mattr_accessor :content_types_to_serve_as_binary, default: []
|
51
|
+
mattr_accessor :content_types_allowed_inline, default: []
|
52
|
+
mattr_accessor :binary_content_type, default: "application/octet-stream"
|
51
53
|
end
|
@@ -37,6 +37,18 @@ module ActiveStorage
|
|
37
37
|
text/xml
|
38
38
|
application/xml
|
39
39
|
application/xhtml+xml
|
40
|
+
application/mathml+xml
|
41
|
+
text/cache-manifest
|
42
|
+
)
|
43
|
+
|
44
|
+
config.active_storage.content_types_allowed_inline = %w(
|
45
|
+
image/png
|
46
|
+
image/gif
|
47
|
+
image/jpg
|
48
|
+
image/jpeg
|
49
|
+
image/vnd.adobe.photoshop
|
50
|
+
image/vnd.microsoft.icon
|
51
|
+
application/pdf
|
40
52
|
)
|
41
53
|
|
42
54
|
config.eager_load_namespaces << ActiveStorage
|
@@ -51,6 +63,8 @@ module ActiveStorage
|
|
51
63
|
|
52
64
|
ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
|
53
65
|
ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
|
66
|
+
ActiveStorage.content_types_allowed_inline = app.config.active_storage.content_types_allowed_inline || []
|
67
|
+
ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
|
54
68
|
end
|
55
69
|
end
|
56
70
|
|
@@ -64,10 +64,16 @@ module ActiveStorage
|
|
64
64
|
|
65
65
|
# Upload the +io+ to the +key+ specified. If a +checksum+ is provided, the service will
|
66
66
|
# ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError.
|
67
|
-
def upload(key, io, checksum: nil)
|
67
|
+
def upload(key, io, checksum: nil, **options)
|
68
68
|
raise NotImplementedError
|
69
69
|
end
|
70
70
|
|
71
|
+
# Update metadata for the file identified by +key+ in the service.
|
72
|
+
# Override in subclasses only if the service needs to store specific
|
73
|
+
# metadata that has to be updated upon identification.
|
74
|
+
def update_metadata(key, **metadata)
|
75
|
+
end
|
76
|
+
|
71
77
|
# Return the content of the file at the +key+.
|
72
78
|
def download(key)
|
73
79
|
raise NotImplementedError
|
@@ -17,7 +17,7 @@ module ActiveStorage
|
|
17
17
|
@container = container
|
18
18
|
end
|
19
19
|
|
20
|
-
def upload(key, io, checksum: nil)
|
20
|
+
def upload(key, io, checksum: nil, **)
|
21
21
|
instrument :upload, key: key, checksum: checksum do
|
22
22
|
begin
|
23
23
|
blobs.create_block_blob(container, key, IO.try_convert(io) || io, content_md5: checksum)
|
@@ -15,7 +15,7 @@ module ActiveStorage
|
|
15
15
|
@root = root
|
16
16
|
end
|
17
17
|
|
18
|
-
def upload(key, io, checksum: nil)
|
18
|
+
def upload(key, io, checksum: nil, **)
|
19
19
|
instrument :upload, key: key, checksum: checksum do
|
20
20
|
IO.copy_stream(io, make_path_for(key))
|
21
21
|
ensure_integrity_of(key, checksum) if checksum
|
@@ -75,17 +75,23 @@ module ActiveStorage
|
|
75
75
|
|
76
76
|
def url(key, expires_in:, filename:, disposition:, content_type:)
|
77
77
|
instrument :url, key: key do |payload|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
host: current_host,
|
84
|
-
filename: filename,
|
85
|
-
disposition: content_disposition_with(type: disposition, filename: filename),
|
78
|
+
content_disposition = content_disposition_with(type: disposition, filename: filename)
|
79
|
+
verified_key_with_expiration = ActiveStorage.verifier.generate(
|
80
|
+
{
|
81
|
+
key: key,
|
82
|
+
disposition: content_disposition,
|
86
83
|
content_type: content_type
|
87
|
-
|
84
|
+
},
|
85
|
+
{ expires_in: expires_in,
|
86
|
+
purpose: :blob_key }
|
87
|
+
)
|
88
88
|
|
89
|
+
generated_url = url_helpers.rails_disk_service_url(verified_key_with_expiration,
|
90
|
+
host: current_host,
|
91
|
+
disposition: content_disposition,
|
92
|
+
content_type: content_type,
|
93
|
+
filename: filename
|
94
|
+
)
|
89
95
|
payload[:url] = generated_url
|
90
96
|
|
91
97
|
generated_url
|
@@ -15,22 +15,30 @@ module ActiveStorage
|
|
15
15
|
@config = config
|
16
16
|
end
|
17
17
|
|
18
|
-
def upload(key, io, checksum: nil)
|
18
|
+
def upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil)
|
19
19
|
instrument :upload, key: key, checksum: checksum do
|
20
20
|
begin
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
end
|
21
|
+
# GCS's signed URLs don't include params such as response-content-type response-content_disposition
|
22
|
+
# in the signature, which means an attacker can modify them and bypass our effort to force these to
|
23
|
+
# binary and attachment when the file's content type requires it. The only way to force them is to
|
24
|
+
# store them as object's metadata.
|
25
|
+
content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
|
26
|
+
bucket.create_file(io, key, md5: checksum, content_type: content_type, content_disposition: content_disposition)
|
28
27
|
rescue Google::Cloud::InvalidArgumentError
|
29
28
|
raise ActiveStorage::IntegrityError
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
33
|
+
def update_metadata(key, content_type:, disposition: nil, filename: nil)
|
34
|
+
instrument :update_metadata, key: key, content_type: content_type, disposition: disposition do
|
35
|
+
file_for(key).update do |file|
|
36
|
+
file.content_type = content_type
|
37
|
+
file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
34
42
|
# FIXME: Download in chunks when given a block.
|
35
43
|
def download(key)
|
36
44
|
instrument :download, key: key do
|
@@ -24,9 +24,9 @@ module ActiveStorage
|
|
24
24
|
|
25
25
|
# Upload the +io+ to the +key+ specified to all services. If a +checksum+ is provided, all services will
|
26
26
|
# ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError.
|
27
|
-
def upload(key, io, checksum: nil)
|
27
|
+
def upload(key, io, checksum: nil, **options)
|
28
28
|
each_service.collect do |service|
|
29
|
-
service.upload key, io.tap(&:rewind), checksum: checksum
|
29
|
+
service.upload key, io.tap(&:rewind), checksum: checksum, **options
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
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: 5.2.1
|
4
|
+
version: 5.2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.2.1
|
19
|
+
version: 5.2.1.1
|
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: 5.2.1
|
26
|
+
version: 5.2.1.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.2.1
|
33
|
+
version: 5.2.1.1
|
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: 5.2.1
|
40
|
+
version: 5.2.1.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: marcel
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,8 +124,8 @@ homepage: http://rubyonrails.org
|
|
124
124
|
licenses:
|
125
125
|
- MIT
|
126
126
|
metadata:
|
127
|
-
source_code_uri: https://github.com/rails/rails/tree/v5.2.1/activestorage
|
128
|
-
changelog_uri: https://github.com/rails/rails/blob/v5.2.1/activestorage/CHANGELOG.md
|
127
|
+
source_code_uri: https://github.com/rails/rails/tree/v5.2.1.1/activestorage
|
128
|
+
changelog_uri: https://github.com/rails/rails/blob/v5.2.1.1/activestorage/CHANGELOG.md
|
129
129
|
post_install_message:
|
130
130
|
rdoc_options: []
|
131
131
|
require_paths:
|