2020-12-18 17:58:38 +00:00
|
|
|
|
from enum import Enum
|
|
|
|
|
from typing import NoReturn, Optional, Union
|
|
|
|
|
|
2018-04-26 09:15:12 +00:00
|
|
|
|
from aiohttp import web
|
|
|
|
|
from aiohttp_session import SimpleCookieStorage, session_middleware
|
2018-09-06 10:06:55 +00:00
|
|
|
|
from aiohttp_security import check_permission, \
|
2018-04-26 09:15:12 +00:00
|
|
|
|
is_anonymous, remember, forget, \
|
|
|
|
|
setup as setup_security, SessionIdentityPolicy
|
|
|
|
|
from aiohttp_security.abc import AbstractAuthorizationPolicy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Demo authorization policy for only one user.
|
|
|
|
|
# User 'jack' has only 'listen' permission.
|
|
|
|
|
# For more complicated authorization policies see examples
|
|
|
|
|
# in the 'demo' directory.
|
|
|
|
|
class SimpleJack_AuthorizationPolicy(AbstractAuthorizationPolicy):
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def authorized_userid(self, identity: str) -> Optional[str]:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
"""Retrieve authorized user id.
|
|
|
|
|
Return the user_id of the user identified by the identity
|
|
|
|
|
or 'None' if no user exists related to the identity.
|
|
|
|
|
"""
|
2020-12-18 17:58:38 +00:00
|
|
|
|
return identity if identity == 'jack' else None
|
2018-04-26 09:15:12 +00:00
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def permits(self, identity: str, permission: Union[str, Enum],
|
|
|
|
|
context: None = None) -> bool:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
"""Check user permissions.
|
|
|
|
|
Return True if the identity is allowed the permission
|
|
|
|
|
in the current context, else return False.
|
|
|
|
|
"""
|
|
|
|
|
return identity == 'jack' and permission in ('listen',)
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def handler_root(request: web.Request) -> web.Response:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
is_logged = not await is_anonymous(request)
|
|
|
|
|
return web.Response(text='''<html><head></head><body>
|
|
|
|
|
Hello, I'm Jack, I'm {logged} logged in.<br /><br />
|
|
|
|
|
<a href="/login">Log me in</a><br />
|
|
|
|
|
<a href="/logout">Log me out</a><br /><br />
|
|
|
|
|
Check my permissions,
|
|
|
|
|
when i'm logged in and logged out.<br />
|
|
|
|
|
<a href="/listen">Can I listen?</a><br />
|
|
|
|
|
<a href="/speak">Can I speak?</a><br />
|
|
|
|
|
</body></html>'''.format(
|
|
|
|
|
logged='' if is_logged else 'NOT',
|
|
|
|
|
), content_type='text/html')
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def handler_login_jack(request: web.Request) -> NoReturn:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
redirect_response = web.HTTPFound('/')
|
|
|
|
|
await remember(request, redirect_response, 'jack')
|
|
|
|
|
raise redirect_response
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def handler_logout(request: web.Request) -> NoReturn:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
redirect_response = web.HTTPFound('/')
|
|
|
|
|
await forget(request, redirect_response)
|
|
|
|
|
raise redirect_response
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def handler_listen(request: web.Request) -> web.Response:
|
2018-09-06 10:06:55 +00:00
|
|
|
|
await check_permission(request, 'listen')
|
2018-04-26 09:15:12 +00:00
|
|
|
|
return web.Response(body="I can listen!")
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def handler_speak(request: web.Request) -> web.Response:
|
2018-09-06 10:06:55 +00:00
|
|
|
|
await check_permission(request, 'speak')
|
2018-04-26 09:15:12 +00:00
|
|
|
|
return web.Response(body="I can speak!")
|
|
|
|
|
|
|
|
|
|
|
2020-12-18 17:58:38 +00:00
|
|
|
|
async def make_app() -> web.Application:
|
2018-04-26 09:15:12 +00:00
|
|
|
|
#
|
|
|
|
|
# WARNING!!!
|
|
|
|
|
# Never use SimpleCookieStorage on production!!!
|
|
|
|
|
# It’s highly insecure!!!
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
# make app
|
|
|
|
|
middleware = session_middleware(SimpleCookieStorage())
|
|
|
|
|
app = web.Application(middlewares=[middleware])
|
|
|
|
|
|
|
|
|
|
# add the routes
|
|
|
|
|
app.router.add_route('GET', '/', handler_root)
|
|
|
|
|
app.router.add_route('GET', '/login', handler_login_jack)
|
|
|
|
|
app.router.add_route('GET', '/logout', handler_logout)
|
|
|
|
|
app.router.add_route('GET', '/listen', handler_listen)
|
|
|
|
|
app.router.add_route('GET', '/speak', handler_speak)
|
|
|
|
|
|
|
|
|
|
# set up policies
|
|
|
|
|
policy = SessionIdentityPolicy()
|
|
|
|
|
setup_security(app, policy, SimpleJack_AuthorizationPolicy())
|
|
|
|
|
|
|
|
|
|
return app
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
web.run_app(make_app(), port=9000)
|