mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-19 15:01:14 +00:00
Option to specify allowed extensions for a file custom field (#6719).
git-svn-id: http://svn.redmine.org/redmine/trunk@15921 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
311ca416d7
commit
f94711ea8c
@ -354,22 +354,37 @@ class Attachment < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if the extension is allowed, otherwise false
|
# Returns true if the extension is allowed regarding allowed/denied
|
||||||
|
# extensions defined in application settings, otherwise false
|
||||||
def self.valid_extension?(extension)
|
def self.valid_extension?(extension)
|
||||||
extension = extension.downcase.sub(/\A\.+/, '')
|
|
||||||
|
|
||||||
denied, allowed = [:attachment_extensions_denied, :attachment_extensions_allowed].map do |setting|
|
denied, allowed = [:attachment_extensions_denied, :attachment_extensions_allowed].map do |setting|
|
||||||
Setting.send(setting).to_s.split(",").map {|s| s.strip.downcase.sub(/\A\.+/, '')}.reject(&:blank?)
|
Setting.send(setting)
|
||||||
end
|
end
|
||||||
if denied.present? && denied.include?(extension)
|
if denied.present? && extension_in?(extension, denied)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
unless allowed.blank? || allowed.include?(extension)
|
if allowed.present? && !extension_in?(extension, allowed)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if extension belongs to extensions list.
|
||||||
|
def self.extension_in?(extension, extensions)
|
||||||
|
extension = extension.downcase.sub(/\A\.+/, '')
|
||||||
|
|
||||||
|
unless extensions.is_a?(Array)
|
||||||
|
extensions = extensions.to_s.split(",").map(&:strip)
|
||||||
|
end
|
||||||
|
extensions = extensions.map {|s| s.downcase.sub(/\A\.+/, '')}.reject(&:blank?)
|
||||||
|
extensions.include?(extension)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns true if attachment's extension belongs to extensions list.
|
||||||
|
def extension_in?(extensions)
|
||||||
|
self.class.extension_in?(File.extname(filename), extensions)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Physically deletes the file from the file system
|
# Physically deletes the file from the file system
|
||||||
|
|||||||
@ -87,7 +87,8 @@ class CustomField < ActiveRecord::Base
|
|||||||
'text_formatting',
|
'text_formatting',
|
||||||
'edit_tag_style',
|
'edit_tag_style',
|
||||||
'user_role',
|
'user_role',
|
||||||
'version_status'
|
'version_status',
|
||||||
|
'extensions_allowed'
|
||||||
|
|
||||||
def format
|
def format
|
||||||
@format ||= Redmine::FieldFormat.find(field_format)
|
@format ||= Redmine::FieldFormat.find(field_format)
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
<p>
|
||||||
|
<%= f.text_field :extensions_allowed, :size => 50, :label => :setting_attachment_extensions_allowed %>
|
||||||
|
<em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: txt, png</em>
|
||||||
|
</p>
|
||||||
@ -861,6 +861,7 @@ module Redmine
|
|||||||
self.form_partial = 'custom_fields/formats/attachment'
|
self.form_partial = 'custom_fields/formats/attachment'
|
||||||
self.is_filter_supported = false
|
self.is_filter_supported = false
|
||||||
self.change_no_details = true
|
self.change_no_details = true
|
||||||
|
field_attributes :extensions_allowed
|
||||||
|
|
||||||
def set_custom_field_value(custom_field, custom_field_value, value)
|
def set_custom_field_value(custom_field, custom_field_value, value)
|
||||||
attachment_present = false
|
attachment_present = false
|
||||||
@ -917,8 +918,18 @@ module Redmine
|
|||||||
def validate_custom_value(custom_value)
|
def validate_custom_value(custom_value)
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
if custom_value.instance_variable_get("@attachment_present") && custom_value.value.blank?
|
if custom_value.value.blank?
|
||||||
errors << ::I18n.t('activerecord.errors.messages.invalid')
|
if custom_value.instance_variable_get("@attachment_present")
|
||||||
|
errors << ::I18n.t('activerecord.errors.messages.invalid')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if custom_value.value.present?
|
||||||
|
attachment = Attachment.where(:id => custom_value.value.to_s).first
|
||||||
|
extensions = custom_value.custom_field.extensions_allowed
|
||||||
|
if attachment && extensions.present? && !attachment.extension_in?(extensions)
|
||||||
|
errors << "#{::I18n.t('activerecord.errors.messages.invalid')} (#{l(:setting_attachment_extensions_allowed)}: #{extensions})"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
errors.uniq
|
errors.uniq
|
||||||
|
|||||||
@ -153,4 +153,42 @@ class AttachmentFieldFormatTest < Redmine::IntegrationTest
|
|||||||
assert_equal attachment.id.to_s, custom_value.value
|
assert_equal attachment.id.to_s, custom_value.value
|
||||||
assert_equal custom_value, attachment.reload.container
|
assert_equal custom_value, attachment.reload.container
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_create_with_valid_extension
|
||||||
|
@field.extensions_allowed = "txt, log"
|
||||||
|
@field.save!
|
||||||
|
|
||||||
|
attachment = new_record(Attachment) do
|
||||||
|
assert_difference 'Issue.count' do
|
||||||
|
post '/projects/ecookbook/issues', {
|
||||||
|
:issue => {
|
||||||
|
:subject => "Blank",
|
||||||
|
:custom_field_values => {
|
||||||
|
@field.id => {:file => uploaded_test_file("testfile.txt", "text/plain")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_response 302
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create_with_invalid_extension_should_fail
|
||||||
|
@field.extensions_allowed = "png, jpeg"
|
||||||
|
@field.save!
|
||||||
|
|
||||||
|
attachment = new_record(Attachment) do
|
||||||
|
assert_no_difference 'Issue.count' do
|
||||||
|
post '/projects/ecookbook/issues', {
|
||||||
|
:issue => {
|
||||||
|
:subject => "Blank",
|
||||||
|
:custom_field_values => {
|
||||||
|
@field.id => {:file => uploaded_test_file("testfile.txt", "text/plain")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user