Merge "Fix response of DELETE Multiple Objects without bucket write permission"
This commit is contained in:
@@ -17,7 +17,7 @@ from swift3.controllers.base import Controller, bucket_operation
|
||||
from swift3.etree import Element, SubElement, fromstring, tostring, \
|
||||
XMLSyntaxError, DocumentInvalid
|
||||
from swift3.response import HTTPOk, S3NotImplemented, NoSuchKey, \
|
||||
ErrorResponse, MalformedXML, UserKeyMustBeSpecified
|
||||
ErrorResponse, MalformedXML, UserKeyMustBeSpecified, AccessDenied
|
||||
from swift3.cfg import CONF
|
||||
from swift3.utils import LOGGER
|
||||
|
||||
@@ -29,6 +29,19 @@ class MultiObjectDeleteController(Controller):
|
||||
Handles Delete Multiple Objects, which is logged as a MULTI_OBJECT_DELETE
|
||||
operation in the S3 server log.
|
||||
"""
|
||||
def _gen_error_body(self, error, elem, delete_list):
|
||||
for key, version in delete_list:
|
||||
if version is not None:
|
||||
# TODO: delete the specific version of the object
|
||||
raise S3NotImplemented()
|
||||
|
||||
error_elem = SubElement(elem, 'Error')
|
||||
SubElement(error_elem, 'Key').text = key
|
||||
SubElement(error_elem, 'Code').text = error.__class__.__name__
|
||||
SubElement(error_elem, 'Message').text = error._msg
|
||||
|
||||
return tostring(elem)
|
||||
|
||||
@bucket_operation
|
||||
def POST(self, req):
|
||||
"""
|
||||
@@ -45,9 +58,6 @@ class MultiObjectDeleteController(Controller):
|
||||
|
||||
yield key, version
|
||||
|
||||
# check bucket existence
|
||||
req.get_response(self.app, 'HEAD')
|
||||
|
||||
try:
|
||||
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
|
||||
elem = fromstring(xml, 'Delete')
|
||||
@@ -71,6 +81,13 @@ class MultiObjectDeleteController(Controller):
|
||||
|
||||
elem = Element('DeleteResult')
|
||||
|
||||
# check bucket existence
|
||||
try:
|
||||
req.get_response(self.app, 'HEAD')
|
||||
except AccessDenied as error:
|
||||
body = self._gen_error_body(error, elem, delete_list)
|
||||
return HTTPOk(body=body)
|
||||
|
||||
for key, version in delete_list:
|
||||
if version is not None:
|
||||
# TODO: delete the specific version of the object
|
||||
|
||||
@@ -173,13 +173,16 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
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)
|
||||
self.keys = ['Key1', 'Key2']
|
||||
self.swift.register(
|
||||
'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[0],
|
||||
swob.HTTPNoContent, {}, None)
|
||||
self.swift.register(
|
||||
'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[1],
|
||||
swob.HTTPNotFound, {}, None)
|
||||
|
||||
elem = Element('Delete')
|
||||
for key in ['Key1', 'Key2']:
|
||||
for key in self.keys:
|
||||
obj = SubElement(elem, 'Object')
|
||||
SubElement(obj, 'Key').text = key
|
||||
body = tostring(elem, use_s3ns=False)
|
||||
@@ -198,14 +201,21 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
@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')
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
elem = fromstring(body)
|
||||
errors = elem.findall('Error')
|
||||
self.assertEquals(len(errors), len(self.keys))
|
||||
for e in errors:
|
||||
self.assertTrue(e.find('Key').text in self.keys)
|
||||
self.assertEquals(e.find('Code').text, 'AccessDenied')
|
||||
self.assertEquals(e.find('Message').text, 'Access Denied.')
|
||||
|
||||
@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)
|
||||
self.assertEquals(len(elem.findall('Deleted')), len(self.keys))
|
||||
|
||||
@s3acl(s3acl_only=True)
|
||||
def test_object_multi_DELETE_with_fullcontrol_permission(self):
|
||||
@@ -213,7 +223,7 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
||||
self._test_object_multi_DELETE('test:full_control')
|
||||
self.assertEquals(status.split()[0], '200')
|
||||
elem = fromstring(body)
|
||||
self.assertEquals(len(elem.findall('Deleted')), 2)
|
||||
self.assertEquals(len(elem.findall('Deleted')), len(self.keys))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user