From 6342cb387a8538a8b59e4a4ba9e2574ac23ff45f Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Tue, 15 Oct 2013 17:46:01 +0200 Subject: [PATCH] Handle COPY verb in account quota middleware Since COPY verb allow to copy an existing object we must check the size of the source object before allowing the copy. Fixes bug: #1201884 Change-Id: Ia37bc716be0c3e5a3174dc4370bb5084f81073ad --- swift/common/middleware/account_quotas.py | 8 +++- .../common/middleware/test_account_quotas.py | 48 +++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/swift/common/middleware/account_quotas.py b/swift/common/middleware/account_quotas.py index 917fd4f45b..87399af772 100644 --- a/swift/common/middleware/account_quotas.py +++ b/swift/common/middleware/account_quotas.py @@ -63,7 +63,7 @@ class AccountQuotaMiddleware(object): @wsgify def __call__(self, request): - if request.method not in ("POST", "PUT"): + if request.method not in ("POST", "PUT", "COPY"): return self.app try: @@ -98,7 +98,11 @@ class AccountQuotaMiddleware(object): if obj and request.method == "POST" or not obj: return self.app - copy_from = request.headers.get('X-Copy-From') + if request.method == 'COPY': + copy_from = container + '/' + obj + else: + copy_from = request.headers.get('X-Copy-From') + content_length = (request.content_length or 0) if obj and copy_from: diff --git a/test/unit/common/middleware/test_account_quotas.py b/test/unit/common/middleware/test_account_quotas.py index 9854fb605a..d24af41bfb 100644 --- a/test/unit/common/middleware/test_account_quotas.py +++ b/test/unit/common/middleware/test_account_quotas.py @@ -186,9 +186,23 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 413) + def test_exceed_bytes_quota_copy_verb(self): + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache}, + headers={'Destination': '/c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 413) + def test_not_exceed_bytes_quota_copy_from(self): headers = [('x-account-bytes-used', '0'), - ('x-account-meta-quota-bytes', '1000')] + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) cache = FakeCache(None) req = Request.blank('/v1/a/c/o', @@ -198,6 +212,19 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 200) + def test_not_exceed_bytes_quota_copy_verb(self): + headers = [('x-account-bytes-used', '0'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache}, + headers={'Destination': '/c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 200) + def test_quota_copy_from_no_src(self): headers = [('x-account-bytes-used', '0'), ('x-account-meta-quota-bytes', '1000')] @@ -223,8 +250,9 @@ class TestAccountQuota(unittest.TestCase): self.assertEquals(res.status_int, 200) def test_exceed_bytes_quota_reseller_copy_from(self): - headers = [('x-account-bytes-used', '1000'), - ('x-account-meta-quota-bytes', '0')] + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) cache = FakeCache(None) req = Request.blank('/v1/a/c/o', @@ -235,6 +263,20 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 200) + def test_exceed_bytes_quota_reseller_copy_verb(self): + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache, + 'reseller_request': True}, + headers={'Destination': 'c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 200) + def test_bad_application_quota(self): headers = [] app = account_quotas.AccountQuotaMiddleware(FakeBadApp(headers))