Commit 4b8dce44 by Dave Donahue Committed by Jon Yurek

Add support for blacklisting certain content_types

parent 4ea2de63
......@@ -8,21 +8,41 @@ module Paperclip
def validate_each(record, attribute, value)
attribute = "#{attribute}_content_type".to_sym
value = record.send(:read_attribute_for_validation, attribute)
allowed_types = [options[:content_type]].flatten
value = record.send :read_attribute_for_validation, attribute
return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
if allowed_types.none? { |type| type === value }
record.errors.add(attribute, :invalid, options.merge(
:types => allowed_types.join(', ')
))
validate_whitelist(record, attribute, value)
validate_blacklist(record, attribute, value)
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
def check_validity!
unless options.has_key?(:content_type)
raise ArgumentError, "You must pass in :content_type to the validator"
unless options.has_key?(:content_type) || options.has_key?(:not)
raise ArgumentError, "You must pass in either :content_type or :not to the validator"
end
end
end
......@@ -36,6 +56,7 @@ module Paperclip
# 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
# match. Allows all by default.
# * +not+: Forbidden content types.
# * +message+: The message to display when the uploaded file has an invalid
# content type.
# * +if+: A lambda or name of an instance method. Validation will only
......
......@@ -76,93 +76,189 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
end
end
context "with an allowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/jpg"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
context "whitelist format" do
context "with an allowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/jpg"
@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?
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
end
context "as an regexp" do
setup do
build_validator :content_type => /^image\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
context "as an regexp" do
setup do
build_validator :content_type => /^image\/.*/
@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
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
context "as a list" do
setup do
build_validator :content_type => ["image/png", "image/jpg", "image/jpeg"]
@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
end
context "as a list" do
setup do
build_validator :content_type => ["image/png", "image/jpg", "image/jpeg"]
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
context "with a disallowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/png"
@dummy.stubs(:avatar_content_type => "image/jpg")
@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
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
context "as a regexp" do
setup do
build_validator :content_type => /^text\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@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 :content_type => "image/png", :message => "should be a PNG image"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should be a PNG image"
end
end
context "with interpolation" do
setup do
build_validator :content_type => "image/png", :message => "should have content type %{types}"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should have content type image/png"
end
end
end
end
end
context "with a disallowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/png"
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
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 "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
should "not set an error message" do
assert @dummy.errors[:avatar_content_type].blank?
end
end
end
context "as a regexp" do
setup do
build_validator :content_type => /^text\/.*/
@dummy.stubs(:avatar_content_type => "image/jpg")
@validator.validate(@dummy)
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
should "set a correct default error message" do
assert @dummy.errors[:avatar_content_type].present?
assert_includes @dummy.errors[:avatar_content_type], "is invalid"
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 :message option" do
context "without interpolation" do
context "with a disallowed type" do
context "as a string" do
setup do
build_validator :content_type => "image/png", :message => "should be a PNG image"
@dummy.stubs(:avatar_content_type => "image/jpg")
build_validator :not => "image/png"
@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 be a PNG image"
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 interpolation" do
context "as a regexp" do
setup do
build_validator :content_type => "image/png", :message => "should have content type %{types}"
@dummy.stubs(:avatar_content_type => "image/jpg")
build_validator :not => /^text\/.*/
@dummy.stubs(:avatar_content_type => "text/plain")
@validator.validate(@dummy)
end
should "set a correct error message" do
assert_includes @dummy.errors[:avatar_content_type], "should have content type image/png"
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
......@@ -185,8 +281,12 @@ class AttachmentContentTypeValidatorTest < Test::Unit::TestCase
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"
end
should "not raise argument error if :not was given" do
build_validator :not => "image/jpg"
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