adding decorator and demo code
This commit is contained in:
parent
c951e3486f
commit
ffa1c08189
|
@ -1,5 +1,5 @@
|
|||
from .abc import AbstractIdentityPolicy, AbstractAuthorizationPolicy
|
||||
from .api import remember, forget, setup, authorize, permits
|
||||
from .api import remember, forget, setup, authorize, permits, get_user_identity
|
||||
from .cookies_identity import CookiesIdentityPolicy
|
||||
from .session_identity import SessionIdentityPolicy
|
||||
|
||||
|
@ -9,4 +9,5 @@ __version__ = '0.1.0'
|
|||
|
||||
__all__ = ('AbstractIdentityPolicy', 'AbstractAuthorizationPolicy',
|
||||
'CookiesIdentityPolicy', 'SessionIdentityPolicy',
|
||||
'remember', 'forget', 'authorize', 'permits', 'setup')
|
||||
'remember', 'forget', 'authorize', 'permits',
|
||||
'get_user_identity', 'setup')
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import asyncio
|
||||
import functools
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from aiohttp_security.abc import (AbstractIdentityPolicy,
|
||||
AbstractAuthorizationPolicy)
|
||||
|
||||
|
@ -16,18 +18,34 @@ def authorize(required=True, redirect_url=None, permission=None):
|
|||
# assuming first argument is request
|
||||
assert isinstance(args[0], web.Request)
|
||||
request = args[0]
|
||||
|
||||
# check if coroutine
|
||||
if asyncio.iscoroutinefunction(f):
|
||||
coro = f
|
||||
else:
|
||||
coro = asyncio.coroutine(f)
|
||||
identity = yield from get_user_identity(request)
|
||||
if not identity and required:
|
||||
raise web.HTTPForbidden()
|
||||
kwargs['identity'] = identity
|
||||
return (yield from coro(*args, **kwargs))
|
||||
return wrapped
|
||||
return wrapper
|
||||
|
||||
# get identity
|
||||
identity = yield from get_user_identity(request)
|
||||
kwargs['identity'] = identity
|
||||
|
||||
if required:
|
||||
|
||||
# check identity
|
||||
if not identity:
|
||||
return web.HTTPFound(redirect_url) if redirect_url \
|
||||
else web.HTTPForbidden(reason='not authenticated')
|
||||
|
||||
# check permission
|
||||
allowed = yield from permits(request, permission)
|
||||
if permission and not allowed:
|
||||
return web.HTTPForbidden(reason='unauthorized')
|
||||
|
||||
return (yield from coro(*args, **kwargs))
|
||||
|
||||
return wrapped
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
@ -78,6 +96,7 @@ def get_user_identity(request):
|
|||
identity = yield from identity_policy.identify(request)
|
||||
return identity
|
||||
|
||||
|
||||
'''
|
||||
@asyncio.coroutine
|
||||
def authorized_userid(request):
|
||||
|
@ -98,6 +117,8 @@ def permits(request, permission, context=None):
|
|||
assert isinstance(permission, str), permission
|
||||
assert permission
|
||||
autz_policy = request.app.get(AUTZ_KEY)
|
||||
if autz_policy is None:
|
||||
return True
|
||||
identity = yield from get_user_identity(request)
|
||||
access = yield from autz_policy.permits(identity, permission, context)
|
||||
return access
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import asyncio
|
||||
|
||||
from aiohttp_security.abc import AbstractAuthorizationPolicy
|
||||
|
||||
|
||||
class StubAuthorizationPolicy(AbstractAuthorizationPolicy):
|
||||
@asyncio.coroutine
|
||||
def permits(self, identity, permission, context=None):
|
||||
if identity == permission:
|
||||
return True
|
||||
return False
|
|
@ -0,0 +1,34 @@
|
|||
from aiohttp import web
|
||||
from aiohttp_jinja2 import render_template
|
||||
|
||||
from aiohttp_security import authorize, get_user_identity, remember, forget
|
||||
|
||||
|
||||
@authorize(required=True, redirect_url='/login', permission='Steve')
|
||||
async def index(request, identity=None):
|
||||
context = {'name': identity}
|
||||
response = render_template('index.html', request, context)
|
||||
return response
|
||||
|
||||
|
||||
async def login(request):
|
||||
identity = await get_user_identity(request)
|
||||
if identity:
|
||||
return web.HTTPFound('/')
|
||||
response = render_template('login.html', request, {})
|
||||
return response
|
||||
|
||||
|
||||
async def login_post(request):
|
||||
post_data = await request.post()
|
||||
user_id = post_data['username']
|
||||
password = post_data['password']
|
||||
response = web.Response(body=b'OK')
|
||||
await remember(request, response, user_id)
|
||||
return response
|
||||
|
||||
|
||||
async def logout(request):
|
||||
response = web.Response(body=b'OK')
|
||||
await forget(request, response)
|
||||
return response
|
|
@ -0,0 +1,27 @@
|
|||
import asyncio
|
||||
import os
|
||||
|
||||
import jinja2
|
||||
from aiohttp import web
|
||||
from aiohttp_jinja2 import setup as setup_jinja
|
||||
from aiohttp_session import setup as setup_session
|
||||
from aiohttp_session.redis_storage import RedisStorage
|
||||
from aioredis import create_pool
|
||||
|
||||
from aiohttp_security import setup as setup_security, SessionIdentityPolicy
|
||||
from .auth_policy import StubAuthorizationPolicy
|
||||
from .handlers import index, login, login_post, logout
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
redis_pool = loop.run_until_complete(create_pool(('localhost', 6379)))
|
||||
app = web.Application(loop=loop)
|
||||
setup_session(app, RedisStorage(redis_pool))
|
||||
setup_security(app,
|
||||
SessionIdentityPolicy(),
|
||||
StubAuthorizationPolicy())
|
||||
setup_jinja(app, loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
|
||||
app.router.add_route('GET', '/', index)
|
||||
app.router.add_route('GET', '/login', login)
|
||||
app.router.add_route('POST', '/login', login_post)
|
||||
app.router.add_route('GET', '/logout', logout)
|
||||
web.run_app(app)
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>aiohttp_security demo</title>
|
||||
</head>
|
||||
<body>
|
||||
{% block content %}{% endblock %}
|
||||
{% block script %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div>
|
||||
<h1>Hello {{name}}!</h1>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div>
|
||||
<h3>Login</h3>
|
||||
<form class="m-t" role="form" action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<input name="username" type="text" class="form-control" placeholder="ID" required="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input name="password" type="password" class="form-control" placeholder="Password" required="">
|
||||
</div>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -15,10 +15,6 @@ class Autz(AbstractAuthorizationPolicy):
|
|||
def permits(self, identity, permission, context=None):
|
||||
pass
|
||||
|
||||
@asyncio.coroutine
|
||||
def authorized_userid(self, identity):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.run_loop
|
||||
def test_remember(create_app_and_client):
|
||||
|
|
|
@ -2,8 +2,7 @@ import asyncio
|
|||
import pytest
|
||||
|
||||
from aiohttp import web
|
||||
from aiohttp_security import (remember,
|
||||
authorized_userid, permits,
|
||||
from aiohttp_security import (remember, permits, get_user_identity,
|
||||
AbstractAuthorizationPolicy)
|
||||
from aiohttp_security import setup as _setup
|
||||
from aiohttp_security.cookies_identity import CookiesIdentityPolicy
|
||||
|
@ -18,12 +17,14 @@ class Autz(AbstractAuthorizationPolicy):
|
|||
else:
|
||||
return False
|
||||
|
||||
'''
|
||||
@asyncio.coroutine
|
||||
def authorized_userid(self, identity):
|
||||
if identity == 'UserID':
|
||||
return 'Andrew'
|
||||
else:
|
||||
return None
|
||||
'''
|
||||
|
||||
|
||||
@pytest.mark.run_loop
|
||||
|
@ -32,12 +33,12 @@ def test_authorized_userid(create_app_and_client):
|
|||
@asyncio.coroutine
|
||||
def login(request):
|
||||
response = web.HTTPFound(location='/')
|
||||
yield from remember(request, response, 'UserID')
|
||||
yield from remember(request, response, 'Andrew')
|
||||
return response
|
||||
|
||||
@asyncio.coroutine
|
||||
def check(request):
|
||||
userid = yield from authorized_userid(request)
|
||||
userid = yield from get_user_identity(request)
|
||||
assert 'Andrew' == userid
|
||||
return web.Response(text=userid)
|
||||
|
||||
|
@ -58,7 +59,7 @@ def test_authorized_userid_not_authorized(create_app_and_client):
|
|||
|
||||
@asyncio.coroutine
|
||||
def check(request):
|
||||
userid = yield from authorized_userid(request)
|
||||
userid = yield from get_user_identity(request)
|
||||
assert userid is None
|
||||
return web.Response()
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import asyncio
|
|||
import pytest
|
||||
|
||||
from aiohttp import web
|
||||
from aiohttp_security import authorized_userid, permits
|
||||
from aiohttp_security import permits, get_user_identity
|
||||
|
||||
|
||||
@pytest.mark.run_loop
|
||||
|
@ -10,7 +10,7 @@ def test_authorized_userid(create_app_and_client):
|
|||
|
||||
@asyncio.coroutine
|
||||
def check(request):
|
||||
userid = yield from authorized_userid(request)
|
||||
userid = yield from get_user_identity(request)
|
||||
assert userid is None
|
||||
return web.Response()
|
||||
|
||||
|
|
|
@ -17,10 +17,6 @@ class Autz(AbstractAuthorizationPolicy):
|
|||
def permits(self, identity, permission, context=None):
|
||||
pass
|
||||
|
||||
@asyncio.coroutine
|
||||
def authorized_userid(self, identity):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def create_app_and_client2(create_app_and_client):
|
||||
|
|
Loading…
Reference in New Issue