Commit 4b8dce44 by Dave Donahue Committed by Jon Yurek

Add support for blacklisting certain content_types

parent 4ea2de63
...@@ -8,21 +8,41 @@ module Paperclip ...@@ -8,21 +8,41 @@ module Paperclip
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
attribute = "#{attribute}_content_type".to_sym attribute = "#{attribute}_content_type".to_sym
value = record.send(:read_attribute_for_validation, attribute) value = record.send :read_attribute_for_validation, attribute
allowed_types = [options[:content_type]].flatten
return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
if allowed_types.none? { |type| type === value } validate_whitelist(record, attribute, value)
record.errors.add(attribute, :invalid, options.merge( validate_blacklist(record, attribute, value)
:types => allowed_types.join(', ')
))
end end
def validate_whitelist(record, attribute, value)
if allowed_types.present? && allowed_types.none? { |type| type === value }
mark_invalid record, attribute, allowed_types
end
end
def validate_blacklist(record, attribute, value)
if forbidden_types.present? && forbidden_types.any? { |type| type === value }
mark_invalid record, attribute, forbidden_types
end
end
def mark_invalid(record, attribute, types)
record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
end
def allowed_types
[options[:content_type]].flatten.compact
end
def forbidden_types
[options[:not]].flatten.compact
end end
def check_validity! def check_validity!
unless options.has_key?(:content_type) unless options.has_key?(:content_type) || options.has_key?(:not)
raise ArgumentError, "You must pass in :content_type to the validator" raise ArgumentError, "You must pass in either :content_type or :not to the validator"
end end
end end
end end
...@@ -36,6 +56,7 @@ module Paperclip ...@@ -36,6 +56,7 @@ module Paperclip
# may not expect. For example, JPEG images are given image/pjpeg and # may not expect. For example, JPEG images are given image/pjpeg and
# PNGs are image/x-png, so keep that in mind when determining how you # PNGs are image/x-png, so keep that in mind when determining how you
# match. Allows all by default. # match. Allows all by default.
# * +not+: Forbidden content types.
# * +message+: The message to display when the uploaded file has an invalid # * +message+: The message to display when the uploaded file has an invalid
# content type. # content type.
# * +if+: A lambda or name of an instance method. Validation will only # * +if+: A lambda or name of an instance method. Validation will only
......
...@@ -76,6 +76,7 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase ...@@ -76,6 +76,7 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
end end
end end
context "whitelist format" do
context "with an allowed type" do context "with an allowed type" do
context "as a string" do context "as a string" do
setup do setup do
...@@ -167,6 +168,101 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase ...@@ -167,6 +168,101 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
end end
end end
end end
end
context "blacklist format" do
context "with an allowed type" do
context "as a string" do
setup do
build_validator :not => "image/gif"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
context "as an regexp" do
setup do
build_validator :not => /^text\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
context "as a list" do
setup do
build_validator :not => ["image/png", "image/jpg", "image/jpeg"]
@dummy.stubs(:avatar_content_type => "image/gif")
@validator.validate(@dummy)
end
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
end
context "with a disallowed type" do
context "as a string" do
setup do
build_validator :not => "image/png"
@dummy.stubs(:avatar_content_type => "image/png")
@validator.validate(@dummy)
end
should "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
end
end
context "as a regexp" do
setup do
build_validator :not => /^text\/.*/
@dummy.stubs(:avatar_content_type => "text/plain")
@validator.validate(@dummy)
end
should "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
end
end
context "with :message option" do
context "without interpolation" do
setup do
build_validator :not => "image/png", :message => "should not be a PNG image"
@dummy.stubs(:avatar_content_type => "image/png")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should not be a PNG image"
end
end
context "with interpolation" do
setup do
build_validator :not => "image/png", :message => "should not have content type %{types}"
@dummy.stubs(:avatar_content_type => "image/png")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should not have content type image/png"
end
end
end
end
end
context "using the helper" do context "using the helper" do
setup do setup do
...@@ -185,8 +281,12 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase ...@@ -185,8 +281,12 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
end end
end end
should "not raise arguemnt error if :content_type was given" do should "not raise argument error if :content_type was given" do
build_validator :content_type => "image/jpg" build_validator :content_type => "image/jpg"
end end
should "not raise argument error if :not was given" do
build_validator :not => "image/jpg"
end
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment