Make collection_key and member_key raise if unset

Instead of populating with __UNUSED__ or other silly string, make
direct use of "collection_key" or "member_key" raise a ValueError
if they are unset and referenced.

Change-Id: Idf4f4df9d933317fff96a474cdf23d758ebdfa8c
Partial-Bug: #1776504
This commit is contained in:
Morgan Fainberg 2018-10-12 10:30:04 -07:00
parent ce93950f44
commit 5c70aef2da
7 changed files with 52 additions and 25 deletions

View File

@ -31,9 +31,6 @@ CRED_TYPE_EC2 = 'ec2'
class ResourceBase(ks_flask.ResourceBase):
collection_key = '__UNUSED__'
member_key = '__UNUSED__'
def get(self):
# SPECIAL CASE: GET is not allowed, raise METHOD_NOT_ALLOWED
raise exceptions.MethodNotAllowed(valid_methods=['POST'])

View File

@ -101,9 +101,6 @@ def _get_sso_origin_host():
class _AuthFederationWebSSOBase(ks_flask.ResourceBase):
collection_key = '__UNUSED__'
member_key = '__UNUSED__'
@staticmethod
def _render_template_response(host, token_id):
with open(CONF.federation.sso_callback_template) as template:

View File

@ -30,9 +30,6 @@ CRED_TYPE_EC2 = 'ec2'
class EC2TokensResource(EC2_S3_Resource.ResourceBase):
collection_key = '__UNUSED__'
member_key = '__UNUSED__'
@staticmethod
def _check_signature(creds_ref, credentials):
signer = ec2_utils.Ec2Signer(creds_ref['secret'])

View File

@ -193,9 +193,6 @@ class UserResource(ks_flask.ResourceBase):
class UserChangePasswordResource(ks_flask.ResourceBase):
collection_key = '__UNUSED__'
member_key = '__UNUSED__'
@ks_flask.unenforced_api
def get(self, user_id):
# Special case, GET is not allowed.

View File

@ -168,7 +168,15 @@ class RBACEnforcer(object):
# here.
resource = flask.current_app.view_functions[
flask.request.endpoint].view_class
member_name = getattr(resource, 'member_key', None)
try:
member_name = getattr(resource, 'member_key', None)
except ValueError:
# NOTE(morgan): In the case that the ResourceBase keystone
# class is used, we raise a value error when member_key
# has not been set on the class. This is perfectly
# normal and acceptable. Set member_name to None as though
# it wasn't set.
member_name = None
func = getattr(
resource, 'get_member_from_driver', None)
if member_name is not None and callable(func):

View File

@ -570,10 +570,22 @@ class APIBase(object):
return inst
class ResourceBase(flask_restful.Resource):
class _AttributeRaisesError(object):
# NOTE(morgan): This is a special case class that exists to effectively
# create a @classproperty style function. We use __get__ to raise the
# exception.
collection_key = None
member_key = None
def __init__(self, name):
self.__msg = 'PROGRAMMING ERROR: `self.{name}` is not set.'.format(
name=name)
def __get__(self, instance, owner):
raise ValueError(self.__msg)
class ResourceBase(flask_restful.Resource):
collection_key = _AttributeRaisesError(name='collection_key')
member_key = _AttributeRaisesError(name='member_key')
_public_parameters = frozenset([])
# NOTE(morgan): This must match the string on the API the resource is
# registered to.
@ -582,15 +594,6 @@ class ResourceBase(flask_restful.Resource):
method_decorators = []
def __init__(self):
super(ResourceBase, self).__init__()
if self.collection_key is None:
raise ValueError('PROGRAMMING ERROR: `self.collection_key` '
'cannot be `None`.')
if self.member_key is None:
raise ValueError('PROGRAMMING ERROR: `self.member_key` cannot '
'be `None`.')
@staticmethod
def _assign_unique_id(ref):
ref = ref.copy()

View File

@ -696,3 +696,31 @@ class TestKeystoneFlaskCommon(rest.RestfulTestCase):
headers={'Content-Type': 'unrecognized/content-type'}):
# No exception should be raised, everything is happy.
json_body.json_body_before_request()
def test_resource_collection_key_raises_exception_if_unset(self):
class TestResource(flask_common.ResourceBase):
"""A Test Resource."""
class TestResourceWithKey(flask_common.ResourceBase):
collection_key = uuid.uuid4().hex
r = TestResource()
self.assertRaises(ValueError, getattr, r, 'collection_key')
r = TestResourceWithKey()
self.assertEqual(
TestResourceWithKey.collection_key, r.collection_key)
def test_resource_member_key_raises_exception_if_unset(self):
class TestResource(flask_common.ResourceBase):
"""A Test Resource."""
class TestResourceWithKey(flask_common.ResourceBase):
member_key = uuid.uuid4().hex
r = TestResource()
self.assertRaises(ValueError, getattr, r, 'member_key')
r = TestResourceWithKey()
self.assertEqual(
TestResourceWithKey.member_key, r.member_key)