Skip to content

Commit

Permalink
Rename blocklist to denylist, and also use allowlist/denylist termino…
Browse files Browse the repository at this point in the history
…logy for I18n

Refs. #2442
  • Loading branch information
mshibuya committed Feb 14, 2021
1 parent 1e60e05 commit 4c3cac7
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 147 deletions.
8 changes: 4 additions & 4 deletions lib/carrierwave/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ en:
carrierwave_processing_error: failed to be processed
carrierwave_integrity_error: is not of an allowed file type
carrierwave_download_error: could not be downloaded
extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
extension_blacklist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
content_type_whitelist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
content_type_blacklist_error: "You are not allowed to upload %{content_type} files"
extension_allowlist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
rmagick_processing_error: "Failed to manipulate with rmagick, maybe it is not an image?"
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
min_size_error: "File size should be greater than %{min_size}"
Expand Down
25 changes: 14 additions & 11 deletions lib/carrierwave/uploader/content_type_blacklist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,48 @@ module ContentTypeBlacklist
end

##
# Override this method in your uploader to provide a blacklist of files content types
# Override this method in your uploader to provide a denylist of files content types
# which are not allowed to be uploaded.
# Not only strings but Regexp are allowed as well.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a blacklist of content types which are not allowed to be uploaded
# [NilClass, String, Regexp, Array[String, Regexp]] a denylist of content types which are not allowed to be uploaded
#
# === Examples
#
# def content_type_blacklist
# def content_type_denylist
# %w(text/json application/json)
# end
#
# Basically the same, but using a Regexp:
#
# def content_type_blacklist
# def content_type_denylist
# [/(text|application)\/json/]
# end
#
def content_type_blacklist
content_type_blocklist
def content_type_denylist
if respond_to?(:content_type_blacklist)
ActiveSupport::Deprecation.warn "#content_type_blacklist is deprecated, use #content_type_denylist instead." unless instance_variable_defined?(:@content_type_blacklist_warned)
@content_type_blacklist_warned = true
content_type_blacklist
end
end

def content_type_blocklist; end

private

def check_content_type_blacklist!(new_file)
return unless content_type_blacklist
return unless content_type_denylist

content_type = new_file.content_type
if blacklisted_content_type?(content_type)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error", content_type: content_type)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error",
content_type: content_type, default: :"errors.messages.content_type_denylist_error")
end
end

def blacklisted_content_type?(content_type)
Array(content_type_blacklist).any? { |item| content_type =~ /#{item}/ }
Array(content_type_denylist).any? { |item| content_type =~ /#{item}/ }
end

end # ContentTypeBlacklist
Expand Down
25 changes: 14 additions & 11 deletions lib/carrierwave/uploader/content_type_whitelist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,49 @@ module ContentTypeWhitelist
before :cache, :check_content_type_whitelist!
end

def content_type_allowlist; end

##
# Override this method in your uploader to provide a whitelist of files content types
# Override this method in your uploader to provide an allowlist of files content types
# which are allowed to be uploaded.
# Not only strings but Regexp are allowed as well.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a whitelist of content types which are allowed to be uploaded
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of content types which are allowed to be uploaded
#
# === Examples
#
# def content_type_whitelist
# def content_type_allowlist
# %w(text/json application/json)
# end
#
# Basically the same, but using a Regexp:
#
# def content_type_whitelist
# def content_type_allowlist
# [/(text|application)\/json/]
# end
#
def content_type_whitelist
content_type_allowlist
def content_type_allowlist
if respond_to?(:content_type_whitelist)
ActiveSupport::Deprecation.warn "#content_type_whitelist is deprecated, use #content_type_allowlist instead." unless instance_variable_defined?(:@content_type_whitelist_warned)
@content_type_whitelist_warned = true
content_type_whitelist
end
end

private

def check_content_type_whitelist!(new_file)
return unless content_type_whitelist
return unless content_type_allowlist

content_type = new_file.content_type
if !whitelisted_content_type?(content_type)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type, allowed_types: Array(content_type_whitelist).join(", "))
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type,
allowed_types: Array(content_type_allowlist).join(", "), default: :"errors.messages.content_type_allowlist_error")
end
end

def whitelisted_content_type?(content_type)
Array(content_type_whitelist).any? do |item|
Array(content_type_allowlist).any? do |item|
item = Regexp.quote(item) if item.class != Regexp
content_type =~ /#{item}/
end
Expand Down
28 changes: 15 additions & 13 deletions lib/carrierwave/uploader/extension_blacklist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,51 @@ module ExtensionBlacklist
end

##
# Override this method in your uploader to provide a black list of extensions which
# Override this method in your uploader to provide a denylist of extensions which
# are prohibited to be uploaded. Compares the file's extension case insensitive.
# Furthermore, not only strings but Regexp are allowed as well.
#
# When using a Regexp in the black list, `\A` and `\z` are automatically added to
# When using a Regexp in the denylist, `\A` and `\z` are automatically added to
# the Regexp expression, also case insensitive.
#
# === Returns

# [NilClass, String, Regexp, Array[String, Regexp]] a black list of extensions which are prohibited to be uploaded
# [NilClass, String, Regexp, Array[String, Regexp]] a deny list of extensions which are prohibited to be uploaded
#
# === Examples
#
# def extension_blacklist
# def extension_denylist
# %w(swf tiff)
# end
#
# Basically the same, but using a Regexp:
#
# def extension_blacklist
# def extension_denylist
# [/swf/, 'tiff']
# end
#

def extension_blacklist
extension_blocklist
def extension_denylist
if respond_to?(:extension_blacklist)
ActiveSupport::Deprecation.warn "#extension_blacklist is deprecated, use #extension_denylist instead." unless instance_variable_defined?(:@extension_blacklist_warned)
@extension_blacklist_warned = true
extension_blacklist
end
end

def extension_blocklist; end

private

def check_extension_blacklist!(new_file)
return unless extension_blacklist
return unless extension_denylist

extension = new_file.extension.to_s
if blacklisted_extension?(extension)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect, prohibited_types: Array(extension_blacklist).join(", "))
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect,
prohibited_types: Array(extension_denylist).join(", "), default: :"errors.messages.extension_denylist_error")
end
end

def blacklisted_extension?(extension)
Array(extension_blacklist).any? { |item| extension =~ /\A#{item}\z/i }
Array(extension_denylist).any? { |item| extension =~ /\A#{item}\z/i }
end
end
end
Expand Down
29 changes: 16 additions & 13 deletions lib/carrierwave/uploader/extension_whitelist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,55 @@ module ExtensionWhitelist
before :cache, :check_extension_whitelist!
end

def extension_allowlist; end

##
# Override this method in your uploader to provide a white list of extensions which
# Override this method in your uploader to provide an allowlist of extensions which
# are allowed to be uploaded. Compares the file's extension case insensitive.
# Furthermore, not only strings but Regexp are allowed as well.
#
# When using a Regexp in the white list, `\A` and `\z` are automatically added to
# When using a Regexp in the allowlist, `\A` and `\z` are automatically added to
# the Regexp expression, also case insensitive.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a white list of extensions which are allowed to be uploaded
# [NilClass, String, Regexp, Array[String, Regexp]] an allowlist of extensions which are allowed to be uploaded
#
# === Examples
#
# def extension_whitelist
# def extension_allowlist
# %w(jpg jpeg gif png)
# end
#
# Basically the same, but using a Regexp:
#
# def extension_whitelist
# def extension_allowlist
# [/jpe?g/, 'gif', 'png']
# end
#
def extension_whitelist
extension_allowlist
def extension_allowlist
if respond_to?(:extension_whitelist)
ActiveSupport::Deprecation.warn "#extension_whitelist is deprecated, use #extension_allowlist instead." unless instance_variable_defined?(:@extension_whitelist_warned)
@extension_whitelist_warned = true
extension_whitelist
end
end

private

def check_extension_whitelist!(new_file)
return unless extension_whitelist
return unless extension_allowlist

extension = new_file.extension.to_s
if !whitelisted_extension?(extension)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect, allowed_types: Array(extension_whitelist).join(", "))
# Look for whitelist first, then fallback to allowlist
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect,
allowed_types: Array(extension_allowlist).join(", "), default: :"errors.messages.extension_allowlist_error")
end
end

def whitelisted_extension?(extension)
downcase_extension = extension.downcase
Array(extension_whitelist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
Array(extension_allowlist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
end

end # ExtensionWhitelist
end # Uploader
end # CarrierWave
60 changes: 38 additions & 22 deletions spec/uploader/content_type_blacklist_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,68 @@
allow(CarrierWave).to receive(:generate_cache_id).and_return('1369894322-345-1234-2255')
end

context "when there is no blacklist" do
context "when there is no denylist" do
it "does not raise an integrity error" do
allow(uploader).to receive(:content_type_blacklist).and_return(nil)
allow(uploader).to receive(:content_type_denylist).and_return(nil)

expect { uploader.cache!(ruby_file) }.not_to raise_error
end
end

context "when there is a blacklist" do
context "when the blacklist is an array of values" do
it "does not raise an integrity error when the file has not a blacklisted content type" do
allow(uploader).to receive(:content_type_blacklist).and_return(['image/gif'])
context "when there is a denylist" do
context "when the denylist is an array of values" do
it "does not raise an integrity error when the file has not a denylisted content type" do
allow(uploader).to receive(:content_type_denylist).and_return(['image/gif'])

expect { uploader.cache!(bork_file) }.not_to raise_error
end

it "raises an integrity error if the file has a blacklisted content type" do
allow(uploader).to receive(:content_type_blacklist).and_return(['image/png'])
it "raises an integrity error if the file has a denylisted content type" do
allow(uploader).to receive(:content_type_denylist).and_return(['image/png'])

expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError)
expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError, 'You are not allowed to upload image/png files')
end

it "raises an integrity error if the file has a blocklisted content type" do
allow(uploader).to receive(:content_type_blocklist).and_return(['image/png'])
it "accepts content types as regular expressions" do
allow(uploader).to receive(:content_type_denylist).and_return([/image\//])

expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError)
end
end

it "accepts content types as regular expressions" do
allow(uploader).to receive(:content_type_blacklist).and_return([/image\//])
context "when the denylist is a single value" do
it "accepts a single content type string value" do
allow(uploader).to receive(:content_type_denylist).and_return('image/gif')

expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError)
expect { uploader.cache!(ruby_file) }.not_to raise_error
end
end

context "when the blacklist is a single value" do
it "accepts a single extension string value" do
allow(uploader).to receive(:extension_whitelist).and_return('jpeg')
it "accepts a single content type regular expression value" do
allow(uploader).to receive(:content_type_denylist).and_return(/image\/gif/)

expect { uploader.cache!(test_file) }.not_to raise_error
expect { uploader.cache!(ruby_file) }.not_to raise_error
end
end
end

context "when there is a blacklist" do
it "uses the blacklist but shows deprecation" do
allow(uploader).to receive(:content_type_blacklist).and_return(['image/png'])

expect(ActiveSupport::Deprecation).to receive(:warn).with('#content_type_blacklist is deprecated, use #content_type_denylist instead.')
expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError)
end

it "accepts a single extension regular expression value" do
allow(uploader).to receive(:extension_whitelist).and_return(/jpe?g/)
it "looks for content_type_whitelist first for I18n translation" do
allow(uploader).to receive(:content_type_denylist).and_return(['image/png'])

expect { uploader.cache!(test_file) }.not_to raise_error
change_locale_and_store_translations(:nl, :errors => {
:messages => {
:content_type_denylist_error => "this will not be used",
:content_type_blacklist_error => "Het is niet toegestaan om %{content_type} bestanden te uploaden"
}
}) do
expect { uploader.cache!(ruby_file) }.to raise_error(CarrierWave::IntegrityError, 'Het is niet toegestaan om image/png bestanden te uploaden')
end
end
end
Expand Down
Loading

0 comments on commit 4c3cac7

Please sign in to comment.