This commit is contained in:
karel.picman@lbcfree.net 2020-08-07 16:16:15 +02:00
parent 2744f72b7f
commit fbba8fd22c
13 changed files with 375 additions and 80 deletions

View File

@ -31,9 +31,7 @@ module RedmineDmsf
attr_reader :public_path attr_reader :public_path
def initialize(path, request, response, options) def initialize(path, request, response, options)
if Setting.plugin_redmine_dmsf['dmsf_webdav'].blank? raise NotFound if Setting.plugin_redmine_dmsf['dmsf_webdav'].blank?
raise NotFound
end
@project = nil @project = nil
@public_path = "#{options[:root_uri_path]}#{path}" @public_path = "#{options[:root_uri_path]}#{path}"
@children = nil @children = nil
@ -122,13 +120,17 @@ module RedmineDmsf
def project def project
unless @project unless @project
i = 1 i = 1
project_names = Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names']
while true while true
pinfo = @path.split('/').drop(i) pinfo = @path.split('/').drop(i)
if pinfo.length > 0 if pinfo.length > 0
if Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] if project_names
if pinfo.first =~ /(\d+)$/ if pinfo.first =~ / (\d+)$/
prj = Project.visible.find_by(id: $1) prj = Project.visible.find_by(id: $1)
Rails.logger.error("No project found on path '#{@path}'") unless prj if prj
# Check again whether it's really the project and not a folder with a number as a suffix
prj = nil unless pinfo.first =~ /^#{prj.name}/
end
end end
else else
begin begin
@ -140,7 +142,10 @@ module RedmineDmsf
end end
end end
end end
break unless prj unless prj
@projectless_path = '/' + @path.split('/').drop(i).join('/')
break
end
i = i + 1 i = i + 1
@project = prj @project = prj
prj = nil prj = nil
@ -151,8 +156,8 @@ module RedmineDmsf
# Make it easy to find the path without project in it. # Make it easy to find the path without project in it.
def projectless_path def projectless_path
# TODO: project # Initialization
'/' + @path.split('/').drop(2).join('/') @projectless_path
end end
def path_prefix def path_prefix

View File

@ -107,18 +107,23 @@ module RedmineDmsf
def subproject def subproject
unless @subproject unless @subproject
@subproject = Project.visible.where(parent_id: parent_project.id, name: basename).first if parent_project if Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names']
if basename =~ / (\d+)$/
@subproject = Project.visible.where(id: $1, parent_id: parent_project.id).first
if @subproject
# Check again whether it's really the project and not a folder with a number as a suffix
@subproject = nil unless basename =~ /^#{@subproject.name}/
end
end
else
@subproject = Project.visible.where(parent_id: parent_project.id, identifier: basename).first if parent_project
end
end end
@subproject @subproject
end end
def parent_project def parent_project
unless @parent_project project&.parent
if /\/(.+)\/#{project.identifier}\/?$/.match(@path)
@parent_project = Project.visible.where(identifier: $1).first
end
end
@parent_project
end end
# Return the content type of file # Return the content type of file
@ -282,6 +287,11 @@ module RedmineDmsf
if dest.exist? if dest.exist?
return overwrite ? NotImplemented : PreconditionFailed return overwrite ? NotImplemented : PreconditionFailed
else else
# Change the title
return MethodNotAllowed unless folder # Moving sub-project not enabled
folder.title = resource.basename
return PreconditionFailed unless folder.save
# Move to a new destination
folder.move_to(resource.project, parent.folder) ? Created : PreconditionFailed folder.move_to(resource.project, parent.folder) ? Created : PreconditionFailed
end end
else else
@ -452,6 +462,11 @@ module RedmineDmsf
end end
lock_check(args[:scope]) lock_check(args[:scope])
entity = file ? file : folder entity = file ? file : folder
unless entity
e = DAV4Rack::LockFailure.new
e.add_failure @path, MethodNotAllowed
raise e
end
begin begin
if entity.locked? && entity.locked_for_user? if entity.locked? && entity.locked_for_user?
raise DAV4Rack::LockFailure.new("Failed to lock: #{@path}") raise DAV4Rack::LockFailure.new("Failed to lock: #{@path}")
@ -704,7 +719,8 @@ module RedmineDmsf
File.new disk_file File.new disk_file
end end
private private
def reuse_version_for_locked_file(file) def reuse_version_for_locked_file(file)
locks = file.lock locks = file.lock
locks.each do |lock| locks.each do |lock|

View File

@ -39,7 +39,7 @@ module RedmineDmsf
unless Setting.plugin_redmine_dmsf['dmsf_webdav'] unless Setting.plugin_redmine_dmsf['dmsf_webdav']
raise NotFound raise NotFound
end end
super(*args) super *args
pinfo = path.split('/').drop(1) pinfo = path.split('/').drop(1)
if pinfo.length == 0 # If this is the base_path, we're at root if pinfo.length == 0 # If this is the base_path, we're at root
@resource_c = IndexResource.new(*args) @resource_c = IndexResource.new(*args)
@ -110,12 +110,12 @@ module RedmineDmsf
end end
def get(request, response) def get(request, response)
@resource_c.get(request, response) @resource_c.get request, response
end end
def put(request, response) def put(request, response)
raise BadGateway if @read_only raise BadGateway if @read_only
@resource_c.put(request, response) @resource_c.put request, response
end end
def delete def delete
@ -125,12 +125,12 @@ module RedmineDmsf
def copy(dest, overwrite, depth) def copy(dest, overwrite, depth)
raise BadGateway if @read_only raise BadGateway if @read_only
@resource_c.copy(dest, overwrite, depth) @resource_c.copy dest, overwrite, depth
end end
def move(dest, overwrite = false) def move(dest, overwrite = false)
raise BadGateway if @read_only raise BadGateway if @read_only
@resource_c.move(dest, overwrite) @resource_c.move dest, overwrite
end end
def make_collection def make_collection
@ -144,16 +144,16 @@ module RedmineDmsf
def lock(args) def lock(args)
raise BadGateway if @read_only raise BadGateway if @read_only
@resource_c.lock(args) @resource_c.lock args
end end
def lock_check(lock_scope = nil) def lock_check(lock_scope = nil)
@resource_c.lock_check(lock_scope) @resource_c.lock_check lock_scope
end end
def unlock(token) def unlock(token)
raise BadGateway if @read_only raise BadGateway if @read_only
@resource_c.unlock(token) @resource_c.unlock token
end end
def name def name
@ -169,7 +169,7 @@ module RedmineDmsf
end end
def get_property(element) def get_property(element)
@resource_c.get_property(element) @resource_c.get_property element
end end
def properties def properties
@ -177,7 +177,7 @@ module RedmineDmsf
end end
def propstats(response, stats) def propstats(response, stats)
@resource_c.propstats(response, stats) @resource_c.propstats response, stats
end end
end end
end end

View File

@ -67,7 +67,7 @@ class DmsfWebdavDeleteTest < RedmineDmsf::Test::IntegrationTest
Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = @dmsf_webdav_use_project_names Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = @dmsf_webdav_use_project_names
Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = @dmsf_storage_directory Setting.plugin_redmine_dmsf['dmsf_storage_directory'] = @dmsf_storage_directory
end end
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
@ -191,7 +191,7 @@ class DmsfWebdavDeleteTest < RedmineDmsf::Test::IntegrationTest
delete "/dmsf/webdav/#{p1name_uri}/#{@folder6.title}", params: nil, headers: @jsmith delete "/dmsf/webdav/#{p1name_uri}/#{@folder6.title}", params: nil, headers: @jsmith
assert_response :success assert_response :success
@folder6.reload @folder6.reload
assert @folder6.deleted?, "Folder #{@folder1.title} is not expected to exist" assert @folder6.deleted?, "Folder #{@folder6.title} is not expected to exist"
end end
def test_file_delete_by_administrator def test_file_delete_by_administrator
@ -259,18 +259,20 @@ class DmsfWebdavDeleteTest < RedmineDmsf::Test::IntegrationTest
assert_nil DmsfFile.visible.find_by(id: @file1.id) assert_nil DmsfFile.visible.find_by(id: @file1.id)
end end
def test_file_delete_in_subproject def test_delete_file_in_subproject
@role.add_permission! :view_dmsf_folders
@role.add_permission! :file_delete
delete "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: nil, headers: @admin delete "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: nil, headers: @admin
assert_response :success assert_response :success
end end
def test_folder_delete_in_subproject def test_delete_folder_in_subproject
@role.add_permission! :view_dmsf_folders delete "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil,
@role.add_permission! :folder_delete headers: @admin
delete "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil, headers: @admin
assert_response :success assert_response :success
end end
def test_delete_subproject
delete "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}", params: nil, headers: @admin
assert_response :method_not_allowed
end
end end

View File

@ -32,6 +32,10 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest
@jsmith = credentials 'jsmith' @jsmith = credentials 'jsmith'
@project1 = Project.find 1 @project1 = Project.find 1
@project2 = Project.find 2 @project2 = Project.find 2
@project3 = Project.find 3
@file1 = DmsfFile.find 1
@folder10 = DmsfFolder.find 10
@file12 = DmsfFile.find 12
@role = Role.find_by(name: 'Manager') @role = Role.find_by(name: 'Manager')
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@ -61,6 +65,10 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of DmsfFile, @file1
assert_kind_of DmsfFile, @file12
assert_kind_of DmsfFolder, @folder10
assert_kind_of Role, @role assert_kind_of Role, @role
end end
@ -168,4 +176,16 @@ class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest
assert_response :success assert_response :success
end end
def test_get_file_in_subproject
@project3.enable_module! :dmsf # Flag module enabled
get "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: nil, headers: @admin
assert_response :success
end
def test_get_folder_in_subproject
@project3.enable_module! :dmsf # Flag module enabled
get "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil, headers: @admin
assert_response :success
end
end end

View File

@ -31,8 +31,11 @@ class DmsfWebdavHeadTest < RedmineDmsf::Test::IntegrationTest
@admin = credentials 'admin' @admin = credentials 'admin'
@jsmith = credentials 'jsmith' @jsmith = credentials 'jsmith'
@project1 = Project.find 1 @project1 = Project.find 1
@project1.enable_module!('dmsf') @project1.enable_module! 'dmsf'
@project2 = Project.find 2 @project2 = Project.find 2
@project3 = Project.find 3
@folder10 = DmsfFolder.find 10
@file12 = DmsfFile.find 12
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] @dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
@ -63,6 +66,9 @@ class DmsfWebdavHeadTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of DmsfFolder, @folder10
assert_kind_of DmsfFile, @file12
end end
def test_head_requires_authentication def test_head_requires_authentication
@ -134,6 +140,18 @@ class DmsfWebdavHeadTest < RedmineDmsf::Test::IntegrationTest
check_headers_dont_exist check_headers_dont_exist
end end
def test_head_file_in_subproject
@project3.enable_module! :dmsf # Flag module enabled
head "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: nil, headers: @admin
assert_response :success
end
def test_head_folder_in_subproject
@project3.enable_module! :dmsf # Flag module enabled
head "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil, headers: @admin
assert_response :success
end
private private
def check_headers_exist def check_headers_exist

View File

@ -23,7 +23,7 @@
require File.expand_path('../../../test_helper', __FILE__) require File.expand_path('../../../test_helper', __FILE__)
require 'fileutils' require 'fileutils'
class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest class DmsfWebdavLockTest < RedmineDmsf::Test::IntegrationTest
fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
:enabled_modules, :dmsf_folders, :dmsf_files, :dmsf_file_revisions :enabled_modules, :dmsf_folders, :dmsf_files, :dmsf_file_revisions
@ -33,7 +33,12 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
@jsmith = credentials 'jsmith' @jsmith = credentials 'jsmith'
@admin_user = User.find_by(login: 'admin') @admin_user = User.find_by(login: 'admin')
@project1 = Project.find 1 @project1 = Project.find 1
@project1.enable_module! 'dmsf'
@project3 = Project.find 3
@project3.enable_module! 'dmsf'
@file1 = DmsfFile.find 1 @file1 = DmsfFile.find 1
@file12 = DmsfFile.find 12
@folder10 = DmsfFolder.find 10
# Fix permissions for jsmith's role # Fix permissions for jsmith's role
@role = Role.find_by(name: 'Manager') @role = Role.find_by(name: 'Manager')
@role.add_permission! :view_dmsf_folders @role.add_permission! :view_dmsf_folders
@ -42,6 +47,12 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] @dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE' Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE'
@xml = %{<?xml version="1.0" encoding="utf-8" ?>
<d:lockinfo xmlns:d="DAV:">
<d:lockscope><d:exclusive/></d:lockscope>
<d:locktype><d:write/></d:locktype>
<d:owner>jsmith</d:owner>
</d:lockinfo>}
end end
def teardown def teardown
@ -51,26 +62,23 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project3
assert_kind_of DmsfFile, @file1 assert_kind_of DmsfFile, @file1
assert_kind_of DmsfFile, @file12
assert_kind_of DmsfFolder, @folder10
assert_kind_of Role, @role assert_kind_of Role, @role
assert_kind_of User, @admin_user assert_kind_of User, @admin_user
end end
def test_lock_file_already_locked_by_other def test_lock_file_already_locked_by_other
log_user 'admin', 'admin' # login as admin log_user 'admin', 'admin' # login as admin
User.current = @admin_user User.current = @admin_user
assert @file1.lock!, "File failed to be locked by #{User.current}" assert @file1.lock!, "File failed to be locked by #{User.current}"
process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: @xml,
%{<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<d:lockinfo xmlns:d=\"DAV:\">
<d:lockscope><d:exclusive/></d:lockscope>
<d:locktype><d:write/></d:locktype>
<d:owner>jsmith</d:owner>
</d:lockinfo>},
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' }) headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' })
assert_response :locked assert_response :locked
end end
def test_lock_file def test_lock_file
create_time = Time.utc(2000, 1, 2, 3, 4, 5) create_time = Time.utc(2000, 1, 2, 3, 4, 5)
refresh_time = Time.utc(2000, 1, 2, 6, 7, 8) refresh_time = Time.utc(2000, 1, 2, 6, 7, 8)
@ -79,13 +87,7 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
# Time travel, will make the usec part of the time 0 # Time travel, will make the usec part of the time 0
travel_to create_time do travel_to create_time do
# Lock file # Lock file
xml = %{<?xml version="1.0" encoding="utf-8" ?> process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: @xml,
<d:lockinfo xmlns:d="DAV:">
<d:lockscope><d:exclusive/></d:lockscope>
<d:locktype><d:write/></d:locktype>
<d:owner>jsmith</d:owner>
</d:lockinfo>}
process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: xml,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' }) headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' })
assert_response :success assert_response :success
# Verify the response # Verify the response
@ -136,4 +138,23 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
end end
end end
def test_lock_file_in_subproject
process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: @xml,
headers: @admin.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' })
assert_response :success
end
def test_lock_folder_in_subproject
process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: @xml,
headers: @admin.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' })
assert_response :success
end
def test_lock_subproject
process :lock, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}", params: @xml,
headers: @admin.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite' })
assert_response :multi_status
assert_match '<d:status>HTTP/1.1 405 Method Not Allowed</d:status>', response.body
end
end end

View File

@ -31,8 +31,13 @@ class DmsfWebdavMkcolTest < RedmineDmsf::Test::IntegrationTest
@admin = credentials 'admin' @admin = credentials 'admin'
@jsmith = credentials 'jsmith' @jsmith = credentials 'jsmith'
@project1 = Project.find 1 @project1 = Project.find 1
@project1.enable_module! :dmsf
@project2 = Project.find 2 @project2 = Project.find 2
@project3 = Project.find 3
@project3.enable_module! :dmsf
@role = Role.find_by(name: 'Manager') @role = Role.find_by(name: 'Manager')
@role.add_permission! :folder_manipulation
@role.add_permission! :view_dmsf_folders
@folder6 = DmsfFolder.find 6 @folder6 = DmsfFolder.find 6
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@ -62,6 +67,7 @@ class DmsfWebdavMkcolTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of Role, @role assert_kind_of Role, @role
assert_kind_of DmsfFolder, @folder6 assert_kind_of DmsfFolder, @folder6
end end
@ -82,36 +88,26 @@ class DmsfWebdavMkcolTest < RedmineDmsf::Test::IntegrationTest
end end
def test_should_not_succed_on_a_non_dmsf_enabled_project def test_should_not_succed_on_a_non_dmsf_enabled_project
@project1.disable_module! :dmsf
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/folder", params: nil, headers: @jsmith process :mkcol, "/dmsf/webdav/#{@project1.identifier}/folder", params: nil, headers: @jsmith
assert_response :forbidden assert_response :not_found
end end
def test_should_not_create_folder_without_permissions def test_should_not_create_folder_without_permissions
@project1.enable_module! :dmsf # Flag module enabled @role.remove_permission! :folder_manipulation
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/folder", params: nil, headers: @jsmith process :mkcol, "/dmsf/webdav/#{@project1.identifier}/folder", params: nil, headers: @jsmith
assert_response :forbidden assert_response :forbidden
end end
def test_should_fail_to_create_folder_that_already_exists def test_should_fail_to_create_folder_that_already_exists
@project1.enable_module! :dmsf # Flag module enabled
@role.add_permission! :folder_manipulation
@role.add_permission! :view_dmsf_folders
process :mkcol, process :mkcol,
"/dmsf/webdav/#{@project1.identifier}/#{@folder6.title}", params: nil, headers: @jsmith "/dmsf/webdav/#{@project1.identifier}/#{@folder6.title}", params: nil, headers: @jsmith
assert_response :method_not_allowed assert_response :method_not_allowed
end end
def test_should_fail_to_create_folder_for_user_without_rights
@project1.enable_module! :dmsf # Flag module enabled
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/test1", params: nil, headers: @jsmith
assert_response :forbidden
end
def test_should_create_folder_for_non_admin_user_with_rights def test_should_create_folder_for_non_admin_user_with_rights
@project1.enable_module! :dmsf
@role.add_permission! :folder_manipulation
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/test1", params: nil, headers: @jsmith process :mkcol, "/dmsf/webdav/#{@project1.identifier}/test1", params: nil, headers: @jsmith
assert_response :success # Created assert_response :success
Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = true Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = true
project1_uri = Addressable::URI.escape(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)) project1_uri = Addressable::URI.escape(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1))
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/test2", params: nil, headers: @jsmith process :mkcol, "/dmsf/webdav/#{@project1.identifier}/test2", params: nil, headers: @jsmith
@ -119,5 +115,11 @@ class DmsfWebdavMkcolTest < RedmineDmsf::Test::IntegrationTest
process :mkcol, "/dmsf/webdav/#{project1_uri}/test3", params: nil, headers: @jsmith process :mkcol, "/dmsf/webdav/#{project1_uri}/test3", params: nil, headers: @jsmith
assert_response :success # Created assert_response :success # Created
end end
def test_create_folder_in_subproject
process :mkcol, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/test1", params: nil,
headers: @admin
assert_response :success
end
end end

View File

@ -40,9 +40,13 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
@project1.enable_module! :dmsf @project1.enable_module! :dmsf
@project2 = Project.find 2 @project2 = Project.find 2
@project2.enable_module! :dmsf @project2.enable_module! :dmsf
@project3 = Project.find 3
@project3.enable_module! :dmsf
@file1 = DmsfFile.find 1 @file1 = DmsfFile.find 1
@file10 = DmsfFile.find 10 @file10 = DmsfFile.find 10
@file12 = DmsfFile.find 12
@folder1 = DmsfFolder.find 1 @folder1 = DmsfFolder.find 1
@folder10 = DmsfFolder.find 10
@role = Role.find 1 @role = Role.find 1
@role.add_permission! :view_dmsf_folders @role.add_permission! :view_dmsf_folders
@role.add_permission! :folder_manipulation @role.add_permission! :folder_manipulation
@ -53,7 +57,6 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE' Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE'
@dmsf_webdav_use_project_names = Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] @dmsf_webdav_use_project_names = Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names']
Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = false Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = false
super
end end
def teardown def teardown
@ -72,10 +75,13 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of Role, @role assert_kind_of Role, @role
assert_kind_of DmsfFile, @file1 assert_kind_of DmsfFile, @file1
assert_kind_of DmsfFile, @file10 assert_kind_of DmsfFile, @file10
assert_kind_of DmsfFile, @file12
assert_kind_of DmsfFolder, @folder1 assert_kind_of DmsfFolder, @folder1
assert_kind_of DmsfFolder, @folder10
assert_kind_of User, @jsmith_user assert_kind_of User, @jsmith_user
assert_kind_of User, @admin_user assert_kind_of User, @admin_user
end end
@ -227,7 +233,7 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil, process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
headers: @jsmith.merge!({ headers: @jsmith.merge!({
destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}"}) destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}"})
assert_response :not_implemented # NotImplemented assert_response :not_implemented
end end
end end
end end
@ -347,5 +353,30 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest
assert_response :success # Created assert_response :success # Created
end end
end end
def test_move_file_in_subproject
assert_difference '@file12.dmsf_file_revisions.count', +1 do
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@file12.name}", params: nil,
headers: @admin.merge!({
destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/new_file_name" })
assert_response :created
end
end
def test_move_folder_in_subproject
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil,
headers: @admin.merge!({
destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/new_folder_name" })
assert_response :created
@folder10.reload
assert_equal 'new_folder_name', @folder10.title
end
def test_move_subproject
process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}", params: nil,
headers: @admin.merge!({
destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/new_project_name" })
assert_response :method_not_allowed
end
end end

View File

@ -32,6 +32,8 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
@jsmith = credentials 'jsmith' @jsmith = credentials 'jsmith'
@project1 = Project.find 1 @project1 = Project.find 1
@project2 = Project.find 2 @project2 = Project.find 2
@project3 = Project.find 3
@project3.enable_module! :dmsf
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] @dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
@ -45,10 +47,11 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = @dmsf_webdav_strategy Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = @dmsf_webdav_strategy
Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = @dmsf_webdav_use_project_names Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = @dmsf_webdav_use_project_names
end end
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
end end
def test_options_requires_no_authentication_for_root_level def test_options_requires_no_authentication_for_root_level
@ -177,4 +180,9 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
assert_response :not_found assert_response :not_found
end end
def test_options_for_subproject
process :options, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}", params: nil, headers: @admin
assert_response :success
end
end end

View File

@ -30,16 +30,20 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
def setup def setup
@admin = credentials 'admin' @admin = credentials 'admin'
@jsmith = credentials 'jsmith' # Not a member of project1 @jsmith = credentials 'jsmith'
@project1 = Project.find 1 # DMSF enabled @project1 = Project.find 1
@project2 = Project.find 2 # DMSF disabled @project1.enable_module! :dmsf
# Folders in project1 @project2 = Project.find 2
@project2.enable_module! :dmsf
@project3 = Project.find 3
@project3.enable_module! :dmsf
@folder1 = DmsfFolder.find 1 @folder1 = DmsfFolder.find 1
@folder6 = DmsfFolder.find 6 @folder6 = DmsfFolder.find 6
# Files in project1 @folder10 = DmsfFolder.find 10
@file1 = DmsfFile.find 1 @file1 = DmsfFile.find 1
@file9 = DmsfFile.find 9 @file9 = DmsfFile.find 9
@file10 = DmsfFile.find 10 @file10 = DmsfFile.find 10
@file12 = DmsfFile.find 12
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] @dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
@ -61,6 +65,14 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of DmsfFolder, @folder1
assert_kind_of DmsfFolder, @folder6
assert_kind_of DmsfFolder, @folder10
assert_kind_of DmsfFile, @file1
assert_kind_of DmsfFile, @file9
assert_kind_of DmsfFile, @file10
assert_kind_of DmsfFile, @file12
end end
def test_propfind_denied_for_anonymous def test_propfind_denied_for_anonymous
@ -168,8 +180,7 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
end end
def test_propfind_depth1_on_root_for_admin def test_propfind_depth1_on_root_for_admin
@project1.name = 'Online Cookbook' Setting.plugin_redmine_dmsf['dmsf_webdav_use_project_names'] = true
@project1.save!
project1_new_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1) project1_new_name = RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)
project1_new_uri = Addressable::URI.escape(project1_new_name) project1_new_uri = Addressable::URI.escape(project1_new_name)
process :propfind, "/dmsf/webdav/#{project1_new_uri}", params: nil, headers: @admin.merge!({ HTTP_DEPTH: '1'}) process :propfind, "/dmsf/webdav/#{project1_new_uri}", params: nil, headers: @admin.merge!({ HTTP_DEPTH: '1'})
@ -178,4 +189,12 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
assert response.body.include?("<d:displayname>#{project1_new_name}</d:displayname>") assert response.body.include?("<d:displayname>#{project1_new_name}</d:displayname>")
end end
def test_propfind_for_subproject
process :propfind, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}", params: nil,
headers: @admin.merge!({ HTTP_DEPTH: '1'})
assert_response :multi_status
assert response.body.include?("<d:href>http://www.example.com:80/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/</d:href>")
assert response.body.include?("<d:displayname>#{@project3.identifier}</d:displayname>")
end
end end

View File

@ -37,6 +37,8 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest
@jsmith_user = User.find_by(login: 'jsmith') @jsmith_user = User.find_by(login: 'jsmith')
@project1 = Project.find 1 @project1 = Project.find 1
@project2 = Project.find 2 @project2 = Project.find 2
@project3 = Project.find 3
@project3.enable_module! :dmsf
@role = Role.find_by(name: 'Manager') @role = Role.find_by(name: 'Manager')
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav'] @dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@ -62,6 +64,7 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest
def test_truth def test_truth
assert_kind_of Project, @project1 assert_kind_of Project, @project1
assert_kind_of Project, @project2 assert_kind_of Project, @project2
assert_kind_of Project, @project3
assert_kind_of Role, @role assert_kind_of Role, @role
assert_kind_of User, @jsmith_user assert_kind_of User, @jsmith_user
end end
@ -344,5 +347,12 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest
end end
Setting.plugin_redmine_dmsf['dmsf_webdav_disable_versioning'] = original Setting.plugin_redmine_dmsf['dmsf_webdav_disable_versioning'] = original
end end
def test_put_into_subproject
put "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/test-1234.txt", params: '1234',
headers: @admin.merge!({ content_type: :text })
assert_response :created
assert DmsfFile.find_by(project_id: @project3.id, dmsf_folder: nil, name: 'test-1234.txt')
end
end end

View File

@ -0,0 +1,143 @@
# encoding: utf-8
# frozen_string_literal: true
#
# Redmine plugin for Document Management System "Features"
#
# Copyright © 2012 Daniel Munn <dan.munn@munnster.co.uk>
# Copyright © 2011-20 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.
require File.expand_path('../../../test_helper', __FILE__)
require 'fileutils'
class DmsfWebdavUnlockTest < RedmineDmsf::Test::IntegrationTest
fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
:enabled_modules, :dmsf_folders, :dmsf_files, :dmsf_file_revisions
def setup
@admin = credentials 'admin'
@jsmith = credentials 'jsmith'
@admin_user = User.find_by(login: 'admin')
@jsmith_user = User.find_by(login: 'jsmith')
@project1 = Project.find 1
@project1.enable_module! 'dmsf'
@project3 = Project.find 3
@project3.enable_module! 'dmsf'
@file1 = DmsfFile.find 1
@file12 = DmsfFile.find 12
@folder1 = DmsfFolder.find 1
@folder10 = DmsfFolder.find 10
# Fix permissions for jsmith's role
@role = Role.find_by(name: 'Manager')
@role.add_permission! :view_dmsf_folders
@role.add_permission! :folder_manipulation
@role.add_permission! :view_dmsf_files
@role.add_permission! :file_manipulation
@dmsf_webdav = Setting.plugin_redmine_dmsf['dmsf_webdav']
Setting.plugin_redmine_dmsf['dmsf_webdav'] = true
@dmsf_webdav_strategy = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE'
end
def teardown
Setting.plugin_redmine_dmsf['dmsf_webdav'] = @dmsf_webdav
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = @dmsf_webdav_strategy
end
def test_truth
assert_kind_of Project, @project1
assert_kind_of Project, @project3
assert_kind_of DmsfFile, @file1
assert_kind_of DmsfFile, @file12
assert_kind_of DmsfFolder, @folder1
assert_kind_of DmsfFolder, @folder10
assert_kind_of Role, @role
assert_kind_of User, @admin_user
assert_kind_of User, @jsmith_user
end
def test_unlock_file
log_user 'jsmith', 'jsmith' # login as jsmith
User.current = @jsmith_user
l = @file1.lock!
assert l, "File failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :success
end
def test_unlock_file_locked_by_someone_else
log_user 'jsmith', 'jsmith' # login as jsmith
User.current = @admin_user
l = @file1.lock!
assert l, "File failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :forbidden
end
def test_unlock_file_with_invalid_token
log_user 'jsmith', 'jsmith' # login as jsmith
User.current = @jsmith_user
l = @file1.lock!
assert l, "File failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: 'invalid_token' })
assert_response :bad_request
end
def test_unlock_file_not_locked
log_user 'jsmith', 'jsmith' # login as jsmith
User.current = @jsmith_user
l = @file1.lock!
@file1.unlock!
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: nil,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :bad_request
end
def test_unlock_folder
log_user 'jsmith', 'jsmith' # login as jsmith
User.current = @jsmith_user
l = @folder1.lock!
assert l, "Folder failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", params: nil,
headers: @jsmith.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :success
end
def test_unlock_file_in_subproject
log_user 'admin', 'admin' # login as admin
User.current = @admin_user
l = @file12.lock!
assert l, "File failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@project1.identifier}/#{@file12.name}", params: nil,
headers: @admin.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :success
end
def test_unlock_folder_in_subproject
log_user 'admin', 'admin' # login as admin
User.current = @admin_user
l = @folder10.lock!
assert l, "Folder failed to be locked by #{User.current}"
process :unlock, "/dmsf/webdav/#{@project1.identifier}/#{@project3.identifier}/#{@folder10.title}", params: nil,
headers: @admin.merge!({ HTTP_DEPTH: 'infinity', HTTP_TIMEOUT: 'Infinite', HTTP_LOCK_TOKEN: l.uuid })
assert_response :success
end
end