From b5c89607fdcc6486a7409714a7e51a8e209dfcf9 Mon Sep 17 00:00:00 2001 From: "COLA@Redmine.local" Date: Fri, 24 Feb 2017 21:51:53 +0100 Subject: [PATCH] Locking/unlocking a file invalidates relevant cache entries #674 Fixed PROPFIND/allprop to return correct props for ProjectResource. --- lib/redmine_dmsf/lockable.rb | 13 +++ .../webdav/dmsf_webdav_propfind_test.rb | 102 ++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/lib/redmine_dmsf/lockable.rb b/lib/redmine_dmsf/lockable.rb index 3b17dbff..f403f186 100644 --- a/lib/redmine_dmsf/lockable.rb +++ b/lib/redmine_dmsf/lockable.rb @@ -73,6 +73,12 @@ module RedmineDmsf l.save! reload locks.reload + + # Invalidate PROPFIND (for parent folder) + RedmineDmsf::Webdav::Cache.invalidate_item(self.propfind_cache_key) + # Invalidate PROPSTATS + RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{RedmineDmsf::Webdav::ProjectResource.create_project_name(self.project)}/#{self.dmsf_path_str}") if self.is_a?(DmsfFolder) + RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{self.id}-#{self.last_revision.id}") if self.is_a?(DmsfFile) return l end @@ -136,6 +142,13 @@ module RedmineDmsf end end end + + # Invalidate PROPFIND (for parent folder) + RedmineDmsf::Webdav::Cache.invalidate_item(self.propfind_cache_key) + # Invalidate PROPSTATS + RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{RedmineDmsf::Webdav::ProjectResource.create_project_name(self.project)}/#{self.dmsf_path_str}") if self.is_a?(DmsfFolder) + RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{self.id}-#{self.last_revision.id}") if self.is_a?(DmsfFile) + reload locks.reload end diff --git a/test/integration/webdav/dmsf_webdav_propfind_test.rb b/test/integration/webdav/dmsf_webdav_propfind_test.rb index ce412ef0..a91d51fa 100644 --- a/test/integration/webdav/dmsf_webdav_propfind_test.rb +++ b/test/integration/webdav/dmsf_webdav_propfind_test.rb @@ -372,4 +372,106 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") end + def test_propfind_depth1_on_project1_for_admin_with_cache_and_locks + RedmineDmsf::Webdav::Cache.init_testcache + + log_user 'admin', 'admin' # login as admin + assert !User.current.anonymous?, 'Current user is anonymous' + + assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +7 do + xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, + @admin.merge!({:HTTP_DEPTH => '1'}) + assert_response 207 # MultiStatus + end + + # Verify that everything exists in the cache as it should + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}") + + # Lock a file and verify that the PROPSTATS for the file and the PROPFIND were deleted + assert @file1.lock!, "File failed to be locked by #{User.current.name}" + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}") + + assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do + xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, + @admin.merge!({:HTTP_DEPTH => '1'}) + assert_response 207 # MultiStatus + end + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + + # Unlock a file and verify that the PROPSTATS for the file and the PROPFIND were deleted + assert @file1.unlock!, "File failed to be unlocked by #{User.current.name}" + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}") + + assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do + xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, + @admin.merge!({:HTTP_DEPTH => '1'}) + assert_response 207 # MultiStatus + end + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + + # Lock a folder and verify that the PROPSTATS for the file and the PROPFIND were deleted + assert @folder1.lock!, "File failed to be locked by #{User.current.name}" + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}") + + assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do + xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, + @admin.merge!({:HTTP_DEPTH => '1'}) + assert_response 207 # MultiStatus + end + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + + # Unlock a folder and verify that the PROPSTATS for the file and the PROPFIND were deleted + assert @folder1.unlock!, "File failed to be unlocked by #{User.current.name}" + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}") + + assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do + xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil, + @admin.merge!({:HTTP_DEPTH => '1'}) + assert_response 207 # MultiStatus + end + assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}") + assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid") + assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}") + end + end \ No newline at end of file