From 8e355ba5322bc58883d76f02a94937fa5148907f Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Tue, 23 Sep 2014 17:59:28 +0200 Subject: [PATCH] Respond with 409 on naming collisions between documents and folders --- lib/remote_storage/riak.rb | 28 ++++++++++++++++++++++++++++ spec/riak_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/lib/remote_storage/riak.rb b/lib/remote_storage/riak.rb index 0bca506..1add990 100644 --- a/lib/remote_storage/riak.rb +++ b/lib/remote_storage/riak.rb @@ -98,6 +98,8 @@ module RemoteStorage end def put_data(user, directory, key, data, content_type=nil) + server.halt 409 if has_name_collision?(user, directory, key) + object = build_data_object(user, directory, key, data, content_type) if required_match = server.env["HTTP_IF_MATCH"] @@ -439,6 +441,32 @@ module RemoteStorage parent_directories << "" end + def has_name_collision?(user, directory, key) + parent_directories = parent_directories_for(directory).reverse + parent_directories.shift # remove root dir entry + + # check for existing documents with the same name as one of the parent directories + parent_directories.each do |dir| + begin + parts = dir.split("/") + document_key = parts.pop + directory_name = parts.join("/") + data_bucket.get("#{user}:#{directory_name}:#{document_key}") + return true + rescue ::Riak::HTTPFailedRequest + end + end + + # check for an existing directory with same name as document + begin + directory_bucket.get("#{user}:#{directory}/#{key}") + return true + rescue ::Riak::HTTPFailedRequest + end + + false + end + def client @client ||= ::Riak::Client.new(:host => settings['host'], :http_port => settings['http_port']) diff --git a/spec/riak_spec.rb b/spec/riak_spec.rb index 6e8051e..e17a5a4 100644 --- a/spec/riak_spec.rb +++ b/spec/riak_spec.rb @@ -302,6 +302,32 @@ describe "App with Riak backend" do end end + describe "naming collissions between documents and directories" do + before do + put "/jimmy/documents/archive/document", "lorem ipsum" + end + + it "responds with 409 when directory with same name already exists" do + put "/jimmy/documents/archive", "some awesome content" + + last_response.status.must_equal 409 + + lambda { + data_bucket.get("jimmy:documents/archive") + }.must_raise Riak::HTTPFailedRequest + end + + it "responds with 409 when there is an existing document with same name as one of the directories" do + put "/jimmy/documents/archive/document/subdir/doc", "some awesome content" + + last_response.status.must_equal 409 + + lambda { + data_bucket.get("jimmy:documents/archive/document/subdir/doc") + }.must_raise Riak::HTTPFailedRequest + end + end + describe "with existing content" do before do put "/jimmy/documents/archive/foo", "lorem ipsum"