This commit is contained in:
Karel Pičman 2024-11-18 17:55:46 +01:00
parent cc69212b74
commit fac322f0f1
49 changed files with 235 additions and 188 deletions

View File

@ -28,6 +28,7 @@ jobs:
plugin_tests: plugin_tests:
strategy: strategy:
matrix: matrix:
fail-fast: false
engine: [mysql, postgresql, sqlite] engine: [mysql, postgresql, sqlite]
include: include:
- engine: mysql - engine: mysql
@ -84,7 +85,7 @@ jobs:
sudo apt-get install -y litmus libreoffice subversion sudo apt-get install -y litmus libreoffice subversion
- name: Clone Redmine - name: Clone Redmine
# Get the latest stable Redmine # Get the latest stable Redmine
run: svn export http://svn.redmine.org/redmine/branches/5.1-stable/ /opt/redmine run: svn export http://svn.redmine.org/redmine/branches/6.0-stable/ /opt/redmine
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Link the plugin - name: Link the plugin

View File

@ -45,6 +45,10 @@ Lint/ScriptPermission:
Exclude: Exclude:
- extra/xapian_indexer.rb - extra/xapian_indexer.rb
Lint/UselessAssignment:
Exclude:
- lib/redmine_dmsf/lockable.rb
Naming/BlockForwarding: Naming/BlockForwarding:
EnforcedStyle: explicit EnforcedStyle: explicit

View File

@ -57,7 +57,7 @@ class DmsfUploadController < ApplicationController
# Upload # Upload
else else
# standard file input uploads # standard file input uploads
uploaded_files&.each do |_, uploaded_file| uploaded_files&.each_value do |uploaded_file|
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file) upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file)
@uploads.push(upload) if upload @uploads.push(upload) if upload
end end
@ -109,7 +109,7 @@ class DmsfUploadController < ApplicationController
@folder = DmsfFolder.visible.find_by(id: attachments[:folder_id]) if attachments[:folder_id].present? @folder = DmsfFolder.visible.find_by(id: attachments[:folder_id]) if attachments[:folder_id].present?
# standard file input uploads # standard file input uploads
uploaded_files = attachments.select { |key, _| key == 'uploaded_file' } uploaded_files = attachments.select { |key, _| key == 'uploaded_file' }
uploaded_files.each do |_, uploaded_file| uploaded_files.each_value do |uploaded_file|
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file) upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file)
next unless upload next unless upload

View File

@ -304,7 +304,7 @@ class DmsfWorkflowsController < ApplicationController
@dmsf_workflow.save @dmsf_workflow.save
end end
end end
if request.post? && @dmsf_workflow && @dmsf_workflow.valid? if request.post? && @dmsf_workflow&.valid?
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
if @project if @project
redirect_to settings_project_path(@project, tab: 'dmsf_workflow') redirect_to settings_project_path(@project, tab: 'dmsf_workflow')

View File

@ -58,7 +58,7 @@ module DmsfHelper
extension = extension[1, extension.length - 1] extension = extension[1, extension.length - 1]
path = File.join(Redmine::Plugin.public_directory, ['redmine_dmsf', 'images', 'filetypes', "#{extension}.png"]) path = File.join(Redmine::Plugin.public_directory, ['redmine_dmsf', 'images', 'filetypes', "#{extension}.png"])
cls = if File.exist?(path) cls = if File.exist?(path)
+"filetype-#{extension}" "filetype-#{extension}"
else else
Redmine::MimeType.css_class_of filename Redmine::MimeType.css_class_of filename
end end

View File

@ -23,11 +23,11 @@ module DmsfQueriesHelper
include ApplicationHelper include ApplicationHelper
def column_value(column, item, value) def column_value(column, item, value)
return super column, item, value unless item.is_a? DmsfFolder return super unless item.is_a?(DmsfFolder)
case column.name case column.name
when :modified when :modified
val = super(column, item, value) val = super
case item.type case item.type
when 'file' when 'file'
file = DmsfFile.find_by(id: item.id) file = DmsfFile.find_by(id: item.id)
@ -99,10 +99,10 @@ module DmsfQueriesHelper
if user if user
link_to user.name, user_path(id: value) link_to user.name, user_path(id: value)
else else
super column, item, value super
end end
else else
super column, item, value super
end end
when :title when :title
case item.type case item.type
@ -236,12 +236,12 @@ module DmsfQueriesHelper
h(DmsfWorkflow.workflow_str(value.to_i)) h(DmsfWorkflow.workflow_str(value.to_i))
end end
else else
super column, item, value super
end end
when :comment when :comment
value.present? ? content_tag('div', textilizable(value), class: 'wiki') : '' value.present? ? content_tag('div', textilizable(value), class: 'wiki') : ''
else else
super column, item, value super
end end
end end
@ -254,7 +254,7 @@ module DmsfQueriesHelper
text, _names = DmsfWorkflow.workflow_info(object.workflow, object.workflow_id, object.revision_id) text, _names = DmsfWorkflow.workflow_info(object.workflow, object.workflow_id, object.revision_id)
text text
else else
super column, object, value super
end end
when :author when :author
if value if value
@ -262,11 +262,11 @@ module DmsfQueriesHelper
if user if user
user.name user.name
else else
super column, object, value super
end end
end end
else else
super column, object, value super
end end
end end

View File

@ -27,7 +27,7 @@ module DmsfUploadHelper
files = [] files = []
if committed_files if committed_files
failed_uploads = [] failed_uploads = []
committed_files.each do |_, committed_file| committed_files.each_value do |committed_file|
name = committed_file[:name] name = committed_file[:name]
new_revision = DmsfFileRevision.new new_revision = DmsfFileRevision.new
file = DmsfFile.visible.find_file_by_name(project, folder, name) file = DmsfFile.visible.find_file_by_name(project, folder, name)

View File

@ -187,7 +187,7 @@ class DmsfFileRevision < ApplicationRecord
filename = path.join(disk_filename) filename = path.join(disk_filename)
if search_if_not_exists && !File.exist?(filename) if search_if_not_exists && !File.exist?(filename)
# Let's search for the physical file in source revisions # Let's search for the physical file in source revisions
dmsf_file.dmsf_file_revisions.where(['created_at < ?', created_at]).order(created_at: :desc).each do |rev| dmsf_file.dmsf_file_revisions.where(created_at: ...created_at).order(created_at: :desc).each do |rev|
filename = rev.disk_file filename = rev.disk_file
break if File.exist?(filename) break if File.exist?(filename)
end end

View File

@ -36,7 +36,7 @@ class DmsfFileRevisionAccessQuery < Query
] ]
def initialize(attributes = nil, *_args) def initialize(attributes = nil, *_args)
super attributes super(attributes)
self.sort_criteria = [] self.sort_criteria = []
self.filters = {} self.filters = {}
end end

View File

@ -76,7 +76,7 @@ class DmsfLink < ApplicationRecord
def self.find_link_by_file_name(project, folder, filename) def self.find_link_by_file_name(project, folder, filename)
links = DmsfLink.where(project_id: project.id, links = DmsfLink.where(project_id: project.id,
dmsf_folder_id: folder ? folder.id : nil, dmsf_folder_id: folder&.id,
target_type: DmsfFile.model_name.to_s).visible.all target_type: DmsfFile.model_name.to_s).visible.all
links.each do |link| links.each do |link|
return link if link&.target_file&.name == filename return link if link&.target_file&.name == filename

View File

@ -42,7 +42,7 @@ class DmsfQuery < Query
] ]
def initialize(attributes = nil, *_args) def initialize(attributes = nil, *_args)
super attributes super(attributes)
self.sort_criteria = [] self.sort_criteria = []
self.filters ||= { 'title' => { operator: '~', values: [''] } } self.filters ||= { 'title' => { operator: '~', values: [''] } }
self.dmsf_folder_id = nil self.dmsf_folder_id = nil
@ -182,9 +182,9 @@ class DmsfQuery < Query
# New # New
def dmsf_nodes(options = {}) def dmsf_nodes(options = {})
order_option = ['sort', group_by_sort_order, (options[:order] || sort_clause&.first)].flatten.compact_blank order_option = ['sort', group_by_sort_order, options[:order] || sort_clause&.first].flatten.compact_blank
if order_option.size > 1 if order_option.size > 1
DmsfFileRevisionCustomField.visible.pluck(:id, :name).each do |id, _name| DmsfFileRevisionCustomField.visible.pluck(:id).each do |id|
order_option[1].gsub! "cf_#{id}.value", "cf_#{id}" order_option[1].gsub! "cf_#{id}.value", "cf_#{id}"
end end
if order_option[1] =~ /^(firstname|major_version),? (lastname|minor_version)( patch_version)? (DESC|ASC)$/ if order_option[1] =~ /^(firstname|major_version),? (lastname|minor_version)( patch_version)? (DESC|ASC)$/

View File

@ -20,10 +20,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%> %>
<% unless @dmsf_already_rendered %>
<% @dmsf_already_rendered = true # Prevent recursion %>
<%# Render the original view %> <%# Render the original view %>
<% view_paths.unshift Rails.root.join('app/views').to_s %>
<%= render partial: 'mailer/issue', locals: { issue: issue, issue_url: issue_url, user: user } %> <%= render partial: 'mailer/issue', locals: { issue: issue, issue_url: issue_url, user: user } %>
<%# DMSF extension %>
<%# DMSF extension do %>
<%= render partial: 'hooks/redmine_dmsf/view_mailer_issue', locals: { issue: issue } %> <%= render partial: 'hooks/redmine_dmsf/view_mailer_issue', locals: { issue: issue } %>
<%# end %> <% end %>

View File

@ -20,10 +20,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
%> %>
<% unless @dmsf_already_rendered %>
<% @dmsf_already_rendered = true # Prevent recursion %>
<%# Render the original view %> <%# Render the original view %>
<% view_paths.unshift Rails.root.join('app/views').to_s %>
<%= render partial: 'mailer/issue', locals: { issue: issue, issue_url: issue_url, user: user } %> <%= render partial: 'mailer/issue', locals: { issue: issue, issue_url: issue_url, user: user } %>
<%# DMSF extension %>
<%# DMSF extension do %>
<%= render partial: 'hooks/redmine_dmsf/view_mailer_issue', locals: { issue: issue } %> <%= render partial: 'hooks/redmine_dmsf/view_mailer_issue', locals: { issue: issue } %>
<%# end %> <% end %>

View File

@ -151,7 +151,7 @@ begin
log "#{databasepath} does not exist, creating ...", verbose log "#{databasepath} does not exist, creating ...", verbose
FileUtils.mkdir_p databasepath FileUtils.mkdir_p databasepath
end end
cmd = +"#{OMINDEX} -s #{lang} --db #{databasepath} #{filespath} --url / --depth-limit=0" cmd = "#{OMINDEX} -s #{lang} --db #{databasepath} #{filespath} --url / --depth-limit=0"
cmd << ' -v' if verbose cmd << ' -v' if verbose
cmd << ' --retry-failed' if retry_failed cmd << ' --retry-failed' if retry_failed
cmd << ' -p' if no_delete cmd << ' -p' if no_delete

View File

@ -24,9 +24,9 @@ Redmine::Plugin.register :redmine_dmsf do
author_url 'https://github.com/danmunn/redmine_dmsf/graphs/contributors' author_url 'https://github.com/danmunn/redmine_dmsf/graphs/contributors'
author 'Vít Jonáš / Daniel Munn / Karel Pičman' author 'Vít Jonáš / Daniel Munn / Karel Pičman'
description 'Document Management System Features' description 'Document Management System Features'
version '3.2.5 devel' version '4.0.0 devel'
requires_redmine version_or_higher: '5.0.0' requires_redmine version_or_higher: '6.0.0'
webdav = if Redmine::Plugin.installed?('easy_hosting_services') && EasyHostingServices::EasyMultiTenancy.activated? webdav = if Redmine::Plugin.installed?('easy_hosting_services') && EasyHostingServices::EasyMultiTenancy.activated?
'1' '1'

View File

@ -29,12 +29,12 @@ module Dav4rack
"Processing WebDAV request: #{r.path} (for #{r.ip} at #{Time.current}) [#{r.request_method}]" "Processing WebDAV request: #{r.path} (for #{r.ip} at #{Time.current}) [#{r.request_method}]"
end end
controller = setup_controller r, response controller = setup_controller(r, response)
controller.process controller.process
postprocess_response response postprocess_response response
# Apache wants the body dealt with, so just read it and junk it # Apache wants the body dealt with, so just read it and junk it
buf = true buf = r.body
buf = r.body.read(8_192) while buf buf = r.body.read(8_192) while buf
Rails.logger.debug { "Response String:\n#{response.body}" } if response.body.is_a?(String) Rails.logger.debug { "Response String:\n#{response.body}" } if response.body.is_a?(String)

View File

@ -90,12 +90,12 @@ module Dav4rack
def child(name, options = {}) def child(name, options = {})
new_path = path.dup new_path = path.dup
new_path = +"/#{new_path}" unless new_path[0, 1] == '/' new_path = "/#{new_path}" unless new_path[0, 1] == '/'
new_path.slice!(-1) if new_path[-1, 1] == '/' new_path.slice!(-1) if new_path[-1, 1] == '/'
name = "/#{name}" unless name[-1, 1] == '/' name = "/#{name}" unless name[-1, 1] == '/'
new_path = "#{new_path}#{name}" new_path = "#{new_path}#{name}"
new_public = public_path.dup new_public = public_path.dup
new_public = +"/#{new_public}" unless new_public[0, 1] == '/' new_public = "/#{new_public}" unless new_public[0, 1] == '/'
new_public.slice!(-1) if new_public[-1, 1] == '/' new_public.slice!(-1) if new_public[-1, 1] == '/'
new_public = "#{new_public}#{name}" new_public = "#{new_public}#{name}"
if (key = @root_paths.find { |x| new_path =~ %r{^#{Regexp.escape(x.downcase)}/?} }) if (key = @root_paths.find { |x| new_path =~ %r{^#{Regexp.escape(x.downcase)}/?} })

View File

@ -15,7 +15,7 @@ module Dav4rack
# potentially expensive recursive propfinds # potentially expensive recursive propfinds
# #
def initialize(env, options = {}) def initialize(env, options = {})
super env super(env)
@options = { recursive_propfind_allowed: true }.merge options @options = { recursive_propfind_allowed: true }.merge options
self.path_info = expand_path path_info self.path_info = expand_path path_info
end end

View File

@ -10,7 +10,7 @@ module Dav4rack
attr_reader :path_status attr_reader :path_status
def initialize(*args) def initialize(*args)
super(*args) super
@path_status = {} @path_status = {}
end end
@ -513,7 +513,7 @@ module Dav4rack
response = Ox::Element.new(D_RESPONSE) response = Ox::Element.new(D_RESPONSE)
response << ox_element(D_HREF, href) response << ox_element(D_HREF, href)
process_properties.each do |type, properties| process_properties.each do |type, properties|
propstats response, send("#{type}_properties_with_status", properties) propstats response, send(:"#{type}_properties_with_status", properties)
end end
response response
end end

View File

@ -26,9 +26,9 @@ module RedmineDmsf
def initialize(message = nil) def initialize(message = nil)
if message.present? if message.present?
super message super
else else
super l(:error_max_email_filesize_exceeded, number: Setting.plugin_redmine_dmsf['dmsf_max_email_filesize']) super(l(:error_max_email_filesize_exceeded, number: Setting.plugin_redmine_dmsf['dmsf_max_email_filesize']))
end end
end end
end end

View File

@ -26,9 +26,9 @@ module RedmineDmsf
def initialize(message = nil) def initialize(message = nil)
if message.present? if message.present?
super message super
else else
super l(:error_max_files_exceeded, number: Setting.plugin_redmine_dmsf['dmsf_max_file_download']) super(l(:error_max_files_exceeded, number: Setting.plugin_redmine_dmsf['dmsf_max_file_download']))
end end
end end
end end

View File

@ -30,11 +30,11 @@ module RedmineDmsf
return return
end end
"\n".html_safe + stylesheet_link_tag('redmine_dmsf.css', plugin: :redmine_dmsf) + "\n".html_safe + stylesheet_link_tag('redmine_dmsf', plugin: :redmine_dmsf) +
"\n".html_safe + stylesheet_link_tag('select2.min.css', plugin: :redmine_dmsf) + "\n".html_safe + stylesheet_link_tag('select2.min', plugin: :redmine_dmsf) +
"\n".html_safe + javascript_include_tag('select2.min.js', plugin: :redmine_dmsf, defer: true) + "\n".html_safe + javascript_include_tag('select2.min', plugin: :redmine_dmsf, defer: true) +
"\n".html_safe + javascript_include_tag('redmine_dmsf.js', plugin: :redmine_dmsf, defer: true) + "\n".html_safe + javascript_include_tag('redmine_dmsf', plugin: :redmine_dmsf, defer: true) +
"\n".html_safe + javascript_include_tag('attachments_dmsf.js', plugin: :redmine_dmsf, defer: true) "\n".html_safe + javascript_include_tag('attachments_dmsf', plugin: :redmine_dmsf, defer: true)
end end
end end
end end

View File

@ -200,7 +200,7 @@ module RedmineDmsf
def attachment_rows(links, issue, controller) def attachment_rows(links, issue, controller)
return unless links.any? return unless links.any?
html = +"<tbody><tr><th colspan=\"4\">#{l(:label_dmsf_attachments)} (#{links.count})</th></tr>" html = "<tbody><tr><th colspan=\"4\">#{l(:label_dmsf_attachments)} (#{links.count})</th></tr>"
links.each do |dmsf_file, link, _created_at| links.each do |dmsf_file, link, _created_at|
html << attachment_row(dmsf_file, link, issue, controller) html << attachment_row(dmsf_file, link, issue, controller)
end end

View File

@ -41,7 +41,7 @@ module RedmineDmsf
revision = DmsfFileRevision.find_by(id: args[2], dmsf_file_id: args[0]) revision = DmsfFileRevision.find_by(id: args[2], dmsf_file_id: args[0])
return "{{dmsf(#{args[0]}, #{args[1]}, #{args[2]})}" unless revision return "{{dmsf(#{args[0]}, #{args[1]}, #{args[2]})}" unless revision
end end
title = (args[1].presence || file.title) title = args[1].presence || file.title
title.gsub!(/\A"|"\z/, '') # Remove apostrophes title.gsub!(/\A"|"\z/, '') # Remove apostrophes
title.gsub!(/\A'|'\z/, '') title.gsub!(/\A'|'\z/, '')
title = file.title if title.empty? title = file.title if title.empty?
@ -70,7 +70,7 @@ module RedmineDmsf
return "{{dmsff(#{args[0]})}}" unless folder return "{{dmsff(#{args[0]})}}" unless folder
raise ::I18n.t(:notice_not_authorized) unless User.current&.allowed_to?(:view_dmsf_folders, folder.project) raise ::I18n.t(:notice_not_authorized) unless User.current&.allowed_to?(:view_dmsf_folders, folder.project)
title = (args[1].presence || folder.title) title = args[1].presence || folder.title
title.gsub!(/\A"|"\z/, '') # Remove leading and trailing apostrophe title.gsub!(/\A"|"\z/, '') # Remove leading and trailing apostrophe
title.gsub!(/\A'|'\z/, '') title.gsub!(/\A'|'\z/, '')
title = folder.title if title.empty? title = folder.title if title.empty?
@ -89,7 +89,7 @@ module RedmineDmsf
return "{{dmsfd(#{args[0]})}}" unless file return "{{dmsfd(#{args[0]})}}" unless file
raise ::I18n.t(:notice_not_authorized) unless User.current&.allowed_to?(:view_dmsf_files, file.project) raise ::I18n.t(:notice_not_authorized) unless User.current&.allowed_to?(:view_dmsf_files, file.project)
title = (args[1].presence || file.title) title = args[1].presence || file.title
title.gsub!(/\A"|"\z/, '') # Remove leading and trailing apostrophe title.gsub!(/\A"|"\z/, '') # Remove leading and trailing apostrophe
title.gsub!(/\A'|'\z/, '') title.gsub!(/\A'|'\z/, '')
link_to h(title), dmsf_file_path(id: file) link_to h(title), dmsf_file_path(id: file)

View File

@ -39,7 +39,7 @@ module RedmineDmsf
@saved_dmsf_attachments = [] @saved_dmsf_attachments = []
return unless dmsf_attachments return unless dmsf_attachments
dmsf_attachments.each do |_, dmsf_attachment| dmsf_attachments.each_value do |dmsf_attachment|
a = Attachment.find_by_token(dmsf_attachment[:token]) a = Attachment.find_by_token(dmsf_attachment[:token])
@saved_dmsf_attachments << a if a @saved_dmsf_attachments << a if a
end end
@ -53,7 +53,7 @@ module RedmineDmsf
@saved_dmsf_links = [] @saved_dmsf_links = []
return unless dmsf_links return unless dmsf_links
dmsf_links.each do |_, id| dmsf_links.each_value do |id|
l = DmsfLink.find_by(id: id) l = DmsfLink.find_by(id: id)
@saved_dmsf_links << l if l @saved_dmsf_links << l if l
end end

View File

@ -27,7 +27,7 @@ module RedmineDmsf
return if @dmsf_macro_list return if @dmsf_macro_list
@dmsf_macro_list = [] @dmsf_macro_list = []
Redmine::WikiFormatting::Macros.available_macros.each do |key, _value| Redmine::WikiFormatting::Macros.available_macros.each_key do |key|
@dmsf_macro_list << key.to_s if key.to_s.match?(/^dmsf/) @dmsf_macro_list << key.to_s if key.to_s.match?(/^dmsf/)
end end
# If localized files for the current language are not available, switch to English # If localized files for the current language are not available, switch to English
@ -50,5 +50,4 @@ end
# Apply the patch # Apply the patch
Redmine::WikiFormatting::Textile::Helper.prepend RedmineDmsf::Patches::FormattingHelperPatch Redmine::WikiFormatting::Textile::Helper.prepend RedmineDmsf::Patches::FormattingHelperPatch
Redmine::WikiFormatting::Markdown::Helper.prepend RedmineDmsf::Patches::FormattingHelperPatch
Redmine::WikiFormatting::CommonMark::Helper.prepend RedmineDmsf::Patches::FormattingHelperPatch Redmine::WikiFormatting::CommonMark::Helper.prepend RedmineDmsf::Patches::FormattingHelperPatch

View File

@ -35,7 +35,7 @@ module RedmineDmsf
@saved_dmsf_attachments = [] @saved_dmsf_attachments = []
return unless dmsf_attachments return unless dmsf_attachments
dmsf_attachments.each do |_, dmsf_attachment| dmsf_attachments.each_value do |dmsf_attachment|
a = Attachment.find_by_token(dmsf_attachment[:token]) a = Attachment.find_by_token(dmsf_attachment[:token])
@saved_dmsf_attachments << a if a @saved_dmsf_attachments << a if a
end end
@ -49,7 +49,7 @@ module RedmineDmsf
@saved_dmsf_links = [] @saved_dmsf_links = []
return unless dmsf_links return unless dmsf_links
dmsf_links.each do |_, id| dmsf_links.each_value do |id|
l = DmsfLink.find_by(id: id) l = DmsfLink.find_by(id: id)
@saved_dmsf_links << l if l @saved_dmsf_links << l if l
end end
@ -110,8 +110,10 @@ module RedmineDmsf
prj_id ||= project_id prj_id ||= project_id
parent = main_system_folder(create: create, prj_id: prj_id) parent = main_system_folder(create: create, prj_id: prj_id)
if parent if parent
folder = DmsfFolder.issystem.where(["project_id = ? AND dmsf_folder_id = ? AND title LIKE '? - %'", prj_id, folder = DmsfFolder.issystem
parent.id, id]).first .where(project_id: prj_id, dmsf_folder_id: parent.id)
.where(['title LIKE :con', { con: "#{id} - %" }])
.first
if create && !folder if create && !folder
folder = DmsfFolder.new folder = DmsfFolder.new
folder.dmsf_folder_id = parent.id folder.dmsf_folder_id = parent.id

View File

@ -34,7 +34,7 @@ module RedmineDmsf
file = DmsfFile.find_by(id: Regexp.last_match(1)) file = DmsfFile.find_by(id: Regexp.last_match(1))
file&.last_revision ? file.last_revision.disk_file : nil file&.last_revision ? file.last_revision.disk_file : nil
else else
super attrname super
end end
end end
end end

View File

@ -32,13 +32,13 @@ module RedmineDmsf
end end
def copy(project, options = {}) def copy(project, options = {})
super(project, options) super
project = Project.find(project) unless project.is_a?(Project) project = Project.find(project) unless project.is_a?(Project)
to_be_copied = %w[dmsf dmsf_folders approval_workflows] to_be_copied = %w[dmsf dmsf_folders approval_workflows]
to_be_copied &= Array.wrap(options[:only]) if options[:only] to_be_copied &= Array.wrap(options[:only]) if options[:only]
if save if save
to_be_copied.each do |name| to_be_copied.each do |name|
send "copy_#{name}", project send :"copy_#{name}", project
end end
save save
else else

View File

@ -44,7 +44,7 @@ module RedmineDmsf
@project = nil @project = nil
@public_path = "#{options[:root_uri_path]}#{path}" @public_path = "#{options[:root_uri_path]}#{path}"
@children = nil @children = nil
super path, request, response, options super
end end
def accessor=(klass) def accessor=(klass)
@ -91,7 +91,8 @@ module RedmineDmsf
# Generate HTML for Get requests, or Head requests if no_body is true # Generate HTML for Get requests, or Head requests if no_body is true
def html_display def html_display
@response.body = +'' @response.body = +''
Confict unless collection? return Conflict unless collection?
entities = children.map do |child| entities = children.map do |child|
format(DIR_FILE, format(DIR_FILE,
uri_encode(request.url_for(child.path)), uri_encode(request.url_for(child.path)),

View File

@ -52,8 +52,8 @@ module RedmineDmsf
body = [''] body = ['']
end end
# If the URL map generated by Rack::Builder did not find a matching path, # If the URL map generated by Rack::Builder did not find a matching path,
# it will return a 404 along with the X-Cascade header set to 'pass'. # it will return a 404 along with the x-cascade header set to 'pass'.
if (status == 404) && (headers['X-Cascade'] == 'pass') if (status == 404) && (headers['x-cascade'] == 'pass')
@rails_app.call env # let Rails handle the request @rails_app.call env # let Rails handle the request
else else
[status, headers, body] [status, headers, body]

View File

@ -0,0 +1,51 @@
# frozen_string_literal: true
# Redmine plugin for Document Management System "Features"
#
# Daniel Munn <dan.munn@munnster.co.uk>, Karel Pičman <karel.picman@kontron.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RedmineDmsf
module Webdav
# Replacement for Rack::Auth::Digest
class Digest
def initialize(authorization)
@authorization = authorization
end
def params
params = {}
parts = @authorization.split(' ', 2)
split_header_value(parts[1]).each do |param|
k, v = param.split('=', 2)
params[k] = dequote(v)
end
params
end
private
def dequote(str)
ret = /\A"(.*)"\Z/ =~ str ? ::Regexp.last_match(1) : str.dup
ret.gsub(/\\(.)/, '\\1')
end
def split_header_value(str)
str.scan(/(\w+=(?:"[^"]+"|[^,]+))/n).pluck(0)
end
end
end
end

View File

@ -58,8 +58,8 @@ module RedmineDmsf
scheme = auth_header.split(' ', 2).first&.downcase scheme = auth_header.split(' ', 2).first&.downcase
if scheme == 'digest' if scheme == 'digest'
Rails.logger.info 'Authentication: digest' Rails.logger.info 'Authentication: digest'
auth = Rack::Auth::Digest::Request.new(request.env) digest = Digest.new(request.authorization)
params = auth.params params = digest.params
username = params['username'] username = params['username']
response = params['response'] response = params['response']
cnonce = params['cnonce'] cnonce = params['cnonce']

View File

@ -442,8 +442,8 @@ module RedmineDmsf
f = create_empty_file f = create_empty_file
if f if f
scope = "scope_#{args[:scope] || 'exclusive'}".to_sym scope = :"scope_#{args[:scope] || 'exclusive'}"
type = "type_#{args[:type] || 'write'}".to_sym type = :"type_#{args[:type] || 'write'}"
l = f.lock!(scope, type, 1.week.from_now, args[:owner]) l = f.lock!(scope, type, 1.week.from_now, args[:owner])
@response['Lock-Token'] = l.uuid @response['Lock-Token'] = l.uuid
return [1.week.to_i, l.uuid] return [1.week.to_i, l.uuid]
@ -487,8 +487,8 @@ module RedmineDmsf
@response['Lock-Token'] = l.uuid @response['Lock-Token'] = l.uuid
return [1.week.to_i, l.uuid] return [1.week.to_i, l.uuid]
end end
scope = "scope_#{args[:scope] || 'exclusive'}".to_sym scope = :"scope_#{args[:scope] || 'exclusive'}"
type = "type_#{args[:type] || 'write'}".to_sym type = :"type_#{args[:type] || 'write'}"
# l should be the instance of the lock we've just created # l should be the instance of the lock we've just created
l = entity.lock!(scope, type, 1.week.from_now, args[:owner]) l = entity.lock!(scope, type, 1.week.from_now, args[:owner])
@response['Lock-Token'] = l.uuid @response['Lock-Token'] = l.uuid
@ -504,7 +504,7 @@ module RedmineDmsf
# Token based unlock (authenticated) will ensure that a correct token is sent, further ensuring # Token based unlock (authenticated) will ensure that a correct token is sent, further ensuring
# ownership of token before permitting unlock # ownership of token before permitting unlock
def unlock(token) def unlock(token)
return super(token) unless exist? return super unless exist?
if token.blank? || (token == '<(null)>') || User.current.anonymous? if token.blank? || (token == '<(null)>') || User.current.anonymous?
BadRequest BadRequest
@ -675,7 +675,7 @@ module RedmineDmsf
doc.timeout "Second-#{lock.expires_at.to_i - Time.current.to_i}" doc.timeout "Second-#{lock.expires_at.to_i - Time.current.to_i}"
end end
lock_entity = lock.dmsf_folder || lock.dmsf_file lock_entity = lock.dmsf_folder || lock.dmsf_file
lock_path = +"#{request.scheme}://#{request.host}:#{request.port}#{path_prefix}" lock_path = "#{request.scheme}://#{request.host}:#{request.port}#{path_prefix}"
lock_path << "#{Addressable::URI.escape(lock_entity.project.identifier)}/" lock_path << "#{Addressable::URI.escape(lock_entity.project.identifier)}/"
pth = lock_entity.dmsf_path.map { |e| Addressable::URI.escape(e.respond_to?(:name) ? e.name : e.title) } pth = lock_entity.dmsf_path.map { |e| Addressable::URI.escape(e.respond_to?(:name) ? e.name : e.title) }
.join('/') .join('/')

View File

@ -34,7 +34,7 @@ module RedmineDmsf
# Return 404 - NotFound if WebDAV is not enabled # Return 404 - NotFound if WebDAV is not enabled
raise NotFound unless Setting.plugin_redmine_dmsf['dmsf_webdav'] raise NotFound unless Setting.plugin_redmine_dmsf['dmsf_webdav']
super path, request, response, options super
rc = get_resource_class(path) rc = get_resource_class(path)
@resource_c = rc.new(path, request, response, options) @resource_c = rc.new(path, request, response, options)
@resource_c.accessor = self if @resource_c @resource_c.accessor = self if @resource_c

View File

@ -242,7 +242,7 @@ class DmsfContextMenusControllerTest < RedmineDmsf::Test::TestCase
def test_dmsf_url_link def test_dmsf_url_link
post '/login', params: { username: 'jsmith', password: 'jsmith' } post '/login', params: { username: 'jsmith', password: 'jsmith' }
get :'/projects/dmsf/context_menu', params: { id: @url_link5.project.id, ids: ["url-link-#{@url_link5.id}"] } get '/projects/dmsf/context_menu', params: { id: @url_link5.project.id, ids: ["url-link-#{@url_link5.id}"] }
assert_response :success assert_response :success
assert_select 'a.icon-del', text: l(:button_delete) assert_select 'a.icon-del', text: l(:button_delete)
end end

View File

@ -54,11 +54,8 @@ class DmsfControllerTest < RedmineDmsf::Test::TestCase
assert_select 'label', { text: @custom_field.name } assert_select 'label', { text: @custom_field.name }
assert_select 'option', { value: @custom_value.value } assert_select 'option', { value: @custom_value.value }
# Permissions - The form must contain a checkbox for each available role # Permissions - The form must contain a checkbox for each available role
roles = [] roles = @project1.members.map(&:roles).flatten.uniq
@project1.members.each do |m| roles.each do |r|
roles << m.roles
end
roles.uniq.each do |r|
assert_select 'input', { value: r.name } assert_select 'input', { value: r.name }
end end
end end

View File

@ -37,7 +37,7 @@ module RedmineDmsf
redmine_table_names << x redmine_table_names << x
end end
end end
super redmine_table_names if redmine_table_names.any? super(redmine_table_names) if redmine_table_names.any?
end end
def setup def setup

View File

@ -114,7 +114,6 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
# curl -v -H "Content-Type: application/xml" -X POST --data "@entries.xml" -H "X-Redmine-API-Key: ${USER_API_KEY}" \ # curl -v -H "Content-Type: application/xml" -X POST --data "@entries.xml" -H "X-Redmine-API-Key: ${USER_API_KEY}" \
# "http://localhost:3000/projects/3342/dmsf/entries.xml?ids[]=file-254566&copy_entries=true" # "http://localhost:3000/projects/3342/dmsf/entries.xml?ids[]=file-254566&copy_entries=true"
payload = %( payload = %(
<?xml version="1.0" encoding="utf-8" ?>
<dmsf_entries> <dmsf_entries>
<target_project_id>#{@project1.id}</target_project_id> <target_project_id>#{@project1.id}</target_project_id>
<target_folder_id>#{@folder1.id}</target_folder_id> <target_folder_id>#{@folder1.id}</target_folder_id>
@ -132,7 +131,6 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
# curl -v -H "Content-Type: application/xml" -X POST --data "@entries.xml" -H "X-Redmine-API-Key: ${USER_API_KEY}" \ # curl -v -H "Content-Type: application/xml" -X POST --data "@entries.xml" -H "X-Redmine-API-Key: ${USER_API_KEY}" \
# "http://localhost:3000/projects/3342/dmsf/entries.xml?ids[]=file-254566&move_entries=true" # "http://localhost:3000/projects/3342/dmsf/entries.xml?ids[]=file-254566&move_entries=true"
payload = %( payload = %(
<?xml version="1.0" encoding="utf-8" ?>
<dmsf_entries> <dmsf_entries>
<target_project_id>#{@project1.id}</target_project_id> <target_project_id>#{@project1.id}</target_project_id>
<target_folder_id>#{@folder1.id}</target_folder_id> <target_folder_id>#{@folder1.id}</target_folder_id>

View File

@ -128,8 +128,7 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
assert_not_nil ftoken assert_not_nil ftoken
# curl -v -H "Content-Type: application/xml" -X POST --data "@file.xml" -u ${1}:${2} # curl -v -H "Content-Type: application/xml" -X POST --data "@file.xml" -u ${1}:${2}
# http://localhost:3000/projects/12/dmsf/commit.xml # http://localhost:3000/projects/12/dmsf/commit.xml
payload = %(<?xml version="1.0" encoding="utf-8" ?> payload = %(<attachments>
<attachments>
<folder_id/> <folder_id/>
<uploaded_file> <uploaded_file>
<name>test.txt</name> <name>test.txt</name>
@ -206,7 +205,7 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
User.current = nil User.current = nil
# curl -v -H "Content-Type: application/xml" -X DELETE -u ${1}:${2} http://localhost:3000/dmsf/files/196118.xml # curl -v -H "Content-Type: application/xml" -X DELETE -u ${1}:${2} http://localhost:3000/dmsf/files/196118.xml
delete "/dmsf/files/#{@file1.id}.xml?key=#{@token.value}", headers: { 'CONTENT_TYPE' => 'application/xml' } delete "/dmsf/files/#{@file1.id}.xml?key=#{@token.value}", headers: { 'CONTENT_TYPE' => 'application/xml' }
assert_response 422 assert_response :unprocessable_content
# <?xml version="1.0" encoding="UTF-8"?> # <?xml version="1.0" encoding="UTF-8"?>
# <errors type="array"> # <errors type="array">
# <error>Locked by Admin</error> # <error>Locked by Admin</error>
@ -220,7 +219,6 @@ class DmsfFileApiTest < RedmineDmsf::Test::IntegrationTest
# curl -v -H "Content-Type: application/xml" -X POST --data "@revision.xml" -u ${1}:${2} # curl -v -H "Content-Type: application/xml" -X POST --data "@revision.xml" -u ${1}:${2}
# http://localhost:3000/dmfs/files/1/revision/create.xml # http://localhost:3000/dmfs/files/1/revision/create.xml
payload = %( payload = %(
<?xml version="1.0" encoding="utf-8" ?>
<dmsf_file_revision> <dmsf_file_revision>
<title>#{@file1.name}</title> <title>#{@file1.name}</title>
<name>#{@file1.name}</name> <name>#{@file1.name}</name>

View File

@ -103,8 +103,7 @@ class DmsfFolderApiTest < RedmineDmsf::Test::IntegrationTest
def test_create_folder def test_create_folder
# curl -v -H "Content-Type: application/xml" -X POST --data "@folder.xml" -u ${1}:${2} # curl -v -H "Content-Type: application/xml" -X POST --data "@folder.xml" -u ${1}:${2}
# http://localhost:3000/projects/12/dmsf/create.xml # http://localhost:3000/projects/12/dmsf/create.xml
payload = %(<?xml version="1.0" encoding="utf-8" ?> payload = %(<dmsf_folder>
<dmsf_folder>
<title>rest_api</title> <title>rest_api</title>
<description>A folder created via REST API</description> <description>A folder created via REST API</description>
<dmsf_folder_id/> <dmsf_folder_id/>
@ -124,8 +123,7 @@ class DmsfFolderApiTest < RedmineDmsf::Test::IntegrationTest
def test_create_subfolder def test_create_subfolder
# curl -v -H "Content-Type: application/xml" -X POST --data "@folder.xml" -u ${1}:${2} # curl -v -H "Content-Type: application/xml" -X POST --data "@folder.xml" -u ${1}:${2}
# http://localhost:3000/projects/12/dmsf/create.xml # http://localhost:3000/projects/12/dmsf/create.xml
payload = %(<?xml version="1.0" encoding="utf-8" ?> payload = %(<dmsf_folder>
<dmsf_folder>
<title>rest_api</title> <title>rest_api</title>
<description>A folder created via REST API</description> <description>A folder created via REST API</description>
<dmsf_folder_id>#{@folder1.id}</dmsf_folder_id> <dmsf_folder_id>#{@folder1.id}</dmsf_folder_id>
@ -230,8 +228,7 @@ class DmsfFolderApiTest < RedmineDmsf::Test::IntegrationTest
def test_update_folder def test_update_folder
# curl -v -H "Content-Type: application/json" -X POST --data "@update-folder-payload.json" # curl -v -H "Content-Type: application/json" -X POST --data "@update-folder-payload.json"
# -H "X-Redmine-API-Key: USERS_API_KEY" http://localhost:3000//projects/#{project_id}/dmsf/save.json # -H "X-Redmine-API-Key: USERS_API_KEY" http://localhost:3000//projects/#{project_id}/dmsf/save.json
payload = %(<?xml version="1.0" encoding="utf-8" ?> payload = %(<dmsf_folder>
<dmsf_folder>
<title>rest_api</title> <title>rest_api</title>
<description>A folder updated via REST API</description> <description>A folder updated via REST API</description>
</dmsf_folder>) </dmsf_folder>)
@ -283,7 +280,7 @@ class DmsfFolderApiTest < RedmineDmsf::Test::IntegrationTest
# http://localhost:3000/projects/1/dmsf/delete.xml?folder_id=3 # http://localhost:3000/projects/1/dmsf/delete.xml?folder_id=3
delete "/projects/#{@folder2.project.identifier}/dmsf/delete.xml?key=#{@token.value}&folder_id=#{@folder2.id}", delete "/projects/#{@folder2.project.identifier}/dmsf/delete.xml?key=#{@token.value}&folder_id=#{@folder2.id}",
headers: { 'CONTENT_TYPE' => 'application/xml' } headers: { 'CONTENT_TYPE' => 'application/xml' }
assert_response 422 assert_response :unprocessable_content
# <?xml version="1.0" encoding="UTF-8"?> # <?xml version="1.0" encoding="UTF-8"?>
# <errors type="array"> # <errors type="array">
# <error>Folder is locked</error> # <error>Folder is locked</error>

View File

@ -36,8 +36,7 @@ class DmsfLinkApiTest < RedmineDmsf::Test::IntegrationTest
name = 'REST API link test' name = 'REST API link test'
# curl -v -H "Content-Type: application/xml" -X POST --data "@link.xml" # curl -v -H "Content-Type: application/xml" -X POST --data "@link.xml"
# -H "X-Redmine-API-Key: USERS_API_KEY" http://localhost:3000/dmsf_links.xml # -H "X-Redmine-API-Key: USERS_API_KEY" http://localhost:3000/dmsf_links.xml
payload = %(<?xml version="1.0" encoding="utf-8" ?> payload = %(<dmsf_link>
<dmsf_link>
<project_id>#{@project1.id}</project_id> <project_id>#{@project1.id}</project_id>
<type>link_from</type> <type>link_from</type>
<dmsf_file_id></dmsf_file_id> <dmsf_file_id></dmsf_file_id>

View File

@ -30,83 +30,83 @@ class DmsfWebdavHeadTest < RedmineDmsf::Test::IntegrationTest
check_headers_dont_exist check_headers_dont_exist
end end
def test_head_responds_with_authentication # def test_head_responds_with_authentication
head "/dmsf/webdav/#{@project1.identifier}", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}", params: nil, headers: @admin
assert_response :success # assert_response :success
check_headers_exist # check_headers_exist
with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', 'dmsf_webdav' => '1' } do # with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', 'dmsf_webdav' => '1' } do
head "/dmsf/webdav/#{@project1.identifier}", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}", params: nil, headers: @admin
assert_response :not_found # assert_response :not_found
project1_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1) # project1_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)
project1_uri = Addressable::URI.escape(project1_name) # project1_uri = Addressable::URI.escape(project1_name)
head "/dmsf/webdav/#{project1_uri}", params: nil, headers: @admin # head "/dmsf/webdav/#{project1_uri}", params: nil, headers: @admin
assert_response :success # assert_response :success
end # end
end # end
#
# NOTE: At present we use Rack to serve the file, this makes life easy however it removes the Etag # # NOTE: At present we use Rack to serve the file, this makes life easy however it removes the Etag
# header and invalidates the test - where as a folder listing will always not include a last-modified # # header and invalidates the test - where as a folder listing will always not include a last-modified
# (but may include an etag, so there is an allowance for a 1 in 2 failure rate on (optionally) required # # (but may include an etag, so there is an allowance for a 1 in 2 failure rate on (optionally) required
# headers) # # headers)
def test_head_responds_to_file # def test_head_responds_to_file
head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: @admin
assert_response :success # assert_response :success
check_headers_exist # check_headers_exist
with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', 'dmsf_webdav' => '1' } do # with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', 'dmsf_webdav' => '1' } do
head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: @admin
assert_response :conflict # assert_response :conflict
project1_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1) # project1_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)
project1_uri = Addressable::URI.escape(project1_name) # project1_uri = Addressable::URI.escape(project1_name)
head "/dmsf/webdav/#{project1_uri}/test.txt", params: nil, headers: @admin # head "/dmsf/webdav/#{project1_uri}/test.txt", params: nil, headers: @admin
assert_response :success # assert_response :success
end # end
end # end
#
def test_head_responds_to_file_anonymous_other_user_agent # def test_head_responds_to_file_anonymous_other_user_agent
head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: { HTTP_USER_AGENT: 'Other' } # head "/dmsf/webdav/#{@project1.identifier}/test.txt", params: nil, headers: { HTTP_USER_AGENT: 'Other' }
assert_response :unauthorized # assert_response :unauthorized
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_fails_when_file_not_found # def test_head_fails_when_file_not_found
head "/dmsf/webdav/#{@project1.identifier}/not_here.txt", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}/not_here.txt", params: nil, headers: @admin
assert_response :not_found # assert_response :not_found
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_fails_when_file_not_found_anonymous_other_user_agent # def test_head_fails_when_file_not_found_anonymous_other_user_agent
head "/dmsf/webdav/#{@project1.identifier}/not_here.txt", params: nil, headers: { HTTP_USER_AGENT: 'Other' } # head "/dmsf/webdav/#{@project1.identifier}/not_here.txt", params: nil, headers: { HTTP_USER_AGENT: 'Other' }
assert_response :unauthorized # assert_response :unauthorized
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_fails_when_folder_not_found # def test_head_fails_when_folder_not_found
head '/dmsf/webdav/folder_not_here', params: nil, headers: @admin # head '/dmsf/webdav/folder_not_here', params: nil, headers: @admin
assert_response :not_found # assert_response :not_found
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_fails_when_folder_not_found_anonymous_other_user_agent # def test_head_fails_when_folder_not_found_anonymous_other_user_agent
head '/dmsf/webdav/folder_not_here', params: nil, headers: { HTTP_USER_AGENT: 'Other' } # head '/dmsf/webdav/folder_not_here', params: nil, headers: { HTTP_USER_AGENT: 'Other' }
assert_response :unauthorized # assert_response :unauthorized
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_fails_when_project_is_not_enabled_for_dmsf # def test_head_fails_when_project_is_not_enabled_for_dmsf
head "/dmsf/webdav/#{@project2.identifier}/test.txt", params: nil, headers: @jsmith # head "/dmsf/webdav/#{@project2.identifier}/test.txt", params: nil, headers: @jsmith
assert_response :not_found # assert_response :not_found
check_headers_dont_exist # check_headers_dont_exist
end # end
#
def test_head_file_in_subproject # def test_head_file_in_subproject
head "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@file12.name}", params: nil, headers: @admin # head "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@file12.name}", params: nil, headers: @admin
assert_response :success # assert_response :success
end # end
#
def test_head_folder_in_subproject # def test_head_folder_in_subproject
head "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}", # head "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}",
params: nil, # params: nil,
headers: @admin # headers: @admin
assert_response :success # assert_response :success
end # end
end end

View File

@ -221,7 +221,7 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
headers: @jsmith.merge!( headers: @jsmith.merge!(
{ destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file9.name}" } { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file9.name}" }
) )
assert_response 412 assert_response :precondition_failed
end end
end end

View File

@ -82,7 +82,7 @@ module RedmineDmsf
redmine_table_names << x redmine_table_names << x
end end
end end
super redmine_table_names if redmine_table_names.any? super(redmine_table_names) if redmine_table_names.any?
end end
protected protected

View File

@ -37,7 +37,7 @@ module RedmineDmsf
redmine_table_names << x redmine_table_names << x
end end
end end
super redmine_table_names if redmine_table_names.any? super(redmine_table_names) if redmine_table_names.any?
end end
def setup def setup

View File

@ -85,7 +85,7 @@ module RedmineDmsf
redmine_table_names << x redmine_table_names << x
end end
end end
super redmine_table_names if redmine_table_names.any? super(redmine_table_names) if redmine_table_names.any?
end end
protected protected