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