From 5b2ff779c39563146386f244468dc788bfcb9a2a Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Wed, 13 Dec 2017 16:51:46 +0200 Subject: [PATCH] Switch to async/await syntax --- .travis.yml | 1 - aiohttp_security/abc.py | 16 +-- aiohttp_security/api.py | 46 +++---- aiohttp_security/cookies_identity.py | 13 +- aiohttp_security/session_identity.py | 17 +-- demo/database_auth/db_auth.py | 29 ++-- demo/database_auth/handlers.py | 33 ++--- demo/database_auth/main.py | 16 +-- demo/dictionary_auth/handlers.py | 8 +- docs/example.rst | 23 ++-- docs/example_db_auth.rst | 52 ++++---- tests/test_cookies_identity.py | 68 ++++------ tests/test_dict_autz.py | 189 +++++++++++---------------- tests/test_no_auth.py | 32 ++--- tests/test_no_identity.py | 28 ++-- tests/test_session_identity.py | 79 +++++------ 16 files changed, 257 insertions(+), 393 deletions(-) diff --git a/.travis.yml b/.travis.yml index 128105e..723b760 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - 3.4.3 - 3.5 - 3.6 - 3.7-dev diff --git a/aiohttp_security/abc.py b/aiohttp_security/abc.py index b1f9f2a..862abd8 100644 --- a/aiohttp_security/abc.py +++ b/aiohttp_security/abc.py @@ -1,21 +1,18 @@ import abc -import asyncio # see http://plope.com/pyramid_auth_design_api_postmortem class AbstractIdentityPolicy(metaclass=abc.ABCMeta): - @asyncio.coroutine @abc.abstractmethod - def identify(self, request): + async def identify(self, request): """Return the claimed identity of the user associated request or ``None`` if no identity can be found associated with the request.""" pass - @asyncio.coroutine @abc.abstractmethod - def remember(self, request, response, identity, **kwargs): + async def remember(self, request, response, identity, **kwargs): """Remember identity. Modify response object by filling it's headers with remembered user. @@ -25,9 +22,8 @@ class AbstractIdentityPolicy(metaclass=abc.ABCMeta): """ pass - @asyncio.coroutine @abc.abstractmethod - def forget(self, request, response): + async def forget(self, request, response): """ Modify response which can be used to 'forget' the current identity on subsequent requests.""" pass @@ -35,9 +31,8 @@ class AbstractIdentityPolicy(metaclass=abc.ABCMeta): class AbstractAuthorizationPolicy(metaclass=abc.ABCMeta): - @asyncio.coroutine @abc.abstractmethod - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): """Check user permissions. Return True if the identity is allowed the permission in the @@ -45,9 +40,8 @@ class AbstractAuthorizationPolicy(metaclass=abc.ABCMeta): """ pass - @asyncio.coroutine @abc.abstractmethod - def authorized_userid(self, identity): + async def authorized_userid(self, identity): """Retrieve authorized user id. Return the user_id of the user identified by the identity diff --git a/aiohttp_security/api.py b/aiohttp_security/api.py index 41f5d20..0dea731 100644 --- a/aiohttp_security/api.py +++ b/aiohttp_security/api.py @@ -1,4 +1,3 @@ -import asyncio import enum from aiohttp import web from aiohttp_security.abc import (AbstractIdentityPolicy, @@ -9,8 +8,7 @@ IDENTITY_KEY = 'aiohttp_security_identity_policy' AUTZ_KEY = 'aiohttp_security_autz_policy' -@asyncio.coroutine -def remember(request, response, identity, **kwargs): +async def remember(request, response, identity, **kwargs): """Remember identity into response. The action is performed by identity_policy.remember() @@ -28,11 +26,10 @@ def remember(request, response, identity, **kwargs): # output and rendered page we add same message to *reason* and # *text* arguments. raise web.HTTPInternalServerError(reason=text, text=text) - yield from identity_policy.remember(request, response, identity, **kwargs) + await identity_policy.remember(request, response, identity, **kwargs) -@asyncio.coroutine -def forget(request, response): +async def forget(request, response): """Forget previously remembered identity. Usually it clears cookie or server-side storage to forget user @@ -46,38 +43,35 @@ def forget(request, response): # output and rendered page we add same message to *reason* and # *text* arguments. raise web.HTTPInternalServerError(reason=text, text=text) - yield from identity_policy.forget(request, response) + await identity_policy.forget(request, response) -@asyncio.coroutine -def authorized_userid(request): +async def authorized_userid(request): identity_policy = request.app.get(IDENTITY_KEY) autz_policy = request.app.get(AUTZ_KEY) if identity_policy is None or autz_policy is None: return None - identity = yield from identity_policy.identify(request) + identity = await identity_policy.identify(request) if identity is None: return None # non-registered user has None user_id - user_id = yield from autz_policy.authorized_userid(identity) + user_id = await autz_policy.authorized_userid(identity) return user_id -@asyncio.coroutine -def permits(request, permission, context=None): +async def permits(request, permission, context=None): assert isinstance(permission, (str, enum.Enum)), permission assert permission identity_policy = request.app.get(IDENTITY_KEY) autz_policy = request.app.get(AUTZ_KEY) if identity_policy is None or autz_policy is None: return True - identity = yield from identity_policy.identify(request) + identity = await identity_policy.identify(request) # non-registered user still may has some permissions - access = yield from autz_policy.permits(identity, permission, context) + access = await autz_policy.permits(identity, permission, context) return access -@asyncio.coroutine -def is_anonymous(request): +async def is_anonymous(request): """Check if user is anonymous. User is considered anonymous if there is not identity @@ -86,7 +80,7 @@ def is_anonymous(request): identity_policy = request.app.get(IDENTITY_KEY) if identity_policy is None: return True - identity = yield from identity_policy.identify(request) + identity = await identity_policy.identify(request) if identity is None: return True return False @@ -98,9 +92,8 @@ def login_required(fn): User is considered authorized if authorized_userid returns some value. """ - @asyncio.coroutine @wraps(fn) - def wrapped(*args, **kwargs): + async def wrapped(*args, **kwargs): request = args[-1] if not isinstance(request, web.BaseRequest): msg = ("Incorrect decorator usage. " @@ -108,11 +101,11 @@ def login_required(fn): "or `def handler(self, request)`.") raise RuntimeError(msg) - userid = yield from authorized_userid(request) + userid = await authorized_userid(request) if userid is None: raise web.HTTPUnauthorized - ret = yield from fn(*args, **kwargs) + ret = await fn(*args, **kwargs) return ret return wrapped @@ -130,9 +123,8 @@ def has_permission( raises HTTPForbidden. """ def wrapper(fn): - @asyncio.coroutine @wraps(fn) - def wrapped(*args, **kwargs): + async def wrapped(*args, **kwargs): request = args[-1] if not isinstance(request, web.BaseRequest): msg = ("Incorrect decorator usage. " @@ -140,14 +132,14 @@ def has_permission( "or `def handler(self, request)`.") raise RuntimeError(msg) - userid = yield from authorized_userid(request) + userid = await authorized_userid(request) if userid is None: raise web.HTTPUnauthorized - allowed = yield from permits(request, permission, context) + allowed = await permits(request, permission, context) if not allowed: raise web.HTTPForbidden - ret = yield from fn(*args, **kwargs) + ret = await fn(*args, **kwargs) return ret return wrapped diff --git a/aiohttp_security/cookies_identity.py b/aiohttp_security/cookies_identity.py index 807af34..3822ef9 100644 --- a/aiohttp_security/cookies_identity.py +++ b/aiohttp_security/cookies_identity.py @@ -5,8 +5,6 @@ more handy. """ -import asyncio - from .abc import AbstractIdentityPolicy @@ -19,19 +17,16 @@ class CookiesIdentityPolicy(AbstractIdentityPolicy): self._cookie_name = 'AIOHTTP_SECURITY' self._max_age = 30 * 24 * 3600 - @asyncio.coroutine - def identify(self, request): + async def identify(self, request): identity = request.cookies.get(self._cookie_name) return identity - @asyncio.coroutine - def remember(self, request, response, identity, max_age=sentinel, - **kwargs): + async def remember(self, request, response, identity, max_age=sentinel, + **kwargs): if max_age is sentinel: max_age = self._max_age response.set_cookie(self._cookie_name, identity, max_age=max_age, **kwargs) - @asyncio.coroutine - def forget(self, request, response): + async def forget(self, request, response): response.del_cookie(self._cookie_name) diff --git a/aiohttp_security/session_identity.py b/aiohttp_security/session_identity.py index 5d9cea0..13d197a 100644 --- a/aiohttp_security/session_identity.py +++ b/aiohttp_security/session_identity.py @@ -4,8 +4,6 @@ aiohttp_session.setup() should be called on application initialization to configure aiohttp_session properly. """ -import asyncio - try: from aiohttp_session import get_session HAS_AIOHTTP_SESSION = True @@ -24,17 +22,14 @@ class SessionIdentityPolicy(AbstractIdentityPolicy): raise ImportError( 'SessionIdentityPolicy requires `aiohttp_session`') - @asyncio.coroutine - def identify(self, request): - session = yield from get_session(request) + async def identify(self, request): + session = await get_session(request) return session.get(self._session_key) - @asyncio.coroutine - def remember(self, request, response, identity, **kwargs): - session = yield from get_session(request) + async def remember(self, request, response, identity, **kwargs): + session = await get_session(request) session[self._session_key] = identity - @asyncio.coroutine - def forget(self, request, response): - session = yield from get_session(request) + async def forget(self, request, response): + session = await get_session(request) session.pop(self._session_key, None) diff --git a/demo/database_auth/db_auth.py b/demo/database_auth/db_auth.py index bb9897c..82c29bd 100644 --- a/demo/database_auth/db_auth.py +++ b/demo/database_auth/db_auth.py @@ -1,5 +1,3 @@ -import asyncio - import sqlalchemy as sa from aiohttp_security.abc import AbstractAuthorizationPolicy @@ -12,29 +10,27 @@ class DBAuthorizationPolicy(AbstractAuthorizationPolicy): def __init__(self, dbengine): self.dbengine = dbengine - @asyncio.coroutine def authorized_userid(self, identity): - with (yield from self.dbengine) as conn: + async with self.dbengine as conn: where = sa.and_(db.users.c.login == identity, sa.not_(db.users.c.disabled)) query = db.users.count().where(where) - ret = yield from conn.scalar(query) + ret = await conn.scalar(query) if ret: return identity else: return None - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): if identity is None: return False - with (yield from self.dbengine) as conn: + async with self.dbengine as conn: where = sa.and_(db.users.c.login == identity, sa.not_(db.users.c.disabled)) query = db.users.select().where(where) - ret = yield from conn.execute(query) - user = yield from ret.fetchone() + ret = await conn.execute(query) + user = await ret.fetchone() if user is not None: user_id = user[0] is_superuser = user[3] @@ -43,8 +39,8 @@ class DBAuthorizationPolicy(AbstractAuthorizationPolicy): where = db.permissions.c.user_id == user_id query = db.permissions.select().where(where) - ret = yield from conn.execute(query) - result = yield from ret.fetchall() + ret = await conn.execute(query) + result = await ret.fetchall() if ret is not None: for record in result: if record.perm_name == permission: @@ -53,14 +49,13 @@ class DBAuthorizationPolicy(AbstractAuthorizationPolicy): return False -@asyncio.coroutine -def check_credentials(db_engine, username, password): - with (yield from db_engine) as conn: +async def check_credentials(db_engine, username, password): + async with db_engine as conn: where = sa.and_(db.users.c.login == username, sa.not_(db.users.c.disabled)) query = db.users.select().where(where) - ret = yield from conn.execute(query) - user = yield from ret.fetchone() + ret = await conn.execute(query) + user = await ret.fetchone() if user is not None: hash = user[2] return sha256_crypt.verify(password, hash) diff --git a/demo/database_auth/handlers.py b/demo/database_auth/handlers.py index 3de2aed..b0c6658 100644 --- a/demo/database_auth/handlers.py +++ b/demo/database_auth/handlers.py @@ -1,4 +1,3 @@ -import asyncio import functools from aiohttp import web @@ -10,14 +9,13 @@ from .db_auth import check_credentials def require(permission): def wrapper(f): - @asyncio.coroutine @functools.wraps(f) - def wrapped(self, request): - has_perm = yield from permits(request, permission) + async def wrapped(self, request): + has_perm = await permits(request, permission) if not has_perm: message = 'User has no permission {}'.format(permission) raise web.HTTPForbidden(body=message.encode()) - return (yield from f(self, request)) + return await f(self, request) return wrapped return wrapper @@ -40,9 +38,8 @@ class Web(object): """ - @asyncio.coroutine - def index(self, request): - username = yield from authorized_userid(request) + async def index(self, request): + username = await authorized_userid(request) if username: template = self.index_template.format( message='Hello, {username}!'.format(username=username)) @@ -51,37 +48,33 @@ class Web(object): response = web.Response(body=template.encode()) return response - @asyncio.coroutine - def login(self, request): + async def login(self, request): response = web.HTTPFound('/') - form = yield from request.post() + form = await request.post() login = form.get('login') password = form.get('password') db_engine = request.app.db_engine - if (yield from check_credentials(db_engine, login, password)): - yield from remember(request, response, login) + if await check_credentials(db_engine, login, password): + await remember(request, response, login) return response return web.HTTPUnauthorized( body=b'Invalid username/password combination') @require('public') - @asyncio.coroutine - def logout(self, request): + async def logout(self, request): response = web.Response(body=b'You have been logged out') - yield from forget(request, response) + await forget(request, response) return response @require('public') - @asyncio.coroutine - def internal_page(self, request): + async def internal_page(self, request): response = web.Response( body=b'This page is visible for all registered users') return response @require('protected') - @asyncio.coroutine - def protected_page(self, request): + async def protected_page(self, request): response = web.Response(body=b'You are on protected page') return response diff --git a/demo/database_auth/main.py b/demo/database_auth/main.py index 4fb3211..a2a6be8 100644 --- a/demo/database_auth/main.py +++ b/demo/database_auth/main.py @@ -13,10 +13,9 @@ from demo.db_auth import DBAuthorizationPolicy from demo.handlers import Web -@asyncio.coroutine def init(loop): - redis_pool = yield from create_pool(('localhost', 6379)) - db_engine = yield from create_engine(user='aiohttp_security', + redis_pool = await create_pool(('localhost', 6379)) + db_engine = await create_engine(user='aiohttp_security', password='aiohttp_security', database='aiohttp_security', host='127.0.0.1') @@ -31,21 +30,20 @@ def init(loop): web_handlers.configure(app) handler = app.make_handler() - srv = yield from loop.create_server(handler, '127.0.0.1', 8080) + srv = await loop.create_server(handler, '127.0.0.1', 8080) print('Server started at http://127.0.0.1:8080') return srv, app, handler -@asyncio.coroutine -def finalize(srv, app, handler): +async def finalize(srv, app, handler): sock = srv.sockets[0] app.loop.remove_reader(sock.fileno()) sock.close() - yield from handler.finish_connections(1.0) + await handler.finish_connections(1.0) srv.close() - yield from srv.wait_closed() - yield from app.finish() + await srv.wait_closed() + await app.finish() def main(): diff --git a/demo/dictionary_auth/handlers.py b/demo/dictionary_auth/handlers.py index 2dffe55..a0d7f7c 100644 --- a/demo/dictionary_auth/handlers.py +++ b/demo/dictionary_auth/handlers.py @@ -1,4 +1,3 @@ -import asyncio import functools from textwrap import dedent @@ -11,14 +10,13 @@ from .authz import check_credentials def require(permission): def wrapper(f): - @asyncio.coroutine @functools.wraps(f) - def wrapped(request): - has_perm = yield from permits(request, permission) + async def wrapped(request): + has_perm = await permits(request, permission) if not has_perm: message = 'User has no permission {}'.format(permission) raise web.HTTPForbidden(body=message.encode()) - return (yield from f(request)) + return await f(request) return wrapped return wrapper diff --git a/docs/example.rst b/docs/example.rst index e50ba38..7498add 100644 --- a/docs/example.rst +++ b/docs/example.rst @@ -10,16 +10,14 @@ Simple example:: import asyncio from aiohttp import web - @asyncio.coroutine - def root_handler(request): + async def root_handler(request): text = "Alive and kicking!" return web.Response(body=text.encode('utf-8')) # option 2: auth at a higher level? # set user_id and allowed in the wsgi handler @protect('view_user') - @asyncio.coroutine - def user_handler(request): + async def user_handler(request): name = request.match_info.get('name', "Anonymous") text = "Hello, " + name return web.Response(body=text.encode('utf-8')) @@ -27,14 +25,12 @@ Simple example:: # option 3: super low # wsgi doesn't do anything - @asyncio.coroutine - def user_update_handler(request): + async def user_update_handler(request): # identity, asked_permission - user_id = yield from identity_policy.identify(request) - identity = yield from auth_policy.authorized_user_id(user_id) - allowed = yield from request.auth_policy.permits( - identity, asked_permission - ) + user_id = await identity_policy.identify(request) + identity = await auth_policy.authorized_user_id(user_id) + allowed = await request.auth_policy.permits(identity, + asked_permission) if not allowed: # how is this pluggable as well? # ? return NotAllowedStream() @@ -42,8 +38,7 @@ Simple example:: update_user() - @asyncio.coroutine - def init(loop): + async def init(loop): # set up identity and auth auth_policy = DictionaryAuthorizationPolicy({'me': ('view_user',), 'you': ('view_user', @@ -60,7 +55,7 @@ Simple example:: app.router.add_route('GET', '/{user}/edit', user_update_handler) # get it started - srv = yield from loop.create_server(app.make_handler(), + srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8080) print("Server started at http://127.0.0.1:8080") return srv diff --git a/docs/example_db_auth.rst b/docs/example_db_auth.rst index 70b78e4..ec87685 100644 --- a/docs/example_db_auth.rst +++ b/docs/example_db_auth.rst @@ -67,13 +67,12 @@ In our example we will lookup database by user login and if present return this identity:: - @asyncio.coroutine - def authorized_userid(self, identity): - with (yield from self.dbengine) as conn: + async def authorized_userid(self, identity): + async with self.dbengine as conn: where = sa.and_(db.users.c.login == identity, sa.not_(db.users.c.disabled)) query = db.users.count().where(where) - ret = yield from conn.scalar(query) + ret = await conn.scalar(query) if ret: return identity else: @@ -84,17 +83,16 @@ For permission check we will fetch the user first, check if he is superuser (all permissions are allowed), otherwise check if permission is explicitly set for that user:: - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): if identity is None: return False - with (yield from self.dbengine) as conn: + async with self.dbengine as conn: where = sa.and_(db.users.c.login == identity, sa.not_(db.users.c.disabled)) query = db.users.select().where(where) - ret = yield from conn.execute(query) - user = yield from ret.fetchone() + ret = await conn.execute(query) + user = await ret.fetchone() if user is not None: user_id = user[0] is_superuser = user[4] @@ -103,8 +101,8 @@ for that user:: where = db.permissions.c.user_id == user_id query = db.permissions.select().where(where) - ret = yield from conn.execute(query) - result = yield from ret.fetchall() + ret = await conn.execute(query) + result = await ret.fetchall() if ret is not None: for record in result: if record.perm_name == permission: @@ -127,13 +125,12 @@ Once we have all the code in place we can install it for our application:: from .db_auth import DBAuthorizationPolicy - @asyncio.coroutine - def init(loop): - redis_pool = yield from create_pool(('localhost', 6379)) - dbengine = yield from create_engine(user='aiohttp_security', - password='aiohttp_security', - database='aiohttp_security', - host='127.0.0.1') + async def init(loop): + redis_pool = await create_pool(('localhost', 6379)) + dbengine = await create_engine(user='aiohttp_security', + password='aiohttp_security', + database='aiohttp_security', + host='127.0.0.1') app = web.Application(loop=loop) setup_session(app, RedisStorage(redis_pool)) setup_security(app, @@ -148,14 +145,13 @@ help to do that:: def require(permission): def wrapper(f): - @asyncio.coroutine @functools.wraps(f) - def wrapped(self, request): - has_perm = yield from permits(request, permission) + async def wrapped(self, request): + has_perm = await permits(request, permission) if not has_perm: message = 'User has no permission {}'.format(permission) raise web.HTTPForbidden(body=message.encode()) - return (yield from f(self, request)) + return await f(self, request) return wrapped return wrapper @@ -164,8 +160,7 @@ For each view you need to protect just apply the decorator on it:: class Web: @require('protected') - @asyncio.coroutine - def protected_page(self, request): + async def protected_page(self, request): response = web.Response(body=b'You are on protected page') return response @@ -187,14 +182,13 @@ function may do what you trying to accomplish:: from passlib.hash import sha256_crypt - @asyncio.coroutine - def check_credentials(db_engine, username, password): - with (yield from db_engine) as conn: + async def check_credentials(db_engine, username, password): + async with db_engine as conn: where = sa.and_(db.users.c.login == username, sa.not_(db.users.c.disabled)) query = db.users.select().where(where) - ret = yield from conn.execute(query) - user = yield from ret.fetchone() + ret = await conn.execute(query) + user = await ret.fetchone() if user is not None: hash = user[2] return sha256_crypt.verify(password, hash) diff --git a/tests/test_cookies_identity.py b/tests/test_cookies_identity.py index e197751..8d739e6 100644 --- a/tests/test_cookies_identity.py +++ b/tests/test_cookies_identity.py @@ -1,5 +1,3 @@ -import asyncio - from aiohttp import web from aiohttp_security import (remember, forget, AbstractAuthorizationPolicy) @@ -10,47 +8,39 @@ from aiohttp_security.api import IDENTITY_KEY class Autz(AbstractAuthorizationPolicy): - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): pass - @asyncio.coroutine - def authorized_userid(self, identity): + async def authorized_userid(self, identity): pass -@asyncio.coroutine -def test_remember(loop, test_client): +async def test_remember(loop, test_client): - @asyncio.coroutine - def handler(request): + async def handler(request): response = web.Response() - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response app = web.Application(loop=loop) _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', handler) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert 200 == resp.status assert 'Andrew' == resp.cookies['AIOHTTP_SECURITY'].value - yield from resp.release() -@asyncio.coroutine -def test_identify(loop, test_client): +async def test_identify(loop, test_client): - @asyncio.coroutine - def create(request): + async def create(request): response = web.Response() - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response - @asyncio.coroutine - def check(request): + async def check(request): policy = request.app[IDENTITY_KEY] - user_id = yield from policy.identify(request) + user_id = await policy.identify(request) assert 'Andrew' == user_id return web.Response() @@ -58,32 +48,27 @@ def test_identify(loop, test_client): _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', check) app.router.add_route('POST', '/', create) - client = yield from test_client(app) - resp = yield from client.post('/') + client = await test_client(app) + resp = await client.post('/') assert 200 == resp.status - yield from resp.release() - resp = yield from client.get('/') + await resp.release() + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_forget(loop, test_client): +async def test_forget(loop, test_client): - @asyncio.coroutine - def index(request): + async def index(request): return web.Response() - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response - @asyncio.coroutine - def logout(request): + async def logout(request): response = web.HTTPFound(location='/') - yield from forget(request, response) + await forget(request, response) return response app = web.Application(loop=loop) @@ -91,18 +76,17 @@ def test_forget(loop, test_client): app.router.add_route('GET', '/', index) app.router.add_route('POST', '/login', login) app.router.add_route('POST', '/logout', logout) - client = yield from test_client(app) - resp = yield from client.post('/login') + client = await test_client(app) + resp = await client.post('/login') assert 200 == resp.status assert str(resp.url).endswith('/') cookies = client.session.cookie_jar.filter_cookies( client.make_url('/')) assert 'Andrew' == cookies['AIOHTTP_SECURITY'].value - yield from resp.release() - resp = yield from client.post('/logout') + + resp = await client.post('/logout') assert 200 == resp.status assert str(resp.url).endswith('/') cookies = client.session.cookie_jar.filter_cookies( client.make_url('/')) assert 'AIOHTTP_SECURITY' not in cookies - yield from resp.release() diff --git a/tests/test_dict_autz.py b/tests/test_dict_autz.py index add2224..9151ce0 100644 --- a/tests/test_dict_autz.py +++ b/tests/test_dict_autz.py @@ -1,4 +1,3 @@ -import asyncio import enum from aiohttp import web @@ -11,33 +10,28 @@ from aiohttp_security.cookies_identity import CookiesIdentityPolicy class Autz(AbstractAuthorizationPolicy): - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): if identity == 'UserID': return permission in {'read', 'write'} else: return False - @asyncio.coroutine - def authorized_userid(self, identity): + async def authorized_userid(self, identity): if identity == 'UserID': return 'Andrew' else: return None -@asyncio.coroutine -def test_authorized_userid(loop, test_client): +async def test_authorized_userid(loop, test_client): - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'UserID') + await remember(request, response, 'UserID') return response - @asyncio.coroutine - def check(request): - userid = yield from authorized_userid(request) + async def check(request): + userid = await authorized_userid(request) assert 'Andrew' == userid return web.Response(text=userid) @@ -45,36 +39,31 @@ def test_authorized_userid(loop, test_client): _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', check) app.router.add_route('POST', '/login', login) - client = yield from test_client(app) + client = await test_client(app) - resp = yield from client.post('/login') + resp = await client.post('/login') assert 200 == resp.status - txt = yield from resp.text() + txt = await resp.text() assert 'Andrew' == txt - yield from resp.release() -@asyncio.coroutine -def test_authorized_userid_not_authorized(loop, test_client): +async def test_authorized_userid_not_authorized(loop, test_client): - @asyncio.coroutine - def check(request): - userid = yield from authorized_userid(request) + async def check(request): + userid = await authorized_userid(request) assert userid is None return web.Response() app = web.Application(loop=loop) _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', check) - client = yield from test_client(app) + client = await test_client(app) - resp = yield from client.get('/') + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_permits_enum_permission(loop, test_client): +async def test_permits_enum_permission(loop, test_client): class Permission(enum.Enum): READ = '101' WRITE = '102' @@ -82,33 +71,29 @@ def test_permits_enum_permission(loop, test_client): class Autz(AbstractAuthorizationPolicy): - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): if identity == 'UserID': return permission in {Permission.READ, Permission.WRITE} else: return False - @asyncio.coroutine - def authorized_userid(self, identity): + async def authorized_userid(self, identity): if identity == 'UserID': return 'Andrew' else: return None - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'UserID') + await remember(request, response, 'UserID') return response - @asyncio.coroutine - def check(request): - ret = yield from permits(request, Permission.READ) + async def check(request): + ret = await permits(request, Permission.READ) assert ret - ret = yield from permits(request, Permission.WRITE) + ret = await permits(request, Permission.WRITE) assert ret - ret = yield from permits(request, Permission.UNKNOWN) + ret = await permits(request, Permission.UNKNOWN) assert not ret return web.Response() @@ -116,54 +101,46 @@ def test_permits_enum_permission(loop, test_client): _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', check) app.router.add_route('POST', '/login', login) - client = yield from test_client(app) - resp = yield from client.post('/login') + client = await test_client(app) + resp = await client.post('/login') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_permits_unauthorized(loop, test_client): +async def test_permits_unauthorized(loop, test_client): - @asyncio.coroutine - def check(request): - ret = yield from permits(request, 'read') + async def check(request): + ret = await permits(request, 'read') assert not ret - ret = yield from permits(request, 'write') + ret = await permits(request, 'write') assert not ret - ret = yield from permits(request, 'unknown') + ret = await permits(request, 'unknown') assert not ret return web.Response() app = web.Application(loop=loop) _setup(app, CookiesIdentityPolicy(), Autz()) app.router.add_route('GET', '/', check) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_is_anonymous(loop, test_client): +async def test_is_anonymous(loop, test_client): - @asyncio.coroutine - def index(request): - is_anon = yield from is_anonymous(request) + async def index(request): + is_anon = await is_anonymous(request) if is_anon: return web.HTTPUnauthorized() return web.HTTPOk() - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'UserID') + await remember(request, response, 'UserID') return response - @asyncio.coroutine - def logout(request): + async def logout(request): response = web.HTTPFound(location='/') - yield from forget(request, response) + await forget(request, response) return response app = web.Application(loop=loop) @@ -171,36 +148,32 @@ def test_is_anonymous(loop, test_client): app.router.add_route('GET', '/', index) app.router.add_route('POST', '/login', login) app.router.add_route('POST', '/logout', logout) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert web.HTTPUnauthorized.status_code == resp.status - yield from client.post('/login') - resp = yield from client.get('/') + await client.post('/login') + resp = await client.get('/') assert web.HTTPOk.status_code == resp.status - yield from client.post('/logout') - resp = yield from client.get('/') + await client.post('/logout') + resp = await client.get('/') assert web.HTTPUnauthorized.status_code == resp.status -@asyncio.coroutine -def test_login_required(loop, test_client): +async def test_login_required(loop, test_client): @login_required - @asyncio.coroutine - def index(request): + async def index(request): return web.HTTPOk() - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'UserID') + await remember(request, response, 'UserID') return response - @asyncio.coroutine - def logout(request): + async def logout(request): response = web.HTTPFound(location='/') - yield from forget(request, response) + await forget(request, response) return response app = web.Application(loop=loop) @@ -208,47 +181,41 @@ def test_login_required(loop, test_client): app.router.add_route('GET', '/', index) app.router.add_route('POST', '/login', login) app.router.add_route('POST', '/logout', logout) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert web.HTTPUnauthorized.status_code == resp.status - yield from client.post('/login') - resp = yield from client.get('/') + await client.post('/login') + resp = await client.get('/') assert web.HTTPOk.status_code == resp.status - yield from client.post('/logout') - resp = yield from client.get('/') + await client.post('/logout') + resp = await client.get('/') assert web.HTTPUnauthorized.status_code == resp.status -@asyncio.coroutine -def test_has_permission(loop, test_client): +async def test_has_permission(loop, test_client): @has_permission('read') - @asyncio.coroutine - def index_read(request): + async def index_read(request): return web.HTTPOk() @has_permission('write') - @asyncio.coroutine - def index_write(request): + async def index_write(request): return web.HTTPOk() @has_permission('forbid') - @asyncio.coroutine - def index_forbid(request): + async def index_forbid(request): return web.HTTPOk() - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'UserID') + await remember(request, response, 'UserID') return response - @asyncio.coroutine - def logout(request): + async def logout(request): response = web.HTTPFound(location='/') - yield from forget(request, response) + await forget(request, response) return response app = web.Application(loop=loop) @@ -258,27 +225,27 @@ def test_has_permission(loop, test_client): app.router.add_route('GET', '/permission/forbid', index_forbid) app.router.add_route('POST', '/login', login) app.router.add_route('POST', '/logout', logout) - client = yield from test_client(app) + client = await test_client(app) - resp = yield from client.get('/permission/read') + resp = await client.get('/permission/read') assert web.HTTPUnauthorized.status_code == resp.status - resp = yield from client.get('/permission/write') + resp = await client.get('/permission/write') assert web.HTTPUnauthorized.status_code == resp.status - resp = yield from client.get('/permission/forbid') + resp = await client.get('/permission/forbid') assert web.HTTPUnauthorized.status_code == resp.status - yield from client.post('/login') - resp = yield from client.get('/permission/read') + await client.post('/login') + resp = await client.get('/permission/read') assert web.HTTPOk.status_code == resp.status - resp = yield from client.get('/permission/write') + resp = await client.get('/permission/write') assert web.HTTPOk.status_code == resp.status - resp = yield from client.get('/permission/forbid') + resp = await client.get('/permission/forbid') assert web.HTTPForbidden.status_code == resp.status - yield from client.post('/logout') - resp = yield from client.get('/permission/read') + await client.post('/logout') + resp = await client.get('/permission/read') assert web.HTTPUnauthorized.status_code == resp.status - resp = yield from client.get('/permission/write') + resp = await client.get('/permission/write') assert web.HTTPUnauthorized.status_code == resp.status - resp = yield from client.get('/permission/forbid') + resp = await client.get('/permission/forbid') assert web.HTTPUnauthorized.status_code == resp.status diff --git a/tests/test_no_auth.py b/tests/test_no_auth.py index cdc448e..55051df 100644 --- a/tests/test_no_auth.py +++ b/tests/test_no_auth.py @@ -1,42 +1,34 @@ -import asyncio - from aiohttp import web from aiohttp_security import authorized_userid, permits -@asyncio.coroutine -def test_authorized_userid(loop, test_client): +async def test_authorized_userid(loop, test_client): - @asyncio.coroutine - def check(request): - userid = yield from authorized_userid(request) + async def check(request): + userid = await authorized_userid(request) assert userid is None return web.Response() app = web.Application(loop=loop) app.router.add_route('GET', '/', check) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_permits(loop, test_client): +async def test_permits(loop, test_client): - @asyncio.coroutine - def check(request): - ret = yield from permits(request, 'read') + async def check(request): + ret = await permits(request, 'read') assert ret - ret = yield from permits(request, 'write') + ret = await permits(request, 'write') assert ret - ret = yield from permits(request, 'unknown') + ret = await permits(request, 'unknown') assert ret return web.Response() app = web.Application(loop=loop) app.router.add_route('GET', '/', check) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() diff --git a/tests/test_no_identity.py b/tests/test_no_identity.py index c2bd329..208521b 100644 --- a/tests/test_no_identity.py +++ b/tests/test_no_identity.py @@ -1,42 +1,34 @@ -import asyncio - from aiohttp import web from aiohttp_security import remember, forget -@asyncio.coroutine -def test_remember(loop, test_client): +async def test_remember(loop, test_client): - @asyncio.coroutine - def do_remember(request): + async def do_remember(request): response = web.Response() - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') app = web.Application(loop=loop) app.router.add_route('POST', '/', do_remember) - client = yield from test_client(app) - resp = yield from client.post('/') + client = await test_client(app) + resp = await client.post('/') assert 500 == resp.status assert (('Security subsystem is not initialized, ' 'call aiohttp_security.setup(...) first') == resp.reason) - yield from resp.release() -@asyncio.coroutine -def test_forget(loop, test_client): +async def test_forget(loop, test_client): - @asyncio.coroutine - def do_forget(request): + async def do_forget(request): response = web.Response() - yield from forget(request, response) + await forget(request, response) app = web.Application(loop=loop) app.router.add_route('POST', '/', do_forget) - client = yield from test_client(app) - resp = yield from client.post('/') + client = await test_client(app) + resp = await client.post('/') assert 500 == resp.status assert (('Security subsystem is not initialized, ' 'call aiohttp_security.setup(...) first') == resp.reason) - yield from resp.release() diff --git a/tests/test_session_identity.py b/tests/test_session_identity.py index 86f9cf7..d6377a8 100644 --- a/tests/test_session_identity.py +++ b/tests/test_session_identity.py @@ -1,4 +1,3 @@ -import asyncio import pytest from aiohttp import web @@ -13,12 +12,10 @@ from aiohttp_session import setup as setup_session class Autz(AbstractAuthorizationPolicy): - @asyncio.coroutine - def permits(self, identity, permission, context=None): + async def permits(self, identity, permission, context=None): pass - @asyncio.coroutine - def authorized_userid(self, identity): + async def authorized_userid(self, identity): pass @@ -30,81 +27,67 @@ def make_app(loop): return app -@asyncio.coroutine -def test_remember(make_app, test_client): +async def test_remember(make_app, test_client): - @asyncio.coroutine - def handler(request): + async def handler(request): response = web.Response() - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response - @asyncio.coroutine - def check(request): - session = yield from get_session(request) + async def check(request): + session = await get_session(request) assert session['AIOHTTP_SECURITY'] == 'Andrew' return web.HTTPOk() app = make_app() app.router.add_route('GET', '/', handler) app.router.add_route('GET', '/check', check) - client = yield from test_client(app) - resp = yield from client.get('/') + client = await test_client(app) + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() - resp = yield from client.get('/check') + resp = await client.get('/check') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_identify(make_app, test_client): +async def test_identify(make_app, test_client): - @asyncio.coroutine - def create(request): + async def create(request): response = web.Response() - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response - @asyncio.coroutine - def check(request): + async def check(request): policy = request.app[IDENTITY_KEY] - user_id = yield from policy.identify(request) + user_id = await policy.identify(request) assert 'Andrew' == user_id return web.Response() app = make_app() app.router.add_route('GET', '/', check) app.router.add_route('POST', '/', create) - client = yield from test_client(app) - resp = yield from client.post('/') + client = await test_client(app) + resp = await client.post('/') assert 200 == resp.status - yield from resp.release() - resp = yield from client.get('/') + resp = await client.get('/') assert 200 == resp.status - yield from resp.release() -@asyncio.coroutine -def test_forget(make_app, test_client): +async def test_forget(make_app, test_client): - @asyncio.coroutine - def index(request): - session = yield from get_session(request) + async def index(request): + session = await get_session(request) return web.HTTPOk(text=session.get('AIOHTTP_SECURITY', '')) - @asyncio.coroutine - def login(request): + async def login(request): response = web.HTTPFound(location='/') - yield from remember(request, response, 'Andrew') + await remember(request, response, 'Andrew') return response - @asyncio.coroutine - def logout(request): + async def logout(request): response = web.HTTPFound('/') - yield from forget(request, response) + await forget(request, response) return response app = make_app() @@ -112,18 +95,16 @@ def test_forget(make_app, test_client): app.router.add_route('POST', '/login', login) app.router.add_route('POST', '/logout', logout) - client = yield from test_client(app) + client = await test_client(app) - resp = yield from client.post('/login') + resp = await client.post('/login') assert 200 == resp.status assert str(resp.url).endswith('/') - txt = yield from resp.text() + txt = await resp.text() assert 'Andrew' == txt - yield from resp.release() - resp = yield from client.post('/logout') + resp = await client.post('/logout') assert 200 == resp.status assert str(resp.url).endswith('/') - txt = yield from resp.text() + txt = await resp.text() assert '' == txt - yield from resp.release()