Skip to content

Instantly share code, notes, and snippets.

@danielholmstrom
Created May 8, 2014 11:18
Show Gist options
  • Save danielholmstrom/da50e76e8839378185ee to your computer and use it in GitHub Desktop.
Save danielholmstrom/da50e76e8839378185ee to your computer and use it in GitHub Desktop.
"""
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