Merge branch 'master' into feature/update_to_recent_rs_spec
# Conflicts: # spec/swift/app_spec.rb
This commit is contained in:
commit
28b6a7f22d
@ -24,12 +24,14 @@ module RemoteStorage
|
|||||||
return true if ["GET", "HEAD"].include?(request_method) && !listing
|
return true if ["GET", "HEAD"].include?(request_method) && !listing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
server.halt 401, "Unauthorized" if token.empty?
|
||||||
|
|
||||||
authorizations = redis.smembers("authorizations:#{user}:#{token}")
|
authorizations = redis.smembers("authorizations:#{user}:#{token}")
|
||||||
permission = directory_permission(authorizations, directory)
|
permission = directory_permission(authorizations, directory)
|
||||||
|
|
||||||
server.halt 401 unless permission
|
server.halt 401, "Unauthorized" unless permission
|
||||||
if ["PUT", "DELETE"].include? request_method
|
if ["PUT", "DELETE"].include? request_method
|
||||||
server.halt 401 unless permission == "rw"
|
server.halt 401, "Unauthorized" unless permission == "rw"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ module RemoteStorage
|
|||||||
|
|
||||||
return res.body
|
return res.body
|
||||||
rescue RestClient::ResourceNotFound
|
rescue RestClient::ResourceNotFound
|
||||||
server.halt 404
|
server.halt 404, "Not Found"
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_head_directory_listing(user, directory)
|
def get_head_directory_listing(user, directory)
|
||||||
@ -131,16 +133,16 @@ module RemoteStorage
|
|||||||
|
|
||||||
def put_data(user, directory, key, data, content_type)
|
def put_data(user, directory, key, data, content_type)
|
||||||
server.halt 400 if server.env["HTTP_CONTENT_RANGE"]
|
server.halt 400 if server.env["HTTP_CONTENT_RANGE"]
|
||||||
server.halt 409 if has_name_collision?(user, directory, key)
|
server.halt 409, "Conflict" if has_name_collision?(user, directory, key)
|
||||||
|
|
||||||
existing_metadata = redis.hgetall redis_metadata_object_key(user, directory, key)
|
existing_metadata = redis.hgetall redis_metadata_object_key(user, directory, key)
|
||||||
url = url_for_key(user, directory, key)
|
url = url_for_key(user, directory, key)
|
||||||
|
|
||||||
if required_match = server.env["HTTP_IF_MATCH"]
|
if required_match = server.env["HTTP_IF_MATCH"]
|
||||||
server.halt 412 unless required_match == %Q("#{existing_metadata["e"]}")
|
server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}")
|
||||||
end
|
end
|
||||||
if server.env["HTTP_IF_NONE_MATCH"] == "*"
|
if server.env["HTTP_IF_NONE_MATCH"] == "*"
|
||||||
server.halt 412 unless existing_metadata.empty?
|
server.halt 412, "Precondition Failed" unless existing_metadata.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
res = do_put_request(url, data, content_type)
|
res = do_put_request(url, data, content_type)
|
||||||
@ -176,7 +178,7 @@ module RemoteStorage
|
|||||||
existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}"
|
existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}"
|
||||||
|
|
||||||
if required_match = server.env["HTTP_IF_MATCH"]
|
if required_match = server.env["HTTP_IF_MATCH"]
|
||||||
server.halt 412 unless required_match == %Q("#{existing_metadata["e"]}")
|
server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}")
|
||||||
end
|
end
|
||||||
|
|
||||||
do_delete_request(url)
|
do_delete_request(url)
|
||||||
@ -186,7 +188,7 @@ module RemoteStorage
|
|||||||
server.headers["Etag"] = %Q("#{existing_metadata["e"]}")
|
server.headers["Etag"] = %Q("#{existing_metadata["e"]}")
|
||||||
server.halt 200
|
server.halt 200
|
||||||
rescue RestClient::ResourceNotFound
|
rescue RestClient::ResourceNotFound
|
||||||
server.halt 404
|
server.halt 404, "Not Found"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -134,6 +134,7 @@ describe "App" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
last_response.status.must_equal 409
|
last_response.status.must_equal 409
|
||||||
|
last_response.body.must_equal "Conflict"
|
||||||
|
|
||||||
metadata = redis.hgetall "rs:m:phil:food"
|
metadata = redis.hgetall "rs:m:phil:food"
|
||||||
metadata.must_be_empty
|
metadata.must_be_empty
|
||||||
@ -164,15 +165,113 @@ describe "App" do
|
|||||||
last_response.status.must_equal 400
|
last_response.status.must_equal 400
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "If-Match header" do
|
||||||
|
before do
|
||||||
|
put_stub = OpenStruct.new(headers: {
|
||||||
|
etag: "oldetag",
|
||||||
|
last_modified: "Fri, 04 Mar 2016 12:20:18 GMT"
|
||||||
|
})
|
||||||
|
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows the request if the header matches the current ETag" do
|
||||||
|
header "If-Match", "\"oldetag\""
|
||||||
|
|
||||||
|
put_stub = OpenStruct.new(headers: {
|
||||||
|
etag: "newetag",
|
||||||
|
last_modified: "Fri, 04 Mar 2016 12:20:18 GMT"
|
||||||
|
})
|
||||||
|
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "aye"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 200
|
||||||
|
last_response.headers["Etag"].must_equal "\"newetag\""
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails the request if the header does not match the current ETag" do
|
||||||
|
header "If-Match", "someotheretag"
|
||||||
|
|
||||||
|
put "/phil/food/aguacate", "aye"
|
||||||
|
|
||||||
|
last_response.status.must_equal 412
|
||||||
|
last_response.body.must_equal "Precondition Failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "If-None-Match header set to '*'" do
|
||||||
|
it "succeeds when the document doesn't exist yet" do
|
||||||
|
put_stub = OpenStruct.new(headers: {
|
||||||
|
etag: "someetag",
|
||||||
|
last_modified: "Fri, 04 Mar 2016 12:20:18 GMT"
|
||||||
|
})
|
||||||
|
|
||||||
|
header "If-None-Match", "*"
|
||||||
|
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 200
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails the request if the document already exsits" do
|
||||||
|
put_stub = OpenStruct.new(headers: {
|
||||||
|
etag: "someetag",
|
||||||
|
last_modified: "Fri, 04 Mar 2016 12:20:18 GMT"
|
||||||
|
})
|
||||||
|
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
end
|
||||||
|
|
||||||
|
header "If-None-Match", "*"
|
||||||
|
RestClient.stub :put, put_stub do
|
||||||
|
put "/phil/food/aguacate", "si"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 412
|
||||||
|
last_response.body.must_equal "Precondition Failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
describe "DELETE requests" do
|
describe "DELETE requests" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
purge_redis
|
purge_redis
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "not authorized" do
|
||||||
|
|
||||||
|
describe "with no token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
delete "/phil/food/aguacate"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_equal "Unauthorized"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with wrong token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
header "Authorization", "Bearer wrongtoken"
|
||||||
|
delete "/phil/food/aguacate"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_equal "Unauthorized"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
context "authorized" do
|
context "authorized" do
|
||||||
before do
|
before do
|
||||||
redis.sadd "authorizations:phil:amarillo", [":rw"]
|
redis.sadd "authorizations:phil:amarillo", [":rw"]
|
||||||
@ -240,13 +339,44 @@ describe "App" do
|
|||||||
redis.smembers("rs:m:phil:/:items").must_be_empty
|
redis.smembers("rs:m:phil:/:items").must_be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
it "responds with the ETag of the deleted item in the haeder" do
|
it "responds with the ETag of the deleted item in the header" do
|
||||||
RestClient.stub :delete, "" do
|
RestClient.stub :delete, "" do
|
||||||
delete "/phil/food/aguacate"
|
delete "/phil/food/aguacate"
|
||||||
end
|
end
|
||||||
|
|
||||||
last_response.headers["ETag"].must_equal "\"bla\""
|
last_response.headers["ETag"].must_equal "\"bla\""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns a 404 when item doesn't exist" do
|
||||||
|
raises_exception = ->(url, headers) { raise RestClient::ResourceNotFound.new }
|
||||||
|
RestClient.stub :delete, raises_exception do
|
||||||
|
delete "/phil/food/steak"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 404
|
||||||
|
last_response.body.must_equal "Not Found"
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "If-Match header" do
|
||||||
|
it "succeeds when the header matches the current ETag" do
|
||||||
|
header "If-Match", "\"bla\""
|
||||||
|
|
||||||
|
RestClient.stub :delete, "" do
|
||||||
|
delete "/phil/food/aguacate"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 200
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails the request if it does not match the current ETag" do
|
||||||
|
header "If-Match", "someotheretag"
|
||||||
|
|
||||||
|
delete "/phil/food/aguacate"
|
||||||
|
|
||||||
|
last_response.status.must_equal 412
|
||||||
|
last_response.body.must_equal "Precondition Failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -256,6 +386,29 @@ describe "App" do
|
|||||||
purge_redis
|
purge_redis
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "not authorized" do
|
||||||
|
|
||||||
|
describe "without token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
get "/phil/food/"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_equal "Unauthorized"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with wrong token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
header "Authorization", "Bearer wrongtoken"
|
||||||
|
get "/phil/food/"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_equal "Unauthorized"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
context "authorized" do
|
context "authorized" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@ -294,6 +447,16 @@ describe "App" do
|
|||||||
last_response.headers["Content-Type"].must_equal "text/plain; charset=utf-8"
|
last_response.headers["Content-Type"].must_equal "text/plain; charset=utf-8"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns a 404 when data doesn't exist" do
|
||||||
|
raises_exception = ->(url, headers) { raise RestClient::ResourceNotFound.new }
|
||||||
|
RestClient.stub :get, raises_exception do
|
||||||
|
get "/phil/food/steak"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 404
|
||||||
|
last_response.body.must_equal "Not Found"
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "directory listings" do
|
describe "directory listings" do
|
||||||
@ -371,6 +534,29 @@ describe "App" do
|
|||||||
purge_redis
|
purge_redis
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "not authorized" do
|
||||||
|
|
||||||
|
describe "without token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
head "/phil/food/camarones"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with wrong token" do
|
||||||
|
it "says it's not authorized" do
|
||||||
|
header "Authorization", "Bearer wrongtoken"
|
||||||
|
head "/phil/food/camarones"
|
||||||
|
|
||||||
|
last_response.status.must_equal 401
|
||||||
|
last_response.body.must_be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
context "authorized" do
|
context "authorized" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@ -399,6 +585,18 @@ describe "App" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "data" do
|
||||||
|
it "returns a 404 when data doesn't exist" do
|
||||||
|
raises_exception = ->(url, headers) { raise RestClient::ResourceNotFound.new }
|
||||||
|
RestClient.stub :head, raises_exception do
|
||||||
|
head "/phil/food/steak"
|
||||||
|
end
|
||||||
|
|
||||||
|
last_response.status.must_equal 404
|
||||||
|
last_response.body.must_be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user