Created
May 8, 2014 11:18
-
-
Save danielholmstrom/da50e76e8839378185ee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Auth views | |
~~~~~~~~~~ | |
""" | |
import functools | |
from pyramid.security import ( | |
remember, | |
forget, | |
authenticated_userid, | |
) | |
from colander import ( | |
Invalid, | |
) | |
from mylib.views import ( | |
InvalidDataError, | |
) | |
from .models import ( | |
AuthUser, | |
) | |
from .schemas import ( | |
Login, | |
) | |
def data_schema(schema, message=None, status=400): | |
"""Adds client data validation to a request | |
The schema validates the client data, not route parameters. | |
The validated data will be added to the request under 'validated_data' | |
""" | |
def decorator(view): | |
@functools.wraps(view) | |
def wrapper(request): | |
try: | |
data = schema().deserialize(request.client_data()) | |
except Invalid as e: | |
raise InvalidDataError(message=message, | |
errors=e.asdict(), | |
status=status) | |
setattr(request, 'validated_data', data) | |
return view(request) | |
return wrapper | |
return decorator | |
def validate(validator, message=None, status=400): | |
"""Run a validator before the view | |
The validator method should raise an error if validation failed. | |
The validator will be called like this: validator(request). | |
""" | |
def decorator(view): | |
@functools.wraps(view) | |
def wrapper(request): | |
validator(request) | |
return view(request) | |
return wrapper | |
return decorator | |
def require_not_authenticated(request): | |
if authenticated_userid(request): | |
raise InvalidDataError(message='You are already logged in') | |
@data_schema(schema=Login) | |
@validate(require_not_authenticated) | |
def login(request): | |
"""Login user""" | |
user_data = request.validated_data | |
user = request.db_session.query( | |
AuthUser).filter_by( | |
username=user_data['username']).first() | |
if not user or not user.validate_password(user_data['password']): | |
raise InvalidDataError(message='Invalid login') | |
headers = remember(request, user.id) | |
request.response.headerlist.extend(headers) | |
return request.response | |
def require_authenticated(request): | |
if not authenticated_userid(request): | |
raise InvalidDataError(message='You are not logged in') | |
@validate(require_authenticated) | |
def logout(request): | |
"""Logout user""" | |
headers = forget(request) | |
request.response.headerlist.extend(headers) | |
return request.response | |
def includeme(config): | |
config.add_view(view=login, | |
route_name='auth.login', | |
request_method='POST', | |
renderer='json', | |
content_type='application/json') | |
config.add_route('auth.login', | |
request_method='POST', | |
pattern='/login') | |
config.add_view(view=logout, | |
route_name='auth.logout', | |
request_method='POST', | |
renderer='json', | |
content_type='application/json') | |
config.add_route('auth.logout', | |
request_method='POST', | |
pattern='/logout') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment