Source code for restless.auth

from django.contrib import auth
from django.utils.encoding import DjangoUnicodeDecodeError
import base64

try:
    from django.utils.encoding import smart_text
except ImportError:
    from django.utils.encoding import smart_unicode as smart_text


from .views import Endpoint
from .http import Http200, Http401, Http403
from .models import serialize


__all__ = ['UsernamePasswordAuthMixin', 'BasicHttpAuthMixin',
    'AuthenticateEndpoint', 'login_required']


[docs]class UsernamePasswordAuthMixin(object): """ :py:class:`restless.views.Endpoint` mixin providing user authentication based on username and password (as specified in "username" and "password" request GET params). """ def authenticate(self, request): if request.method == 'POST': self.username = request.data.get('username') self.password = request.data.get('password') else: self.username = request.params.get('username') self.password = request.params.get('password') user = auth.authenticate(username=self.username, password=self.password) if user is not None and user.is_active: auth.login(request, user)
# Taken from Django Rest Framework
[docs]class BasicHttpAuthMixin(object): """ :py:class:`restless.views.Endpoint` mixin providing user authentication based on HTTP Basic authentication. """ def authenticate(self, request): if 'HTTP_AUTHORIZATION' in request.META: authdata = request.META['HTTP_AUTHORIZATION'].split() if len(authdata) == 2 and authdata[0].lower() == "basic": try: raw = authdata[1].encode('ascii') auth_parts = base64.b64decode(raw).split(b':') except: return try: uname, passwd = (smart_text(auth_parts[0]), smart_text(auth_parts[1])) except DjangoUnicodeDecodeError: return user = auth.authenticate(username=uname, password=passwd) if user is not None and user.is_active: # We don't user auth.login(request, user) because # may be running without session request.user = user
[docs]def login_required(fn): """ Decorator for :py:class:`restless.views.Endpoint` methods to require authenticated, active user. If the user isn't authenticated, HTTP 403 is returned immediately (HTTP 401 if Basic HTTP authentication is used). """ def wrapper(self, request, *args, **kwargs): if request.user is None or not request.user.is_active: if isinstance(self, BasicHttpAuthMixin): return Http401() else: return Http403('forbidden') return fn(self, request, *args, **kwargs) wrapper.__name__ = fn.__name__ wrapper.__doc__ = fn.__doc__ return wrapper
[docs]class AuthenticateEndpoint(Endpoint, UsernamePasswordAuthMixin): """ Session-based authentication API endpoint. Provides a GET method for authenticating the user based on passed-in "username" and "password" request params. On successful authentication, the method returns authenticated user details. Uses :py:class:`UsernamePasswordAuthMixin` to actually implement the Authentication API endpoint. On success, the user will get a response with their serialized User object, containing id, username, first_name, last_name and email fields. """ user_fields = ('id', 'username', 'first_name', 'last_name', 'email') @login_required def get(self, request): return Http200(serialize(request.user, fields=self.user_fields))