From da4eb43f5c74ffc18af3664545c95476c5123d5c Mon Sep 17 00:00:00 2001 From: Morgan Fainberg Date: Thu, 19 Jul 2018 11:46:13 -0700 Subject: [PATCH] Move unenforced_api decorator to module function Move the unenforced_api decorator off the APIBase object and into the module. It is likely the code would require calling the decorator from the module level anyway since the Resource is added to a list that is a property of the API. Moving the decorator makes it so the call is more akin to @keystone_flask.unenforced_api instead of @keystone_flask.APIBase.unenforced_api. Change-Id: Ic1d5466bc26c76886333f00b6962886fd2ce32fd Partial-Bug: #1776504 --- keystone/server/flask/__init__.py | 3 +- keystone/server/flask/common.py | 36 +++++++++---------- .../tests/unit/server/test_keystone_flask.py | 2 +- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/keystone/server/flask/__init__.py b/keystone/server/flask/__init__.py index e5f1648012..94f0a5730c 100644 --- a/keystone/server/flask/__init__.py +++ b/keystone/server/flask/__init__.py @@ -22,10 +22,11 @@ from keystone.server.flask.common import full_url # noqa from keystone.server.flask.common import JsonHomeData # noqa from keystone.server.flask.common import ResourceBase # noqa from keystone.server.flask.common import ResourceMap # noqa +from keystone.server.flask.common import unenforced_api # noqa # NOTE(morgan): This allows for from keystone.flask import * and have all the # cool stuff needed to develop new APIs within a module/subsystem __all__ = ('APIBase', 'JsonHomeData', 'ResourceBase', 'ResourceMap', 'base_url', 'construct_json_home_data', 'construct_resource_map', - 'full_url') + 'full_url', 'unenforced_api') diff --git a/keystone/server/flask/common.py b/keystone/server/flask/common.py index 09bbaa2278..c062966c91 100644 --- a/keystone/server/flask/common.py +++ b/keystone/server/flask/common.py @@ -487,24 +487,6 @@ class APIBase(object): resp.headers.extend(headers or {}) return resp - @staticmethod - def unenforced_api(f): - """Decorate a resource method to mark is as an unenforced API. - - Explicitly exempts an API from receiving the enforced API check, - specifically for cases such as user self-service password changes (or - other APIs that must work without already having a token). - - This decorator may also be used if the API has extended enforcement - logic/varying enforcement logic (such as some of the AUTH paths) where - the full enforcement will be implemented directly within the methods. - """ - @functools.wraps(f) - def wrapper(*args, **kwargs): - setattr(flask.g, enforcer._ENFORCEMENT_CHECK_ATTR, True) - return f(*args, **kwargs) - return wrapper - @classmethod def instantiate_and_register_to_app(cls, flask_app): """Build the API object and register to the passed in flask_app. @@ -823,3 +805,21 @@ def full_url(): if qs: subs['query_string'] = '?%s' % qs return '%(url)s%(query_string)s' % subs + + +def unenforced_api(f): + """Decorate a resource method to mark is as an unenforced API. + + Explicitly exempts an API from receiving the enforced API check, + specifically for cases such as user self-service password changes (or + other APIs that must work without already having a token). + + This decorator may also be used if the API has extended enforcement + logic/varying enforcement logic (such as some of the AUTH paths) where + the full enforcement will be implemented directly within the methods. + """ + @functools.wraps(f) + def wrapper(*args, **kwargs): + setattr(flask.g, enforcer._ENFORCEMENT_CHECK_ATTR, True) + return f(*args, **kwargs) + return wrapper diff --git a/keystone/tests/unit/server/test_keystone_flask.py b/keystone/tests/unit/server/test_keystone_flask.py index 524ce6170c..319f4ff1bc 100644 --- a/keystone/tests/unit/server/test_keystone_flask.py +++ b/keystone/tests/unit/server/test_keystone_flask.py @@ -436,7 +436,7 @@ class TestKeystoneFlaskCommon(rest.RestfulTestCase): # Test unenforced decorator works as expected class MappedResource(flask_restful.Resource): - @_TestRestfulAPI.unenforced_api + @flask_common.unenforced_api def post(self): post_body = flask.request.get_json() return {'post_body': post_body}, 201