99 lines
3.3 KiB
Python

"""Authorization middleware."""
from ..auth import get_auth
from .abc import AbstractAutzPolicy
AUTZ_POLICY_KEY = 'aiohttp_auth.autz.policy'
def autz_middleware(autz_policy):
"""Return authorization middleware factory.
Return ``aiohttp_auth.autz`` middleware factory for use by the ``aiohttp``
application object. This middleware can be used only with
``aiohttp_auth.auth`` middleware installed.
The ``autz`` middleware provides follow interface to use in applications:
- Using ``autz.permit`` coroutine.
- Using ``autz.autz_required`` decorator for ``aiohttp`` handlers.
Note that the recomended way to initialize this middleware is through
``aiohttp_auth.autz.setup`` or ``aiohttp_auth.setup`` functions. As the
``autz`` middleware can be used only with authentication
``aiohttp_auth.auth`` middleware it is preferred to use
``aiohttp_auth.setup``.
Args:
autz_policy: a subclass of
``aiohttp_auth.autz.abc.AbstractAutzPolicy``.
Returns:
An ``aiohttp`` middleware factory.
"""
assert isinstance(autz_policy, AbstractAutzPolicy)
async def _middleware_factory(app, handler):
async def _middleware_handler(request):
# Save the policy in the request
request[AUTZ_POLICY_KEY] = autz_policy
# Call the next handler in the chain
return await handler(request)
return _middleware_handler
return _middleware_factory
async def permit(request, permission, context=None):
"""Check if permission is allowed for given request with given context.
The authorization checking is provided by authorization policy which is
set by setup function. The nature of permission and context is also
determined by the given policy.
Note that this coroutine uses ``aiohttp_auth.auth.get_auth`` coroutine
to determine ``user_identity`` for given request. So that middleware
should be installed too.
Note that some additional exceptions could be raised by certain policy
while checking the permission.
Args:
request: aiohttp ``Request`` object.
permission: The specific permission requested.
context: A context provided for checking permissions. Could be
optional if authorization policy provides a way to specify a
global application context.
Returns:
``True`` if permission is allowed ``False`` otherwise.
Raises:
RuntimeError: If ``auth`` or ``autz`` middleware is not installed.
"""
user_identity = await get_auth(request)
policy = request.get(AUTZ_POLICY_KEY, None)
if policy is None:
raise RuntimeError('autz_middleware not installed.')
return await policy.permit(user_identity, permission, context)
def setup(app, autz_policy):
"""Setup an authorization middleware in ``aiohttp`` fashion.
Note that ``aiohttp_auth.auth`` middleware should be installed too to use
``autz`` middleware. So the preferred way to install this middleware is to
use global ``aiohttp_auth.setup`` function.
Args:
app: aiohttp ``Application`` object.
autz_policy: A subclass of
``aiohttp_auth.autz.abc.AbstractAutzPolicy``.
"""
app.middlewares.append(autz_middleware(autz_policy))