Add S3 ACL for DELETE Multiple Objects
Change-Id: Iff5ed59720a27b20a64087024c8a7fc2adb720b9
This commit is contained in:
@@ -45,6 +45,10 @@ class MultiObjectDeleteController(Controller):
|
||||
|
||||
yield key, version
|
||||
|
||||
# check bucket permission
|
||||
if CONF.s3_acl:
|
||||
req.get_response(self.app, 'HEAD')
|
||||
|
||||
try:
|
||||
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
|
||||
elem = fromstring(xml, 'Delete')
|
||||
|
||||
@@ -720,4 +720,7 @@ ACL_MAP = {
|
||||
('DELETE', 'DELETE', 'object'):
|
||||
{'Resource': 'container',
|
||||
'Permission': 'WRITE'},
|
||||
# DELETE Multiple Objects
|
||||
('POST', 'HEAD', 'container'):
|
||||
{'Permission': 'WRITE'},
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ from swift.common.swob import Request
|
||||
from swift3.test.unit import Swift3TestCase
|
||||
from swift3.etree import fromstring, tostring, Element, SubElement
|
||||
from swift3.cfg import CONF
|
||||
from swift3.test.unit.test_s3_acl import s3acl
|
||||
|
||||
|
||||
class TestSwift3MultiDelete(Swift3TestCase):
|
||||
@@ -30,6 +31,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
def setUp(self):
|
||||
super(TestSwift3MultiDelete, self).setUp()
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_to_object(self):
|
||||
elem = Element('Delete')
|
||||
obj = SubElement(elem, 'Object')
|
||||
@@ -46,6 +48,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
status, headers, body = self.call_swift3(req)
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE(self):
|
||||
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1',
|
||||
swob.HTTPNoContent, {}, None)
|
||||
@@ -72,6 +75,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
elem = fromstring(body)
|
||||
self.assertEquals(len(elem.findall('Deleted')), 2)
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_quiet(self):
|
||||
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1',
|
||||
swob.HTTPNoContent, {}, None)
|
||||
@@ -97,6 +101,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
elem = fromstring(body)
|
||||
self.assertEquals(len(elem.findall('Deleted')), 0)
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_no_key(self):
|
||||
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1',
|
||||
swob.HTTPNoContent, {}, None)
|
||||
@@ -119,6 +124,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
status, headers, body = self.call_swift3(req)
|
||||
self.assertEquals(self._get_error_code(body), 'UserKeyMustBeSpecified')
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_with_invalid_md5(self):
|
||||
elem = Element('Delete')
|
||||
for key in ['Key1', 'Key2']:
|
||||
@@ -134,6 +140,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
status, headers, body = self.call_swift3(req)
|
||||
self.assertEquals(self._get_error_code(body), 'InvalidDigest')
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_without_md5(self):
|
||||
elem = Element('Delete')
|
||||
for key in ['Key1', 'Key2']:
|
||||
@@ -148,6 +155,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
status, headers, body = self.call_swift3(req)
|
||||
self.assertEquals(self._get_error_code(body), 'InvalidRequest')
|
||||
|
||||
@s3acl
|
||||
def test_object_multi_DELETE_too_many_keys(self):
|
||||
elem = Element('Delete')
|
||||
for i in range(CONF.max_multi_delete_objects + 1):
|
||||
@@ -164,5 +172,48 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
status, headers, body = self.call_swift3(req)
|
||||
self.assertEquals(self._get_error_code(body), 'MalformedXML')
|
||||
|
||||
def _test_object_multi_DELETE(self, account):
|
||||
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1',
|
||||
swob.HTTPNoContent, {}, None)
|
||||
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2',
|
||||
swob.HTTPNotFound, {}, None)
|
||||
|
||||
elem = Element('Delete')
|
||||
for key in ['Key1', 'Key2']:
|
||||
obj = SubElement(elem, 'Object')
|
||||
SubElement(obj, 'Key').text = key
|
||||
body = tostring(elem, use_s3ns=False)
|
||||
content_md5 = md5(body).digest().encode('base64').strip()
|
||||
|
||||
req = Request.blank('/bucket?delete',
|
||||
environ={'REQUEST_METHOD': 'POST'},
|
||||
headers={'Authorization': 'AWS %s:hmac' % account,
|
||||
'Content-MD5': content_md5},
|
||||
body=body)
|
||||
req.date = datetime.now()
|
||||
req.content_type = 'text/plain'
|
||||
|
||||
return self.call_swift3(req)
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_multi_DELETE_without_permission(self):
|
||||
status, headers, body = self._test_object_multi_DELETE('test:other')
|
||||
self.assertEquals(self._get_error_code(body), 'AccessDenied')
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_multi_DELETE_with_write_permission(self):
|
||||
status, headers, body = self._test_object_multi_DELETE('test:write')
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
elem = fromstring(body)
|
||||
self.assertEquals(len(elem.findall('Deleted')), 2)
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_multi_DELETE_with_fullcontrol_permission(self):
|
||||
status, headers, body = \
|
||||
self._test_object_multi_DELETE('test:full_control')
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
elem = fromstring(body)
|
||||
self.assertEquals(len(elem.findall('Deleted')), 2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user