Remove routes collection mappings

When using the routes mapper's collection to map from URLs to
python functions several additional URIs are created by
default: 'new', 'format' and 'edit', eg this URI

/v1/images/new

was accessible and would return a '500'.

/v1/images/detail.xxx

was accessible and a 'GET' to it would create a file called 'detail.xxx'
in the image cache directory (where 'xxx' is an arbitrary string).

Similar resources for image memberships existed.

Other collection URIs (for both the API and Registry) would return
unexpected behaviour.

Use explicit mappings rather than a 'collection' to remove
the superfluous resources.

Fixes bug 1185828.

Change-Id: I2f451f0208d43cdc83dcf58a41ea31359b18fcf2
This commit is contained in:
Stuart McLaren 2013-05-31 14:20:40 +00:00
parent 98dcfb4b90
commit 519c0a6be1
4 changed files with 148 additions and 17 deletions

View File

@ -28,23 +28,66 @@ class API(wsgi.Router):
def __init__(self, mapper):
images_resource = images.create_resource()
mapper.resource("image", "images", controller=images_resource,
collection={'detail': 'GET'})
mapper.connect("/", controller=images_resource, action="index")
mapper.connect("/images/{id}", controller=images_resource,
action="meta", conditions=dict(method=["HEAD"]))
mapper.connect("/",
controller=images_resource,
action="index")
mapper.connect("/images",
controller=images_resource,
action='index',
conditions={'method': ['GET']})
mapper.connect("/images",
controller=images_resource,
action='create',
conditions={'method': ['POST']})
mapper.connect("/images/detail",
controller=images_resource,
action='detail',
conditions={'method': ['GET']})
mapper.connect("/images/{id}",
controller=images_resource,
action="meta",
conditions=dict(method=["HEAD"]))
mapper.connect("/images/{id}",
controller=images_resource,
action="show",
conditions=dict(method=["GET"]))
mapper.connect("/images/{id}",
controller=images_resource,
action="update",
conditions=dict(method=["PUT"]))
mapper.connect("/images/{id}",
controller=images_resource,
action="delete",
conditions=dict(method=["DELETE"]))
members_resource = members.create_resource()
mapper.resource("member", "members", controller=members_resource,
parent_resource=dict(member_name='image',
collection_name='images'))
mapper.connect("/shared-images/{id}",
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="index_shared_images")
action="index",
conditions={'method': ['GET']})
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="create",
conditions={'method': ['POST']})
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="update_all",
conditions=dict(method=["PUT"]))
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="show",
conditions={'method': ['GET']})
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="update",
conditions={'method': ['PUT']})
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="delete",
conditions={'method': ['DELETE']})
mapper.connect("/shared-images/{id}",
controller=members_resource,
action="index_shared_images")
super(API, self).__init__(mapper)

View File

@ -29,17 +29,61 @@ class API(wsgi.Router):
mapper = routes.Mapper()
images_resource = images.create_resource()
mapper.resource("image", "images", controller=images_resource,
collection={'detail': 'GET'})
mapper.connect("/", controller=images_resource, action="index")
mapper.connect("/",
controller=images_resource,
action="index")
mapper.connect("/images",
controller=images_resource,
action="index",
conditions={'method': ['GET']})
mapper.connect("/images",
controller=images_resource,
action="create",
conditions={'method': ['POST']})
mapper.connect("/images/detail",
controller=images_resource,
action="detail",
conditions={'method': ['GET']})
mapper.connect("/images/{id}",
controller=images_resource,
action="show",
conditions=dict(method=["GET"]))
mapper.connect("/images/{id}",
controller=images_resource,
action="update",
conditions=dict(method=["PUT"]))
mapper.connect("/images/{id}",
controller=images_resource,
action="delete",
conditions=dict(method=["DELETE"]))
members_resource = members.create_resource()
mapper.resource("member", "members", controller=members_resource,
parent_resource=dict(member_name='image',
collection_name='images'))
mapper.connect("/images/{image_id}/members",
controller=members_resource, action="update_all",
controller=members_resource,
action="index",
conditions={'method': ['GET']})
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="create",
conditions={'method': ['POST']})
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="update_all",
conditions=dict(method=["PUT"]))
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="show",
conditions={'method': ['GET']})
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="update",
conditions={'method': ['PUT']})
mapper.connect("/images/{image_id}/members/{id}",
controller=members_resource,
action="delete",
conditions={'method': ['DELETE']})
mapper.connect("/shared-images/{id}",
controller=members_resource,
action="index_shared_images")

View File

@ -1100,6 +1100,28 @@ class TestGlanceAPI(base.IsolatedUnitTest):
res = req.get_response(self.api)
self.assertEquals(res.status_int, 400)
def test_get_images_bad_urls(self):
"""Check that routes collections are not on (LP bug 1185828)"""
req = webob.Request.blank('/images/detail.xxx')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank('/images.xxx')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank('/images/new')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank("/images/%s/members" % UUID1)
res = req.get_response(self.api)
self.assertEquals(res.status_int, 200)
req = webob.Request.blank("/images/%s/members.xxx" % UUID1)
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
def test_get_images_detailed_unauthorized(self):
rules = {"get_images": '!'}
self.set_policy_rules(rules)

View File

@ -2500,3 +2500,25 @@ class TestRegistryAPI(base.IsolatedUnitTest):
res = req.get_response(api)
self.assertEquals(res.status_int, 403)
def test_get_images_bad_urls(self):
"""Check that routes collections are not on (LP bug 1185828)"""
req = webob.Request.blank('/images/detail.xxx')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank('/images.xxx')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank('/images/new')
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)
req = webob.Request.blank("/images/%s/members" % UUID1)
res = req.get_response(self.api)
self.assertEquals(res.status_int, 200)
req = webob.Request.blank("/images/%s/members.xxx" % UUID1)
res = req.get_response(self.api)
self.assertEquals(res.status_int, 404)