diff --git a/.github/workflows/rubyonrails.yml b/.github/workflows/rubyonrails.yml index d1f6422d..3fae8de4 100644 --- a/.github/workflows/rubyonrails.yml +++ b/.github/workflows/rubyonrails.yml @@ -150,8 +150,7 @@ jobs: cd /opt/redmine bundle exec rake redmine:plugins:test:units bundle exec rake redmine:plugins:test:functionals -# TODO: -# bundle exec rake redmine:plugins:test:integration + bundle exec rake redmine:plugins:test:integration - name: Helpers tests run: | cd /opt/redmine @@ -164,23 +163,23 @@ jobs: run: | cd /opt/redmine bundle exec rubocop -c plugins/redmine_dmsf/.rubocop.yml plugins/redmine_dmsf/ - #- name: Litmus - # Prepare Redmine's environment for WebDAV testing - # Run Webrick server - # Run Litmus tests (Omit 'http' tests due to 'timeout waiting for interim response' and locks due to complex bogus conditional) - # Shutdown Webrick - # Clean up Redmine's environment from WebDAV testing -# TODO: -# run: | -# cd /opt/redmine -# bundle exec rake redmine:dmsf_webdav_test_on -# bundle exec rails server -u webrick -e test -d -# sleep 5 -# litmus http://localhost:3000/dmsf/webdav/dmsf_test_project admin admin -# kill $(pgrep -f webrick) -# bundle exec rake redmine:dmsf_webdav_test_off -# env: -# TESTS: "basic copymove props" + - name: Litmus + Prepare Redmine's environment for WebDAV testing + Run Webrick server + Run Litmus tests (Omit 'http' tests due to 'timeout waiting for interim response' and locks due to complex bogus conditional) + Shutdown Webrick + Clean up Redmine's environment from WebDAV testing + TODO: + run: | + cd /opt/redmine + bundle exec rake redmine:dmsf_webdav_test_on + bundle exec rails server -u webrick -e test -d + sleep 5 + litmus http://localhost:3000/dmsf/webdav/dmsf_test_project admin admin + kill $(pgrep -f webrick) + bundle exec rake redmine:dmsf_webdav_test_off + env: + TESTS: "basic copymove props" - name: Cleanup # Rollback plugin's changes to the database # Stop the database engine diff --git a/app/controllers/dmsf_files_controller.rb b/app/controllers/dmsf_files_controller.rb index 7b63732f..2e200716 100644 --- a/app/controllers/dmsf_files_controller.rb +++ b/app/controllers/dmsf_files_controller.rb @@ -142,7 +142,7 @@ class DmsfFilesController < ApplicationController revision.disk_filename = revision.new_storage_filename revision.mime_type = upload.mime_type revision.digest = upload.digest - revision.shared_file.attach( + revision.file.attach( io: File.open(upload.tempfile_path), filename: revision.disk_filename, content_type: revision.mime_type, diff --git a/app/helpers/dmsf_upload_helper.rb b/app/helpers/dmsf_upload_helper.rb index 0d6a9028..21757c7f 100644 --- a/app/helpers/dmsf_upload_helper.rb +++ b/app/helpers/dmsf_upload_helper.rb @@ -96,7 +96,7 @@ module DmsfUploadHelper a = Attachment.find_by_token(committed_file[:token]) committed_file[:tempfile_path] = a.diskfile if a end - new_revision.shared_file.attach( + new_revision.file.attach( io: File.open(committed_file[:tempfile_path]), filename: new_revision.name, content_type: new_revision.mime_type, diff --git a/app/models/dmsf_file.rb b/app/models/dmsf_file.rb index f26da173..d4d0c15f 100644 --- a/app/models/dmsf_file.rb +++ b/app/models/dmsf_file.rb @@ -313,10 +313,15 @@ class DmsfFile < ApplicationRecord file = DmsfFile.new file.dmsf_folder_id = folder.id if folder file.project_id = project.id - if DmsfFile.exists?(project_id: file.project_id, dmsf_folder_id: file.dmsf_folder_id, name: filename) + title = last_revision&.title + if DmsfFile.visible.exists?(project_id: file.project_id, dmsf_folder_id: file.dmsf_folder_id, name: filename) + basename = File.basename(filename, '.*') + extname = File.extname(filename) 1.step do |i| - gen_filename = " #{filename} #{l(:dmsf_copy, n: i)}" - unless DmsfFile.exists?(project_id: file.project_id, dmsf_folder_id: file.dmsf_folder_id, name: gen_filename) + title = "#{basename} (#{i})" + gen_filename = "#{title}#{extname}" + unless DmsfFile.visible.exists?(project_id: file.project_id, dmsf_folder_id: file.dmsf_folder_id, + name: gen_filename) filename = gen_filename break end @@ -326,9 +331,11 @@ class DmsfFile < ApplicationRecord file.notification = RedmineDmsf.dmsf_default_notifications? if file.save && last_revision new_revision = last_revision.clone + new_revision.name = filename + new_revision.title = title new_revision.dmsf_file = file new_revision.disk_filename = new_revision.new_storage_filename - # Assign the same workflow if it's a global one or we are in the same project + # Assign the same workflow if it's a global one, or we are in the same project new_revision.workflow = nil new_revision.dmsf_workflow_id = nil new_revision.dmsf_workflow_assigned_by_user_id = nil @@ -340,8 +347,17 @@ class DmsfFile < ApplicationRecord new_revision.set_workflow wf.id, nil new_revision.assign_workflow wf.id end - if File.exist? last_revision.disk_file - FileUtils.cp last_revision.disk_file, new_revision.disk_file(search_if_not_exists: false) + if last_revision.file.attached? + begin + new_revision.file.attach( + io: StringIO.new(last_revision.file.blob.download), + filename: filename, + content_type: new_revision.file.content_type, + identify: false + ) + rescue ActiveStorage::FileNotFoundError => e + Rails.logger.error e + end end new_revision.comment = l(:comment_copied_from, source: "#{self.project.identifier}:#{dmsf_path_str}") new_revision.custom_values = [] diff --git a/app/models/dmsf_file_revision.rb b/app/models/dmsf_file_revision.rb index c1f95bfe..88576dad 100644 --- a/app/models/dmsf_file_revision.rb +++ b/app/models/dmsf_file_revision.rb @@ -316,7 +316,12 @@ class DmsfFileRevision < ApplicationRecord end def copy_file_content(open_file) - file.attach io: open_file, filename: dmsf_file.name + file.attach( + io: open_file, + filename: dmsf_file.name, + content_type: mime_type, + identify: false + ) self.digest = file.blob.checksum end diff --git a/db/migrate/20251015130601_active_storage_migration.rb b/db/migrate/20251015130601_active_storage_migration.rb index 801a7e23..0cc168ed 100644 --- a/db/migrate/20251015130601_active_storage_migration.rb +++ b/db/migrate/20251015130601_active_storage_migration.rb @@ -44,7 +44,7 @@ class ActiveStorageMigration < ActiveRecord::Migration[7.0] .find_each .with_index do |r, i| if i.zero? - r.shared_file.attach( + r.file.attach( io: File.open(path), filename: r.name, content_type: r.mime_type, @@ -52,8 +52,8 @@ class ActiveStorageMigration < ActiveRecord::Migration[7.0] ) # Remove the original file FileUtils.rm path - key = r.shared_file.blob.key - $stdout.puts "#{path} => #{File.join(key[0..1], key[2..3], key)} (#{r.shared_file.blob.filename})" + key = r.file.blob.key + $stdout.puts "#{path} => #{File.join(key[0..1], key[2..3], key)} (#{r.file.blob.filename})" else # The other revisions should have set the source revision warn("r#{r.id}.source_dmsf_file_revision_id is null") unless r.source_dmsf_file_revision_id diff --git a/lib/redmine_dmsf/webdav/dmsf_resource.rb b/lib/redmine_dmsf/webdav/dmsf_resource.rb index f591bdb6..db59f4e8 100644 --- a/lib/redmine_dmsf/webdav/dmsf_resource.rb +++ b/lib/redmine_dmsf/webdav/dmsf_resource.rb @@ -276,9 +276,7 @@ module RedmineDmsf # Copy file.last_revision.disk_file to new_revision.disk_file new_revision.size = file.last_revision.size new_revision.disk_filename = new_revision.new_storage_filename - File.open(file.last_revision.disk_file, 'rb') do |f| - new_revision.copy_file_content f - end + new_revision.copy_file_content StringIO.new(file.last_revision.file.download) # Save new_revision.save && dest.resource.file.save # Delete (and destroy) the file that should have been renamed and return what should have been returned @@ -340,7 +338,7 @@ module RedmineDmsf res = NoContent end - return PreconditionFailed unless parent.exist? && parent.folder + return PreconditionFailed unless parent.exist? && (parent.folder || parent.project) if collection? # Permission check if they can manipulate folders and view folders @@ -376,15 +374,11 @@ module RedmineDmsf new_file = file.copy_to(dest.resource.project, parent&.folder) return InternalServerError unless new_file&.last_revision - # Update Revision and names of file (We can link to old physical resource, as it's not changed) - new_file.last_revision.name = dest.resource.basename - new_file.name = dest.resource.basename - # Save Changes - new_file.last_revision.save && new_file.save ? res : PreconditionFailed + res end end - # Lock Check + # Lock check # Check for the existence of locks def lock_check(args = {}) entity = file || folder @@ -626,7 +620,6 @@ module RedmineDmsf end new_revision.disk_filename = new_revision.new_storage_filename unless reuse_revision - if new_revision.save new_revision.copy_file_content request.body new_revision.save @@ -636,7 +629,6 @@ module RedmineDmsf Rails.logger.error new_revision.errors.full_messages.to_sentence raise InternalServerError end - Created end diff --git a/test/integration/webdav/dmsf_webdav_move_test.rb b/test/integration/webdav/dmsf_webdav_move_test.rb index dce8c7f9..a9f999d6 100644 --- a/test/integration/webdav/dmsf_webdav_move_test.rb +++ b/test/integration/webdav/dmsf_webdav_move_test.rb @@ -22,199 +22,199 @@ require 'fileutils' # WebDAV MOVE tests class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest - # def test_move_denied_for_anonymous - # new_name = "#{@file1.name}.moved" - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # assert_response :unauthorized - # end - # end - # - # def test_move_to_new_filename_without_file_manipulation_permission - # @role.remove_permission! :file_manipulation - # new_name = "#{@file1.name}.moved" - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :forbidden - # end - # end - # - # def test_move_to_new_filename_without_file_manipulation_permission_as_admin - # @role.remove_permission! :file_manipulation - # new_name = "#{@file1.name}.moved" - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @admin.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :created - # f = DmsfFile.find_file_by_name @project1, nil, new_name - # assert f, "Moved file '#{new_name}' not found in project." - # end - # end - # - # def test_without_folder_manipulation_permission - # @role.remove_permission! :folder_manipulation - # new_name = "#{@folder1.title}.moved" - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :forbidden - # end - # - # def test_without_folder_manipulation_permission_as_admin - # @role.remove_permission! :folder_manipulation - # new_name = "#{@folder1.title}.moved" - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", - # params: nil, - # headers: @admin.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :created - # end - # - # def test_move_folder_to_another_project - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", - # params: nil, - # headers: @admin.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project2.identifier}/#{@folder1.title}" } - # ) - # assert_response :created - # @folder1.dmsf_folders.each do |d| - # assert_equal @project2, d.project - # end - # @folder1.dmsf_files.each do |f| - # assert_equal @project2, f.project - # end - # @folder1.dmsf_links.each do |l| - # assert_equal @project2, l.project - # end - # end - # - # def test_move_non_existent_file - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/not_a_file.txt", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/moved_file.txt" } - # ) - # assert_response :not_found # NotFound - # end - # - # def test_move_to_new_filename - # new_name = "#{@file1.name}.moved" - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :created - # f = DmsfFile.find_file_by_name @project1, nil, new_name - # assert f, "Moved file '#{new_name}' not found in project." - # end - # end - # - # def test_move_to_new_filename_with_project_names - # with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', - # 'dmsf_webdav' => '1', - # 'dmsf_webdav_authentication' => 'Basic', - # 'dmsf_webdav_strategy' => 'WEBDAV_READ_WRITE' } do - # project1_uri = ERB::Util.url_encode(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)) - # new_name = "#{@file1.name}.moved" - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, "/dmsf/webdav/#{project1_uri}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{project1_uri}/#{new_name}" } - # ) - # assert_response :created - # f = DmsfFile.find_file_by_name @project1, nil, new_name - # assert f, "Moved file '#{new_name}' not found in project." - # end - # end - # end - # - # def test_move_zero_sized_to_new_filename - # new_name = "#{@file10.name}.moved" - # assert_no_difference '@file10.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file10.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :created - # f = DmsfFile.find_file_by_name @project1, nil, new_name - # assert f, "Moved file '#{new_name}' not found in project." - # end - # end - # - # def test_move_to_new_folder - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process( - # :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}/#{@file1.name}" } - # ) - # ) - # assert_response :created - # @file1.reload - # assert_equal @folder1.id, @file1.dmsf_folder_id - # end - # end - # - # def test_move_to_new_folder_with_project_names - # with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', - # 'dmsf_webdav' => '1', - # 'dmsf_webdav_authentication' => 'Basic', - # 'dmsf_webdav_strategy' => 'WEBDAV_READ_WRITE' } do - # project1_uri = ERB::Util.url_encode(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)) - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, - # "/dmsf/webdav/#{project1_uri}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{project1_uri}/#{@folder1.title}/#{@file1.name}" } - # ) - # assert_response :created - # @file1.reload - # assert_equal @folder1.id, @file1.dmsf_folder_id - # end - # end - # end - # - # def test_move_zero_sized_to_new_folder - # assert_no_difference '@file10.dmsf_file_revisions.count' do - # process( - # :move, "/dmsf/webdav/#{@project1.identifier}/#{@file10.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}/#{@file10.name}" } - # ) - # ) - # assert_response :created - # @file10.reload - # assert_equal @folder1.id, @file10.dmsf_folder_id - # end - # end + def test_move_denied_for_anonymous + new_name = "#{@file1.name}.moved" + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + assert_response :unauthorized + end + end + + def test_move_to_new_filename_without_file_manipulation_permission + @role.remove_permission! :file_manipulation + new_name = "#{@file1.name}.moved" + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :forbidden + end + end + + def test_move_to_new_filename_without_file_manipulation_permission_as_admin + @role.remove_permission! :file_manipulation + new_name = "#{@file1.name}.moved" + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @admin.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :created + f = DmsfFile.find_file_by_name @project1, nil, new_name + assert f, "Moved file '#{new_name}' not found in project." + end + end + + def test_without_folder_manipulation_permission + @role.remove_permission! :folder_manipulation + new_name = "#{@folder1.title}.moved" + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :forbidden + end + + def test_without_folder_manipulation_permission_as_admin + @role.remove_permission! :folder_manipulation + new_name = "#{@folder1.title}.moved" + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", + params: nil, + headers: @admin.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :created + end + + def test_move_folder_to_another_project + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}", + params: nil, + headers: @admin.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project2.identifier}/#{@folder1.title}" } + ) + assert_response :created + @folder1.dmsf_folders.each do |d| + assert_equal @project2, d.project + end + @folder1.dmsf_files.each do |f| + assert_equal @project2, f.project + end + @folder1.dmsf_links.each do |l| + assert_equal @project2, l.project + end + end + + def test_move_non_existent_file + process :move, + "/dmsf/webdav/#{@project1.identifier}/not_a_file.txt", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/moved_file.txt" } + ) + assert_response :not_found # NotFound + end + + def test_move_to_new_filename + new_name = "#{@file1.name}.moved" + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :created + f = DmsfFile.find_file_by_name @project1, nil, new_name + assert f, "Moved file '#{new_name}' not found in project." + end + end + + def test_move_to_new_filename_with_project_names + with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', + 'dmsf_webdav' => '1', + 'dmsf_webdav_authentication' => 'Basic', + 'dmsf_webdav_strategy' => 'WEBDAV_READ_WRITE' } do + project1_uri = ERB::Util.url_encode(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)) + new_name = "#{@file1.name}.moved" + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, "/dmsf/webdav/#{project1_uri}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{project1_uri}/#{new_name}" } + ) + assert_response :created + f = DmsfFile.find_file_by_name @project1, nil, new_name + assert f, "Moved file '#{new_name}' not found in project." + end + end + end + + def test_move_zero_sized_to_new_filename + new_name = "#{@file10.name}.moved" + assert_no_difference '@file10.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file10.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :created + f = DmsfFile.find_file_by_name @project1, nil, new_name + assert f, "Moved file '#{new_name}' not found in project." + end + end + + def test_move_to_new_folder + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process( + :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}/#{@file1.name}" } + ) + ) + assert_response :created + @file1.reload + assert_equal @folder1.id, @file1.dmsf_folder_id + end + end + + def test_move_to_new_folder_with_project_names + with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', + 'dmsf_webdav' => '1', + 'dmsf_webdav_authentication' => 'Basic', + 'dmsf_webdav_strategy' => 'WEBDAV_READ_WRITE' } do + project1_uri = ERB::Util.url_encode(RedmineDmsf::Webdav::ProjectResource.create_project_name(@project1)) + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, + "/dmsf/webdav/#{project1_uri}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{project1_uri}/#{@folder1.title}/#{@file1.name}" } + ) + assert_response :created + @file1.reload + assert_equal @folder1.id, @file1.dmsf_folder_id + end + end + end + + def test_move_zero_sized_to_new_folder + assert_no_difference '@file10.dmsf_file_revisions.count' do + process( + :move, "/dmsf/webdav/#{@project1.identifier}/#{@file10.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@folder1.title}/#{@file10.name}" } + ) + ) + assert_response :created + @file10.reload + assert_equal @folder1.id, @file10.dmsf_folder_id + end + end def test_move_to_existing_filename assert_no_difference '@file9.dmsf_file_revisions.count' do @@ -228,189 +228,189 @@ class DmsfWebdavMoveTest < RedmineDmsf::Test::IntegrationTest end end - # def test_move_when_file_is_locked_by_other - # log_user 'admin', 'admin' # login as admin - # User.current = @admin_user - # assert @file1.lock!, "File failed to be locked by #{User.current}" - # new_name = "#{@file1.name}.moved" - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :locked - # end - # end - # - # def test_move_when_file_is_locked_by_other_and_user_is_admin - # log_user 'jsmith', 'jsmith' # login as jsmith - # User.current = @jsmith_user - # assert @file1.lock!, "File failed to be locked by #{User.current}" - # - # new_name = "#{@file1.name}.moved" - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @admin.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :locked - # end - # end - # - # def test_move_when_file_is_locked_by_user - # log_user 'jsmith', 'jsmith' # login as jsmith - # User.current = @jsmith_user - # assert @file1.lock!, "File failed to be locked by #{User.current}" - # - # # Move once - # new_name = "#{@file1.name}.m1" - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } - # ) - # assert_response :success # Created - # end - # # Move twice, make sure that the MsOffice store sequence is not disrupting normal move - # new_name2 = "#{new_name}.m2" - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{new_name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name2}" } - # ) - # assert_response :success # Created - # end - # end - # - # def test_move_msoffice_save_locked_file - # # When some versions of MsOffice save a file they use the following sequence: - # # 1. Save changes to a new temporary document, XXX.tmp - # # 2. Rename (MOVE) document to YYY.tmp. History is lost here if the original document is moved. - # # 3. Rename (MOVE) XXX.tmp to document's name. XXX.tmp must be merged to the original document otherwise the - # # history is lost. - # # 4. Delete YYY.tmp. - # # Verify that steps 2 and 3 work. - # log_user 'jsmith', 'jsmith' # login as jsmith - # User.current = @jsmith_user - # assert @file1.lock!, "File failed to be locked by #{User.current}" - # - # # First save while the file is locked, should create new revision - # temp_file_name = 'AAAAAAAA.tmp' - # - # # Make sure that the temp-file does not exist. - # temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name - # assert_not temp_file, "File '#{temp_file_name}' should not exist yet." - # - # # Move the original file to AAAAAAAA.tmp. The original file should not changed but a new file should be created. - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}" } - # ) - # assert_response :success # Created - # end - # - # # Verify that a new file has been created - # temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name - # assert temp_file, "File '#{temp_file_name}' not found, move failed." - # assert_equal temp_file.dmsf_file_revisions.count, 1 - # assert_not_equal temp_file.id, @file1.id - # - # # Move a temporary file (use AAAAAAAA.tmp) to the original file. - # assert_difference '@file1.dmsf_file_revisions.count', +1 do - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}", - # params: nil, - # headers: @jsmith.merge!( - # { - # destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # 'HTTP_OVERWRITE' => 'T' - # } - # ) - # assert_response :success # Created - # end - # - # # Second save while file is locked, should NOT create new revision - # temp_file_name = 'BBBBBBBB.tmp' - # - # # Make sure that the temp-file does not exist. - # temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name - # assert_not temp_file, "File '#{temp_file_name}' should not exist yet." - # - # # Move the original file to BBBBBBBB.tmp. The original file should not change but a new file should be created. - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}" } - # ) - # assert_response :success # Created - # end - # - # # Verify that a new file has been created - # temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name - # assert temp_file, "File '#{temp_file_name}' not found, move failed." - # assert_equal temp_file.dmsf_file_revisions.count, 1 - # assert_not_equal temp_file.id, @file1.id - # - # # Move a temporary file (use BBBBBBBB.tmp) to the original file. - # assert_no_difference '@file1.dmsf_file_revisions.count' do - # process :move, "/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}", - # params: nil, - # headers: @jsmith.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file1.name}" } - # ) - # assert_response :success # Created - # end - # end - # - # def test_move_file_in_subproject - # dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/new_file_name" - # assert_difference '@file12.dmsf_file_revisions.count', +1 do - # process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@file12.name}", - # params: nil, - # headers: @admin.merge!({ destination: dest }) - # assert_response :created - # end - # end - # - # def test_move_folder_in_subproject - # dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/new_folder_name" - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}", - # params: nil, - # headers: @admin.merge!({ destination: dest }) - # assert_response :created - # @folder10.reload - # assert_equal 'new_folder_name', @folder10.title - # end - # - # def test_move_folder_in_subproject_to_the_same_name_as_subproject - # dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@project5.identifier}" - # process :move, - # "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}", - # params: nil, - # headers: @admin.merge!({ destination: dest }) - # assert_response :created - # @folder10.reload - # assert_equal @project5.identifier, @folder10.title - # end - # - # def test_move_subproject - # process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}", - # params: nil, - # headers: @admin.merge!( - # { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/new_project_name" } - # ) - # assert_response :method_not_allowed - # end + def test_move_when_file_is_locked_by_other + log_user 'admin', 'admin' # login as admin + User.current = @admin_user + assert @file1.lock!, "File failed to be locked by #{User.current}" + new_name = "#{@file1.name}.moved" + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :locked + end + end + + def test_move_when_file_is_locked_by_other_and_user_is_admin + log_user 'jsmith', 'jsmith' # login as jsmith + User.current = @jsmith_user + assert @file1.lock!, "File failed to be locked by #{User.current}" + + new_name = "#{@file1.name}.moved" + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @admin.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :locked + end + end + + def test_move_when_file_is_locked_by_user + log_user 'jsmith', 'jsmith' # login as jsmith + User.current = @jsmith_user + assert @file1.lock!, "File failed to be locked by #{User.current}" + + # Move once + new_name = "#{@file1.name}.m1" + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name}" } + ) + assert_response :success # Created + end + # Move twice, make sure that the MsOffice store sequence is not disrupting normal move + new_name2 = "#{new_name}.m2" + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{new_name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{new_name2}" } + ) + assert_response :success # Created + end + end + + def test_move_msoffice_save_locked_file + # When some versions of MsOffice save a file they use the following sequence: + # 1. Save changes to a new temporary document, XXX.tmp + # 2. Rename (MOVE) document to YYY.tmp. History is lost here if the original document is moved. + # 3. Rename (MOVE) XXX.tmp to document's name. XXX.tmp must be merged to the original document otherwise the + # history is lost. + # 4. Delete YYY.tmp. + # Verify that steps 2 and 3 work. + log_user 'jsmith', 'jsmith' # login as jsmith + User.current = @jsmith_user + assert @file1.lock!, "File failed to be locked by #{User.current}" + + # First save while the file is locked, should create new revision + temp_file_name = 'AAAAAAAA.tmp' + + # Make sure that the temp-file does not exist. + temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name + assert_not temp_file, "File '#{temp_file_name}' should not exist yet." + + # Move the original file to AAAAAAAA.tmp. The original file should not changed but a new file should be created. + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}" } + ) + assert_response :success # Created + end + + # Verify that a new file has been created + temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name + assert temp_file, "File '#{temp_file_name}' not found, move failed." + assert_equal temp_file.dmsf_file_revisions.count, 1 + assert_not_equal temp_file.id, @file1.id + + # Move a temporary file (use AAAAAAAA.tmp) to the original file. + assert_difference '@file1.dmsf_file_revisions.count', +1 do + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}", + params: nil, + headers: @jsmith.merge!( + { + destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + 'HTTP_OVERWRITE' => 'T' + } + ) + assert_response :success # Created + end + + # Second save while file is locked, should NOT create new revision + temp_file_name = 'BBBBBBBB.tmp' + + # Make sure that the temp-file does not exist. + temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name + assert_not temp_file, "File '#{temp_file_name}' should not exist yet." + + # Move the original file to BBBBBBBB.tmp. The original file should not change but a new file should be created. + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}" } + ) + assert_response :success # Created + end + + # Verify that a new file has been created + temp_file = DmsfFile.find_file_by_name @project1, nil, temp_file_name + assert temp_file, "File '#{temp_file_name}' not found, move failed." + assert_equal temp_file.dmsf_file_revisions.count, 1 + assert_not_equal temp_file.id, @file1.id + + # Move a temporary file (use BBBBBBBB.tmp) to the original file. + assert_no_difference '@file1.dmsf_file_revisions.count' do + process :move, "/dmsf/webdav/#{@project1.identifier}/#{temp_file_name}", + params: nil, + headers: @jsmith.merge!( + { destination: "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@file1.name}" } + ) + assert_response :success # Created + end + end + + def test_move_file_in_subproject + dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/new_file_name" + assert_difference '@file12.dmsf_file_revisions.count', +1 do + process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@file12.name}", + params: nil, + headers: @admin.merge!({ destination: dest }) + assert_response :created + end + end + + def test_move_folder_in_subproject + dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/new_folder_name" + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}", + params: nil, + headers: @admin.merge!({ destination: dest }) + assert_response :created + @folder10.reload + assert_equal 'new_folder_name', @folder10.title + end + + def test_move_folder_in_subproject_to_the_same_name_as_subproject + dest = "http://www.example.com/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@project5.identifier}" + process :move, + "/dmsf/webdav/#{@project1.identifier}/#{@project5.identifier}/#{@folder10.title}", + params: nil, + headers: @admin.merge!({ destination: dest }) + assert_response :created + @folder10.reload + assert_equal @project5.identifier, @folder10.title + end + + def test_move_subproject + process :move, "/dmsf/webdav/#{@project1.identifier}/#{@project5.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 diff --git a/test/integration/webdav/dmsf_webdav_put_test.rb b/test/integration/webdav/dmsf_webdav_put_test.rb index 34834ab3..c0b2638d 100644 --- a/test/integration/webdav/dmsf_webdav_put_test.rb +++ b/test/integration/webdav/dmsf_webdav_put_test.rb @@ -112,7 +112,7 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest file = DmsfFile.find_file_by_name @project1, nil, 'test-1234.txt' assert file, 'File test-1234 was not found in projects dmsf folder.' assert file.last_revision - assert_equal 'SHA256', file.last_revision.digest_type + assert_equal 'MD5', file.last_revision.digest_type with_settings plugin_redmine_dmsf: { 'dmsf_webdav_use_project_names' => '1', 'dmsf_webdav' => '1', @@ -381,17 +381,18 @@ class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest headers: @jsmith.merge!({ content_type: :text }) assert_response :created end - sha = Digest::SHA256.file(@file1.last_revision.disk_file) + sha = @file1.last_revision.file.checksum assert_equal sha, @file1.last_revision.digest end def test_put_version + assert_equal '1.0', @file1.last_revision.version assert_difference '@file1.dmsf_file_revisions.count', +1 do put "/dmsf/webdav/#{@project1.identifier}/#{@file1.name}", params: '1234', headers: @jsmith.merge!({ content_type: :text }) assert_response :created end - assert_equal '1.2', @file1.last_revision.version + assert_equal '1.1', @file1.dmsf_file_revisions.visible.first.version end end diff --git a/test/unit/project_patch_test.rb b/test/unit/project_patch_test.rb index 49060d9d..e3ad9943 100644 --- a/test/unit/project_patch_test.rb +++ b/test/unit/project_patch_test.rb @@ -72,23 +72,23 @@ class ProjectPatchTest < RedmineDmsf::Test::UnitTest assert_equal 5, @project1.dmsf_files.visible.all.size assert_equal 3, @project1.dmsf_folders.visible.all.size - assert_equal 2, @project1.file_links.visible.all.size - assert_equal 1, @project1.folder_links.visible.all.size - assert_equal 0, @project1.url_links.visible.all.size + assert_equal 2, @project1.file_links.all.size + assert_equal 1, @project1.folder_links.all.size + assert_equal 0, @project1.url_links.all.size - assert_equal 1, @project5.dmsf_files.visible.all.size - assert_equal 1, @project5.dmsf_folders.visible.all.size - assert_equal 0, @project5.file_links.visible.all.size - assert_equal 0, @project5.folder_links.visible.all.size - assert_equal 0, @project5.url_links.visible.all.size + assert_equal 1, @project5.dmsf_files.all.size + assert_equal 1, @project5.dmsf_folders.all.size + assert_equal 0, @project5.file_links.all.size + assert_equal 0, @project5.folder_links.all.size + assert_equal 0, @project5.url_links.all.size @project5.copy_dmsf @project1 - assert_equal 6, @project5.dmsf_files.visible.all.size - assert_equal 4, @project5.dmsf_folders.visible.all.size - assert_equal 2, @project5.file_links.visible.all.size - assert_equal 1, @project5.folder_links.visible.all.size - assert_equal 0, @project5.url_links.visible.all.size + assert_equal 6, @project5.dmsf_files.all.size + assert_equal 4, @project5.dmsf_folders.all.size + assert_equal 2, @project5.file_links.all.size + assert_equal 1, @project5.folder_links.all.size + assert_equal 0, @project5.url_links.all.size end def test_dmsf_avaliable