file_validators 2.1.0 → 2.2.0.beta1
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/.gitignore +2 -0
- data/.travis.yml +1 -2
- data/Appraisals +7 -11
- data/CHANGELOG.md +11 -0
- data/README.md +7 -4
- data/file_validators.gemspec +1 -1
- data/gemfiles/activemodel_3.2.gemfile +1 -1
- data/gemfiles/activemodel_4.0.gemfile +1 -1
- data/gemfiles/activemodel_4.2.gemfile +1 -1
- data/gemfiles/{activemodel_3.0.gemfile → activemodel_5.0.gemfile} +1 -1
- data/lib/file_validators/utils/content_type_detector.rb +11 -8
- data/lib/file_validators/validators/file_content_type_validator.rb +19 -6
- data/lib/file_validators/validators/file_size_validator.rb +15 -5
- data/lib/file_validators/version.rb +1 -1
- data/spec/integration/file_content_type_validation_integration_spec.rb +50 -0
- data/spec/integration/file_size_validator_integration_spec.rb +63 -0
- data/spec/spec_helper.rb +1 -0
- metadata +8 -9
- data/CHANGELOG.mod +0 -6
- data/gemfiles/activemodel_3.1.gemfile +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75fbf34dcce7be5b3770f09d4068c00f50f2cd9d
|
4
|
+
data.tar.gz: e81f181e641308492a13b1ef3ed5034724d2a7f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abb281ff04de1964a07f19d2ee5fa5ccc51f63827b0ae7bb2628c3ddc36379d16ad48e9aa037d5e16ed18a6ab5d0690b0cc866a263c48ce9a754006c53204d9f
|
7
|
+
data.tar.gz: 01417d071f54021f5c8ad73b6a9eb5d35c7b49b29c450037dd2b3b40cbaa13fb9250bf9cfc66931385caab5e2bd934b51987329a736a87645ce6cfa7063bee6c
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -7,12 +7,11 @@ rvm:
|
|
7
7
|
- jruby-9.0.4.0
|
8
8
|
|
9
9
|
gemfile:
|
10
|
+
- gemfiles/activemodel_5.0.gemfile
|
10
11
|
- gemfiles/activemodel_4.2.gemfile
|
11
12
|
- gemfiles/activemodel_4.1.gemfile
|
12
13
|
- gemfiles/activemodel_4.0.gemfile
|
13
14
|
- gemfiles/activemodel_3.2.gemfile
|
14
|
-
- gemfiles/activemodel_3.1.gemfile
|
15
|
-
- gemfiles/activemodel_3.0.gemfile
|
16
15
|
|
17
16
|
matrix:
|
18
17
|
allow_failures:
|
data/Appraisals
CHANGED
@@ -1,17 +1,9 @@
|
|
1
|
-
appraise 'activemodel-3.0' do
|
2
|
-
gem 'activemodel', '3.0.20'
|
3
|
-
end
|
4
|
-
|
5
|
-
appraise 'activemodel-3.1' do
|
6
|
-
gem 'activemodel', '3.1.12'
|
7
|
-
end
|
8
|
-
|
9
1
|
appraise 'activemodel-3.2' do
|
10
|
-
gem 'activemodel', '3.2.
|
2
|
+
gem 'activemodel', '3.2.22.5'
|
11
3
|
end
|
12
4
|
|
13
5
|
appraise 'activemodel-4.0' do
|
14
|
-
gem 'activemodel', '4.0.
|
6
|
+
gem 'activemodel', '4.0.13'
|
15
7
|
end
|
16
8
|
|
17
9
|
appraise 'activemodel-4.1' do
|
@@ -19,5 +11,9 @@ appraise 'activemodel-4.1' do
|
|
19
11
|
end
|
20
12
|
|
21
13
|
appraise 'activemodel-4.2' do
|
22
|
-
gem 'activemodel', '4.2.
|
14
|
+
gem 'activemodel', '4.2.7.1'
|
15
|
+
end
|
16
|
+
|
17
|
+
appraise 'activemodel-5.0' do
|
18
|
+
gem 'activemodel', '5.0.1'
|
23
19
|
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# 2.2.0-beta.1
|
2
|
+
|
3
|
+
* [#17](https://github.com/musaffa/file_validators/pull/17) Now Supports multiple file uploads
|
4
|
+
* As activemodel 3.0 and 3.1 doesn't support `added?` method on the Errors class, the support for both of them have been deprecated in this release.
|
5
|
+
|
6
|
+
# 2.1.0
|
7
|
+
|
8
|
+
* Use autoload for lazy loading of libraries.
|
9
|
+
* Media type spoof valiation is moved to content type detector.
|
10
|
+
* `spoofed_file_media_type` message isn't needed anymore.
|
11
|
+
* Logger info and warning is added.
|
data/README.md
CHANGED
@@ -12,8 +12,11 @@ Any module that uses ActiveModel, for example ActiveRecord, can use these file v
|
|
12
12
|
|
13
13
|
## Support
|
14
14
|
|
15
|
-
* ActiveModel versions: 3 and
|
16
|
-
* Rails versions: 3 and
|
15
|
+
* ActiveModel versions: 3.2, 4 and 5.
|
16
|
+
* Rails versions: 3.2, 4 and 5.
|
17
|
+
|
18
|
+
As of version `2.2`, activemodel 3.0 and 3.1 will no longer be supported.
|
19
|
+
For activemodel 3.0 and 3.1, please use file_validators version `<= 2.1`.
|
17
20
|
|
18
21
|
It has been tested to work with Carrierwave, Paperclip, Dragonfly, Refile etc file uploading solutions.
|
19
22
|
Validations works both before and after uploads.
|
@@ -253,8 +256,8 @@ $ rake test:unit
|
|
253
256
|
$ rake test:integration
|
254
257
|
|
255
258
|
# test different active model versions
|
256
|
-
$ appraisal install
|
257
|
-
$ appraisal rake
|
259
|
+
$ bundle exec appraisal install
|
260
|
+
$ bundle exec appraisal rake
|
258
261
|
```
|
259
262
|
|
260
263
|
## Problems
|
data/file_validators.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.test_files = s.files.grep(%r{^spec/})
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
|
20
|
-
s.add_dependency 'activemodel', '>= 3.
|
20
|
+
s.add_dependency 'activemodel', '>= 3.2'
|
21
21
|
s.add_dependency 'mime-types', '>= 1.0'
|
22
22
|
|
23
23
|
s.add_development_dependency 'cocaine', '~> 0.5.4'
|
@@ -22,20 +22,23 @@ module FileValidators
|
|
22
22
|
|
23
23
|
# content type detection strategy:
|
24
24
|
#
|
25
|
-
# 1.
|
26
|
-
# 2.
|
27
|
-
# 3.
|
25
|
+
# 1. invalid file_path: returns 'application/octet-stream'
|
26
|
+
# 2. empty file: returns 'inode/x-empty'
|
27
|
+
# 3. valid file: returns the content type using file command
|
28
|
+
# 4. valid file but file commoand raises error: returns 'application/octet-stream'
|
28
29
|
|
29
30
|
def detect
|
30
|
-
|
31
|
+
if !File.exist?(file_path)
|
32
|
+
DEFAULT_CONTENT_TYPE
|
33
|
+
elsif File.zero?(file_path)
|
34
|
+
EMPTY_CONTENT_TYPE
|
35
|
+
else
|
36
|
+
content_type_from_content
|
37
|
+
end
|
31
38
|
end
|
32
39
|
|
33
40
|
private
|
34
41
|
|
35
|
-
def empty_file?
|
36
|
-
File.exists?(file_path) && File.size(file_path) == 0
|
37
|
-
end
|
38
|
-
|
39
42
|
def content_type_from_content
|
40
43
|
content_type = type_from_file_command
|
41
44
|
|
@@ -9,15 +9,17 @@ module ActiveModel
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def validate_each(record, attribute, value)
|
12
|
-
|
13
|
-
unless
|
12
|
+
values = parse_values(value)
|
13
|
+
unless values.empty?
|
14
14
|
mode = option_value(record, :mode)
|
15
|
-
content_type = get_content_type(value, mode)
|
16
15
|
allowed_types = option_content_types(record, :allow)
|
17
16
|
forbidden_types = option_content_types(record, :exclude)
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
values.each do |value|
|
19
|
+
content_type = get_content_type(value, mode)
|
20
|
+
validate_whitelist(record, attribute, content_type, allowed_types)
|
21
|
+
validate_blacklist(record, attribute, content_type, forbidden_types)
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
@@ -35,6 +37,14 @@ module ActiveModel
|
|
35
37
|
|
36
38
|
private
|
37
39
|
|
40
|
+
def parse_values(value)
|
41
|
+
return [] unless value.present?
|
42
|
+
|
43
|
+
value = JSON.parse(value) if value.is_a?(String)
|
44
|
+
|
45
|
+
Array.wrap(value).reject { |value| value.blank? }
|
46
|
+
end
|
47
|
+
|
38
48
|
def get_file_path(value)
|
39
49
|
if value.try(:path)
|
40
50
|
value.path
|
@@ -87,7 +97,10 @@ module ActiveModel
|
|
87
97
|
end
|
88
98
|
|
89
99
|
def mark_invalid(record, attribute, error, option_types)
|
90
|
-
|
100
|
+
error_options = options.merge(types: option_types.join(', '))
|
101
|
+
unless record.errors.added?(attribute, error, error_options)
|
102
|
+
record.errors.add attribute, error, error_options
|
103
|
+
end
|
91
104
|
end
|
92
105
|
end
|
93
106
|
|
@@ -13,15 +13,14 @@ module ActiveModel
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def validate_each(record, attribute, value)
|
16
|
-
|
17
|
-
unless
|
16
|
+
values = parse_values(value)
|
17
|
+
unless values.empty?
|
18
18
|
options.slice(*CHECKS.keys).each do |option, option_value|
|
19
|
-
value = OpenStruct.new(value) if value.is_a?(Hash)
|
20
19
|
option_value = option_value.call(record) if option_value.is_a?(Proc)
|
21
|
-
|
20
|
+
if values.any? { |v| not valid_size?(v.size, option, option_value) }
|
22
21
|
record.errors.add(attribute,
|
23
22
|
"file_size_is_#{option}".to_sym,
|
24
|
-
filtered_options(
|
23
|
+
filtered_options(values).merge!(detect_error_options(option_value)))
|
25
24
|
end
|
26
25
|
end
|
27
26
|
end
|
@@ -39,6 +38,17 @@ module ActiveModel
|
|
39
38
|
|
40
39
|
private
|
41
40
|
|
41
|
+
def parse_values(value)
|
42
|
+
return [] unless value.present?
|
43
|
+
|
44
|
+
value = JSON.parse(value) if value.is_a?(String)
|
45
|
+
return [] unless value.present?
|
46
|
+
|
47
|
+
value = OpenStruct.new(value) if value.is_a?(Hash)
|
48
|
+
|
49
|
+
Array.wrap(value).reject { |value| value.blank? }
|
50
|
+
end
|
51
|
+
|
42
52
|
def check_options(klass, options)
|
43
53
|
options.each do |option, value|
|
44
54
|
unless value.is_a?(klass) || value.is_a?(Proc)
|
@@ -379,4 +379,54 @@ describe 'File Content Type integration with ActiveModel' do
|
|
379
379
|
it { is_expected.to be_valid }
|
380
380
|
end
|
381
381
|
end
|
382
|
+
|
383
|
+
context 'image data as array' do
|
384
|
+
before :all do
|
385
|
+
Person.class_eval do
|
386
|
+
Person.reset_callbacks(:validate)
|
387
|
+
validates :avatar, file_content_type: { allow: 'image/jpeg' }
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
subject { Person.new }
|
392
|
+
|
393
|
+
context 'for one invalid content type' do
|
394
|
+
before {
|
395
|
+
subject.avatar = [
|
396
|
+
Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain'),
|
397
|
+
Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
|
398
|
+
]
|
399
|
+
}
|
400
|
+
it { is_expected.not_to be_valid }
|
401
|
+
end
|
402
|
+
|
403
|
+
context 'for two invalid content types' do
|
404
|
+
before {
|
405
|
+
subject.avatar = [
|
406
|
+
Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain'),
|
407
|
+
Rack::Test::UploadedFile.new(@sample_text_path, 'text/plain')
|
408
|
+
]
|
409
|
+
}
|
410
|
+
|
411
|
+
it 'is invalid and adds just one error' do
|
412
|
+
expect(subject).not_to be_valid
|
413
|
+
expect(subject.errors.count).to eq 1
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context 'for valid content type' do
|
418
|
+
before {
|
419
|
+
subject.avatar = [
|
420
|
+
Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg'),
|
421
|
+
Rack::Test::UploadedFile.new(@cute_path, 'image/jpeg')
|
422
|
+
]
|
423
|
+
}
|
424
|
+
it { is_expected.to be_valid }
|
425
|
+
end
|
426
|
+
|
427
|
+
context 'empty array' do
|
428
|
+
before { subject.avatar = [] }
|
429
|
+
it { is_expected.to be_valid }
|
430
|
+
end
|
431
|
+
end
|
382
432
|
end
|
@@ -263,4 +263,67 @@ describe 'File Size Validator integration with ActiveModel' do
|
|
263
263
|
it { is_expected.to be_valid }
|
264
264
|
end
|
265
265
|
end
|
266
|
+
|
267
|
+
context 'image data as array' do
|
268
|
+
before :all do
|
269
|
+
Person.class_eval do
|
270
|
+
Person.reset_callbacks(:validate)
|
271
|
+
validates :avatar, file_size: { greater_than: 20.kilobytes }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
subject { Person.new }
|
276
|
+
|
277
|
+
context 'when size of one file is less than the specified size' do
|
278
|
+
before {
|
279
|
+
subject.avatar = [
|
280
|
+
Rack::Test::UploadedFile.new(@cute_path),
|
281
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path)
|
282
|
+
]
|
283
|
+
}
|
284
|
+
it { is_expected.not_to be_valid }
|
285
|
+
end
|
286
|
+
|
287
|
+
context 'when size of all files is within the specified size' do
|
288
|
+
before {
|
289
|
+
subject.avatar = [
|
290
|
+
Rack::Test::UploadedFile.new(@cute_path),
|
291
|
+
Rack::Test::UploadedFile.new(@cute_path)
|
292
|
+
]
|
293
|
+
}
|
294
|
+
|
295
|
+
it 'is invalid and adds just one error' do
|
296
|
+
expect(subject).not_to be_valid
|
297
|
+
expect(subject.errors.count).to eq 1
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'when size of all files is less than the specified size' do
|
302
|
+
before {
|
303
|
+
subject.avatar = [
|
304
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path),
|
305
|
+
Rack::Test::UploadedFile.new(@chubby_bubble_path)
|
306
|
+
]
|
307
|
+
}
|
308
|
+
|
309
|
+
it { is_expected.to be_valid }
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'one file' do
|
313
|
+
context 'when file size is out of range' do
|
314
|
+
before { subject.avatar = [Rack::Test::UploadedFile.new(@cute_path)] }
|
315
|
+
it { is_expected.not_to be_valid }
|
316
|
+
end
|
317
|
+
|
318
|
+
context 'when file size within range' do
|
319
|
+
before { subject.avatar = [Rack::Test::UploadedFile.new(@chubby_bubble_path)] }
|
320
|
+
it { is_expected.to be_valid }
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'empty array' do
|
325
|
+
before { subject.avatar = [] }
|
326
|
+
it { is_expected.to be_valid }
|
327
|
+
end
|
328
|
+
end
|
266
329
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: file_validators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ahmad Musaffa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.2'
|
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: '3.
|
26
|
+
version: '3.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: mime-types
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,19 +119,18 @@ files:
|
|
119
119
|
- ".rspec"
|
120
120
|
- ".travis.yml"
|
121
121
|
- Appraisals
|
122
|
-
- CHANGELOG.
|
122
|
+
- CHANGELOG.md
|
123
123
|
- Gemfile
|
124
124
|
- MIT-LICENSE
|
125
125
|
- README.md
|
126
126
|
- README.rdoc
|
127
127
|
- Rakefile
|
128
128
|
- file_validators.gemspec
|
129
|
-
- gemfiles/activemodel_3.0.gemfile
|
130
|
-
- gemfiles/activemodel_3.1.gemfile
|
131
129
|
- gemfiles/activemodel_3.2.gemfile
|
132
130
|
- gemfiles/activemodel_4.0.gemfile
|
133
131
|
- gemfiles/activemodel_4.1.gemfile
|
134
132
|
- gemfiles/activemodel_4.2.gemfile
|
133
|
+
- gemfiles/activemodel_5.0.gemfile
|
135
134
|
- lib/file_validators.rb
|
136
135
|
- lib/file_validators/locale/en.yml
|
137
136
|
- lib/file_validators/utils/content_type_detector.rb
|
@@ -170,9 +169,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
170
169
|
version: '0'
|
171
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
171
|
requirements:
|
173
|
-
- - "
|
172
|
+
- - ">"
|
174
173
|
- !ruby/object:Gem::Version
|
175
|
-
version:
|
174
|
+
version: 1.3.1
|
176
175
|
requirements: []
|
177
176
|
rubyforge_project:
|
178
177
|
rubygems_version: 2.5.1
|
data/CHANGELOG.mod
DELETED