Don't allow directory listings of the public directory without proper permissions (refs #19)
This commit is contained in:
parent
6541b97997
commit
39355ff0f2
@ -23,9 +23,12 @@ module RemoteStorage
|
||||
@auth_bucket ||= client.bucket(LiquorCabinet.config['buckets']['authorizations'])
|
||||
end
|
||||
|
||||
def authorize_request(user, directory, token)
|
||||
def authorize_request(user, directory, token, listing=false)
|
||||
request_method = env["REQUEST_METHOD"]
|
||||
return true if directory.split("/").first == "public" && request_method == "GET"
|
||||
|
||||
if directory.split("/").first == "public"
|
||||
return true if request_method == "GET" && !listing
|
||||
end
|
||||
|
||||
authorizations = auth_bucket.get("#{user}:#{token}").data
|
||||
permission = directory_permission(authorizations, directory)
|
||||
@ -125,10 +128,11 @@ module RemoteStorage
|
||||
permission = authorizations[""]
|
||||
|
||||
authorizations.each do |key, value|
|
||||
if directory.match key
|
||||
if directory.match /^(public\/)?#{key}(\/|$)/
|
||||
if permission.nil? || permission == "r"
|
||||
permission = value
|
||||
end
|
||||
return permission if permission == "rw"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,7 +49,7 @@ class LiquorCabinet < Sinatra::Base
|
||||
|
||||
token = env["HTTP_AUTHORIZATION"] ? env["HTTP_AUTHORIZATION"].split(" ")[1] : ""
|
||||
|
||||
authorize_request(@user, @directory, token) unless request.options?
|
||||
authorize_request(@user, @directory, token, @key.blank?) unless request.options?
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -15,7 +15,6 @@ describe "Directories" do
|
||||
end
|
||||
|
||||
describe "GET listing" do
|
||||
|
||||
before do
|
||||
put "/jimmy/tasks/foo", "do the laundry"
|
||||
put "/jimmy/tasks/http%3A%2F%2F5apps.com", "prettify design"
|
||||
@ -175,6 +174,62 @@ describe "Directories" do
|
||||
content["tasks/"].to_s.length.must_equal 13
|
||||
end
|
||||
end
|
||||
|
||||
context "for the public directory" do
|
||||
before do
|
||||
auth = auth_bucket.new("jimmy:123")
|
||||
auth.data = ["documents:r", "bookmarks:rw"]
|
||||
auth.store
|
||||
|
||||
put "/jimmy/public/bookmarks/5apps", "http://5apps.com"
|
||||
end
|
||||
|
||||
context "when authorized for the category" do
|
||||
it "lists the files" do
|
||||
get "/jimmy/public/bookmarks/"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
|
||||
content = JSON.parse(last_response.body)
|
||||
content.must_include "5apps"
|
||||
end
|
||||
end
|
||||
|
||||
context "when directly authorized for the public directory" do
|
||||
before do
|
||||
auth = auth_bucket.new("jimmy:123")
|
||||
auth.data = ["documents:r", "public/bookmarks:rw"]
|
||||
auth.store
|
||||
end
|
||||
|
||||
it "lists the files" do
|
||||
get "/jimmy/public/bookmarks/"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
|
||||
content = JSON.parse(last_response.body)
|
||||
content.must_include "5apps"
|
||||
end
|
||||
end
|
||||
|
||||
context "when not authorized" do
|
||||
before do
|
||||
auth_bucket.delete("jimmy:123")
|
||||
end
|
||||
|
||||
it "does not allow a directory listing of the public root" do
|
||||
get "/jimmy/public/"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
|
||||
it "does not allow a directory listing of a sub-directory" do
|
||||
get "/jimmy/public/bookmarks/"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "directory object" do
|
||||
|
@ -134,6 +134,32 @@ describe "Permissions" do
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
end
|
||||
|
||||
context "to the public directory" do
|
||||
context "when authorized for the corresponding category" do
|
||||
it "saves the value" do
|
||||
put "/jimmy/public/contacts/foo", "Foo Bar"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
data_bucket.get("jimmy:public/contacts:foo").data.must_equal "Foo Bar"
|
||||
end
|
||||
|
||||
it "saves the value to a sub-directory" do
|
||||
put "/jimmy/public/contacts/family/foo", "Foo Bar"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
data_bucket.get("jimmy:public/contacts/family:foo").data.must_equal "Foo Bar"
|
||||
end
|
||||
end
|
||||
|
||||
context "when not authorized for the corresponding category" do
|
||||
it "returns a 403" do
|
||||
put "/jimmy/public/documents/foo", "Foo Bar"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE" do
|
||||
@ -175,6 +201,24 @@ describe "Permissions" do
|
||||
data_bucket.get("jimmy:tasks/home:1")
|
||||
}.must_raise Riak::HTTPFailedRequest
|
||||
end
|
||||
|
||||
context "public directory" do
|
||||
before do
|
||||
object = data_bucket.new("jimmy:public/tasks:open")
|
||||
object.content_type = "text/plain"
|
||||
object.data = "hello world"
|
||||
object.store
|
||||
end
|
||||
|
||||
it "removes the key" do
|
||||
delete "/jimmy/public/tasks/open"
|
||||
|
||||
last_response.status.must_equal 204
|
||||
lambda {
|
||||
data_bucket.get("jimmy:public/tasks:open")
|
||||
}.must_raise Riak::HTTPFailedRequest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when not authorized" do
|
||||
@ -201,6 +245,21 @@ describe "Permissions" do
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
|
||||
context "public directory" do
|
||||
before do
|
||||
object = data_bucket.new("jimmy:public/documents:foo")
|
||||
object.content_type = "text/plain"
|
||||
object.data = "some private, authorized text data"
|
||||
object.store
|
||||
end
|
||||
|
||||
it "returns a 403" do
|
||||
delete "/jimmy/public/documents/foo"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -275,6 +334,37 @@ describe "Permissions" do
|
||||
}.must_raise Riak::HTTPFailedRequest
|
||||
end
|
||||
end
|
||||
|
||||
context "public directory" do
|
||||
before do
|
||||
object = data_bucket.new("jimmy:public/tasks:hello")
|
||||
object.content_type = "text/plain"
|
||||
object.data = "Hello World"
|
||||
object.store
|
||||
end
|
||||
|
||||
it "allows GET requests" do
|
||||
get "/jimmy/public/tasks/"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
end
|
||||
|
||||
it "allows PUT requests" do
|
||||
put "/jimmy/public/1", "Hello World"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
data_bucket.get("jimmy:public:1").data.must_equal "Hello World"
|
||||
end
|
||||
|
||||
it "allows DELETE requests" do
|
||||
delete "/jimmy/public/tasks/hello"
|
||||
|
||||
last_response.status.must_equal 204
|
||||
lambda {
|
||||
data_bucket.get("jimmy:public/tasks:hello")
|
||||
}.must_raise Riak::HTTPFailedRequest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "read all" do
|
||||
@ -304,6 +394,33 @@ describe "Permissions" do
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
|
||||
context "public directory" do
|
||||
before do
|
||||
object = data_bucket.new("jimmy:public/tasks:hello")
|
||||
object.content_type = "text/plain"
|
||||
object.data = "Hello World"
|
||||
object.store
|
||||
end
|
||||
|
||||
it "allows GET requests" do
|
||||
get "/jimmy/tasks/"
|
||||
|
||||
last_response.status.must_equal 200
|
||||
end
|
||||
|
||||
it "disallows PUT requests" do
|
||||
put "/jimmy/tasks/foo", "some text"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
|
||||
it "disallows DELETE requests" do
|
||||
delete "/jimmy/tasks/hello"
|
||||
|
||||
last_response.status.must_equal 403
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user