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
This commit is contained in:
Morgan Fainberg 2018-07-19 11:46:13 -07:00
parent 6dbd005842
commit da4eb43f5c
3 changed files with 21 additions and 20 deletions

View File

@ -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')

View File

@ -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

View File

@ -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