file_validators 2.1.0 → 2.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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