Merge "Fix response of DELETE Multiple Objects without bucket write permission"

This commit is contained in:
Jenkins
2015-01-08 03:05:31 +00:00
committed by Gerrit Code Review
2 changed files with 39 additions and 12 deletions

View File

@@ -17,7 +17,7 @@ from swift3.controllers.base import Controller, bucket_operation
from swift3.etree import Element, SubElement, fromstring, tostring, \ from swift3.etree import Element, SubElement, fromstring, tostring, \
XMLSyntaxError, DocumentInvalid XMLSyntaxError, DocumentInvalid
from swift3.response import HTTPOk, S3NotImplemented, NoSuchKey, \ from swift3.response import HTTPOk, S3NotImplemented, NoSuchKey, \
ErrorResponse, MalformedXML, UserKeyMustBeSpecified ErrorResponse, MalformedXML, UserKeyMustBeSpecified, AccessDenied
from swift3.cfg import CONF from swift3.cfg import CONF
from swift3.utils import LOGGER from swift3.utils import LOGGER
@@ -29,6 +29,19 @@ class MultiObjectDeleteController(Controller):
Handles Delete Multiple Objects, which is logged as a MULTI_OBJECT_DELETE Handles Delete Multiple Objects, which is logged as a MULTI_OBJECT_DELETE
operation in the S3 server log. 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 @bucket_operation
def POST(self, req): def POST(self, req):
""" """
@@ -45,9 +58,6 @@ class MultiObjectDeleteController(Controller):
yield key, version yield key, version
# check bucket existence
req.get_response(self.app, 'HEAD')
try: try:
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True) xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
elem = fromstring(xml, 'Delete') elem = fromstring(xml, 'Delete')
@@ -71,6 +81,13 @@ class MultiObjectDeleteController(Controller):
elem = Element('DeleteResult') 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: for key, version in delete_list:
if version is not None: if version is not None:
# TODO: delete the specific version of the object # TODO: delete the specific version of the object

View File

@@ -173,13 +173,16 @@ class TestSwift3MultiDelete(Swift3TestCase):
self.assertEquals(self._get_error_code(body), 'MalformedXML') self.assertEquals(self._get_error_code(body), 'MalformedXML')
def _test_object_multi_DELETE(self, account): def _test_object_multi_DELETE(self, account):
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1', self.keys = ['Key1', 'Key2']
swob.HTTPNoContent, {}, None) self.swift.register(
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2', 'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[0],
swob.HTTPNotFound, {}, None) swob.HTTPNoContent, {}, None)
self.swift.register(
'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[1],
swob.HTTPNotFound, {}, None)
elem = Element('Delete') elem = Element('Delete')
for key in ['Key1', 'Key2']: for key in self.keys:
obj = SubElement(elem, 'Object') obj = SubElement(elem, 'Object')
SubElement(obj, 'Key').text = key SubElement(obj, 'Key').text = key
body = tostring(elem, use_s3ns=False) body = tostring(elem, use_s3ns=False)
@@ -198,14 +201,21 @@ class TestSwift3MultiDelete(Swift3TestCase):
@s3acl(s3acl_only=True) @s3acl(s3acl_only=True)
def test_object_multi_DELETE_without_permission(self): def test_object_multi_DELETE_without_permission(self):
status, headers, body = self._test_object_multi_DELETE('test:other') 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) @s3acl(s3acl_only=True)
def test_object_multi_DELETE_with_write_permission(self): def test_object_multi_DELETE_with_write_permission(self):
status, headers, body = self._test_object_multi_DELETE('test:write') status, headers, body = self._test_object_multi_DELETE('test:write')
self.assertEquals(status.split()[0], '200') self.assertEquals(status.split()[0], '200')
elem = fromstring(body) elem = fromstring(body)
self.assertEquals(len(elem.findall('Deleted')), 2) self.assertEquals(len(elem.findall('Deleted')), len(self.keys))
@s3acl(s3acl_only=True) @s3acl(s3acl_only=True)
def test_object_multi_DELETE_with_fullcontrol_permission(self): 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._test_object_multi_DELETE('test:full_control')
self.assertEquals(status.split()[0], '200') self.assertEquals(status.split()[0], '200')
elem = fromstring(body) elem = fromstring(body)
self.assertEquals(len(elem.findall('Deleted')), 2) self.assertEquals(len(elem.findall('Deleted')), len(self.keys))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()