Ensure repeated member deletion fails with 404

Fixes bug 1157427

If an image membership is deleted more than once, the second and
subsequent deletions would be expected to return a 404 Not Found
response code, as opposed to 204 No Content.

Previously, the can_show_deleted logic got in the way, such that
for an admin caller the previously deleted membership was considered
still extant.

We now override the show_deleted logic for deletion, as it makes no
sense to consider the existence of previously deleted database rows
when another deletion request is issued.

Note that there is no corresponding proposal to master as this logic
has been refactored and this no longer affects master.

Change-Id: If8200bbb74e46c814c9f8fa6b4c636e7b022ab6c
This commit is contained in:
Eoghan Glynn 2013-03-19 21:13:58 +00:00
parent dd849a9be5
commit cfaa2d86dd
3 changed files with 30 additions and 3 deletions

View File

@ -710,11 +710,15 @@ def image_member_delete(context, memb_ref, session=None):
return memb_ref
def image_member_find(context, image_id=None, member=None, session=None):
def image_member_find(context, image_id=None, member=None, session=None,
show_deleted=True):
"""Find all members that meet the given criteria
:param image_id: identifier of image entity
:param member: tenant to which membership has been granted
:param session: an existing sqlalchemy session to use
:param show_deleted: set to False to override use of the context to
determine if deleted memberships are included
"""
session = session or get_session()
@ -726,7 +730,7 @@ def image_member_find(context, image_id=None, member=None, session=None):
query = query.filter_by(image_id=image_id)
if member is not None:
query = query.filter_by(member=member)
if not can_show_deleted(context):
if not (show_deleted and can_show_deleted(context)):
query = query.filter_by(deleted=False)
return query.all()

View File

@ -278,7 +278,8 @@ class Controller(object):
members = self.db_api.image_member_find(req.context,
image_id=image_id,
member=id,
session=session)
session=session,
show_deleted=False)
if members:
self.db_api.image_member_delete(req.context,
members[0],

View File

@ -1918,6 +1918,28 @@ class TestRegistryAPI(base.IsolatedUnitTest):
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code)
self.assertTrue('Membership could not be found' in res.body)
def test_delete_member_existing(self):
"""
Tests deleting an existing member is handled correctly
"""
member = dict(image_id=UUID2, member='pattieblack', can_share=False)
db_api.image_member_create(self.context, member)
self.api = test_utils.FakeAuthMiddleware(rserver.API(self.mapper),
is_admin=True)
req = webob.Request.blank('/images/%s/members/pattieblack' % UUID2)
req.method = 'DELETE'
res = req.get_response(self.api)
self.assertEquals(res.status_int, webob.exc.HTTPNoContent.code)
req = webob.Request.blank('/images/%s/members/pattieblack' % UUID2)
req.method = 'DELETE'
res = req.get_response(self.api)
self.assertEquals(res.status_int, webob.exc.HTTPNotFound.code)
self.assertTrue('Membership could not be found' in res.body)
class TestGlanceAPI(base.IsolatedUnitTest):
def setUp(self):