From fd3293025d3b1ea08db6dc3664917a328d42ed78 Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Fri, 4 Mar 2016 19:32:36 +0100 Subject: [PATCH 1/4] ETags are quoted, doh --- lib/remote_storage/swift.rb | 4 ++-- spec/swift/app_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index e8a9a7d..6a88013 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -72,14 +72,14 @@ module RemoteStorage none_match = (server.env["HTTP_IF_NONE_MATCH"] || "").split(",").map(&:strip) if etag - server.halt 304 if none_match.include? etag + server.halt 304 if none_match.include? %Q("#{etag}") items = get_directory_listing_from_redis_via_lua(user, directory) else etag = etag_for(user, directory) items = {} - server.halt 304 if none_match.include? etag + server.halt 304 if none_match.include? %Q("#{etag}") end server.headers["ETag"] = %Q("#{etag}") diff --git a/spec/swift/app_spec.rb b/spec/swift/app_spec.rb index 0da57a4..1f244f7 100644 --- a/spec/swift/app_spec.rb +++ b/spec/swift/app_spec.rb @@ -271,7 +271,7 @@ describe "App" do end it "responds with 304 when IF_NONE_MATCH header contains the ETag" do - header "If-None-Match", "a693babe4b4027de2340b4f1c362d2c8" + header "If-None-Match", "\"a693babe4b4027de2340b4f1c362d2c8\"" get "/phil/food/" last_response.status.must_equal 304 From 43ff83d26b8907ff8d1d4825b317ed2ad21acc52 Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Fri, 4 Mar 2016 19:33:00 +0100 Subject: [PATCH 2/4] Don't allow PUTS with Content-Range header --- lib/remote_storage/swift.rb | 1 + spec/swift/app_spec.rb | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index 6a88013..6427200 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -130,6 +130,7 @@ module RemoteStorage end def put_data(user, directory, key, data, content_type) + server.halt 400 if server.env["HTTP_CONTENT_RANGE"] server.halt 409 if has_name_collision?(user, directory, key) existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}" diff --git a/spec/swift/app_spec.rb b/spec/swift/app_spec.rb index 1f244f7..e29b629 100644 --- a/spec/swift/app_spec.rb +++ b/spec/swift/app_spec.rb @@ -129,6 +129,14 @@ describe "App" do metadata = redis.hgetall "rs:m:phil:food/aguacate/empanado" metadata.must_be_empty end + + it "returns 400 when a Content-Range header is sent" do + header "Content-Range", "bytes 0-3/3" + + put "/phil/food/aguacate", "si" + + last_response.status.must_equal 400 + end end end end From 1c0bd18915dd5be36b6c9acbc3f5438e3593b0cc Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Fri, 4 Mar 2016 20:34:48 +0100 Subject: [PATCH 3/4] Delete obsolete method --- lib/remote_storage/swift.rb | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index 6427200..1889f18 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -221,35 +221,6 @@ module RemoteStorage permission end - def directory_listing(res_body) - listing = { - "@context" => "http://remotestorage.io/spec/folder-description", - "items" => {} - } - - res_body.each do |entry| - name = entry["name"] - name.sub!("#{File.dirname(entry["name"])}/", '') - if name[-1] == "/" # It's a directory - listing["items"].merge!({ - name => { - "ETag" => entry["hash"], - } - }) - else # It's a file - listing["items"].merge!({ - name => { - "ETag" => entry["hash"], - "Content-Type" => entry["content_type"], - "Content-Length" => entry["bytes"] - } - }) - end - end - - listing - end - def has_name_collision?(user, directory, key) lua_script = <<-EOF local user = ARGV[1] From 3590b7dedc4a29304986e9fc23ce40900b4e0c70 Mon Sep 17 00:00:00 2001 From: Garret Alfert Date: Fri, 4 Mar 2016 20:47:41 +0100 Subject: [PATCH 4/4] Determine correct metadata key for objects in root dir --- lib/remote_storage/swift.rb | 11 +++++++---- spec/swift/app_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index 1889f18..00bda35 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -133,7 +133,7 @@ module RemoteStorage server.halt 400 if server.env["HTTP_CONTENT_RANGE"] server.halt 409 if has_name_collision?(user, directory, key) - existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}" + existing_metadata = redis.hgetall redis_metadata_object_key(user, directory, key) url = url_for_key(user, directory, key) if required_match = server.env["HTTP_IF_MATCH"] @@ -309,7 +309,7 @@ module RemoteStorage end def update_metadata_object(user, directory, key, metadata) - redis_key = "rs:m:#{user}:#{directory}/#{key}" + redis_key = redis_metadata_object_key(user, directory, key) redis.hmset(redis_key, *metadata) redis.sadd "rs:m:#{user}:#{directory}/:items", key @@ -328,8 +328,7 @@ module RemoteStorage end def delete_metadata_objects(user, directory, key) - redis_key = "rs:m:#{user}:#{directory}/#{key}" - redis.del(redis_key) + redis.del redis_metadata_object_key(user, directory, key) redis.srem "rs:m:#{user}:#{directory}/:items", key end @@ -353,6 +352,10 @@ module RemoteStorage redis.smembers("rs:m:#{user}:#{dir}/:items").empty? end + def redis_metadata_object_key(user, directory, key) + "rs:m:#{user}:#{[directory, key].delete_if(&:empty?).join("/")}" + end + def container_url_for(user) "#{base_url}/#{container_for(user)}" end diff --git a/spec/swift/app_spec.rb b/spec/swift/app_spec.rb index e29b629..6e8a7a7 100644 --- a/spec/swift/app_spec.rb +++ b/spec/swift/app_spec.rb @@ -74,6 +74,32 @@ describe "App" do root_items.must_equal ["food/"] end + describe "objects in root dir" do + before do + put_stub = OpenStruct.new(headers: { + etag: "bla", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT" + }) + + RestClient.stub :put, put_stub do + put "/phil/bamboo.txt", "shir kan" + end + end + + it "are listed in the directory listing with all metadata" do + get "phil/" + + last_response.status.must_equal 200 + last_response.content_type.must_equal "application/json" + + content = JSON.parse(last_response.body) + content["items"]["bamboo.txt"].wont_be_nil + content["items"]["bamboo.txt"]["ETag"].must_equal "bla" + content["items"]["bamboo.txt"]["Content-Type"].must_equal "text/plain; charset=utf-8" + content["items"]["bamboo.txt"]["Content-Length"].must_equal 8 + end + end + describe "name collision checks" do it "is successful when there is no name collision" do put_stub = OpenStruct.new(headers: {