simplify and clean ldt.api.authentication
authorymh <ymh.work@gmail.com>
Thu, 17 Sep 2015 19:45:35 +0200
changeset 1441 88f6b795bf95
parent 1440 e2cf46e32e9e
child 1442 eaca389b4df8
simplify and clean ldt.api.authentication
src/ldt/ldt/api/ldt/authentication.py
src/ldt/ldt/api/ldt/resources/content.py
src/ldt/ldt/api/ldt/resources/project.py
--- a/src/ldt/ldt/api/ldt/authentication.py	Thu Sep 17 17:49:45 2015 +0200
+++ b/src/ldt/ldt/api/ldt/authentication.py	Thu Sep 17 19:45:35 2015 +0200
@@ -1,16 +1,13 @@
-from django.conf import settings
-from django.middleware.csrf import _sanitize_token, constant_time_compare
-from django.utils.http import same_origin
-from tastypie.authentication import Authentication
-from tastypie.http import HttpUnauthorized
-from django.contrib.auth import get_user_model
-from django.contrib.auth import login
 from ldt.security import set_current_user
 
-User = get_user_model()
+from django.contrib.auth import login
+from tastypie.authentication import (
+    SessionAuthentication as TastypieSessionAuthentication,
+    ApiKeyAuthentication as TastypieApiKeyAuthentication)
+from tastypie.http import HttpUnauthorized
 
-# imported from tastypie's next version 0.9.12
-class SessionAuthentication(Authentication):
+
+class SessionAuthentication(TastypieSessionAuthentication):
     """
     An authentication mechanism that piggy-backs on Django sessions.
     
@@ -31,29 +28,7 @@
         # the serialized bodies.
         if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
             return True
-
-        if getattr(request, '_dont_enforce_csrf_checks', False):
-            return request.user.is_authenticated()
-
-        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))
-
-        if request.is_secure():
-            referer = request.META.get('HTTP_REFERER')
-
-            if referer is None:
-                return False
-
-            good_referer = 'https://%s/' % request.get_host()
-
-            if not same_origin(referer, good_referer):
-                return False
-
-        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
-
-        if not constant_time_compare(request_csrf_token, csrf_token):
-            return False
-
-        return request.user.is_authenticated()
+        return super(SessionAuthentication, self).is_authenticated(request, **kwargs)
 
     def get_identifier(self, request):
         """
@@ -61,53 +36,10 @@
         
         This implementation returns the user's username.
         """
-        if request.user:
-            return request.user.username
-        else:
-            return "anon."
-        
-# imported from tastypie's next version 1.0.0
-class MultiAuthentication(object):
-    """
-    An authentication backend that tries a number of backends in order.
-    """
-    def __init__(self, *backends, **kwargs):
-        super(MultiAuthentication, self).__init__(**kwargs)
-        self.backends = backends
-
-    def is_authenticated(self, request, **kwargs):
-        """
-        Identifies if the user is authenticated to continue or not.
-
-        Should return either ``True`` if allowed, ``False`` if not or an
-        ``HttpResponse`` if you need something custom.
-        """
-        unauthorized = False
+        return request.user.username or "anon."
 
-        for backend in self.backends:
-            check = backend.is_authenticated(request, **kwargs)
 
-            if check:
-                if isinstance(check, HttpUnauthorized):
-                    unauthorized = unauthorized or check
-                else:
-                    request._authentication_backend = backend
-                    return check
-
-        return unauthorized
-
-    def get_identifier(self, request):
-        """
-        Provides a unique string identifier for the requestor.
-
-        This implementation returns a combination of IP address and hostname.
-        """
-        try:
-            return request._authentication_backend.get_identifier(request)
-        except AttributeError:
-            return 'anon.'
-
-class ApiKeyAuthentication(Authentication):
+class ApiKeyAuthentication(TastypieApiKeyAuthentication):
     """
     Handles API key auth, in which a user provides a username & API key.
 
@@ -115,25 +47,6 @@
     a different model, override the ``get_key`` method to perform the key check
     as suits your needs.
     """
-    def __init__(self, require_active=True):
-        self.require_active = require_active
-        
-    def _unauthorized(self):
-        return HttpUnauthorized()
-
-    def extract_credentials(self, request):
-        if request.META.get('HTTP_AUTHORIZATION') and request.META['HTTP_AUTHORIZATION'].lower().startswith('apikey '):
-            (auth_type, data) = request.META['HTTP_AUTHORIZATION'].split()
-
-            if auth_type.lower() != 'apikey':
-                raise ValueError("Incorrect authorization header.")
-
-            username, api_key = data.split(':', 1)
-        else:
-            username = request.GET.get('username') or request.POST.get('username')
-            api_key = request.GET.get('api_key') or request.POST.get('api_key')
-
-        return username, api_key
 
     def is_authenticated(self, request, **kwargs):
         """
@@ -142,54 +55,15 @@
         Should return either ``True`` if allowed, ``False`` if not or an
         ``HttpResponse`` if you need something custom.
         """
-
-        try:
-            username, api_key = self.extract_credentials(request)
-        except ValueError:
-            return self._unauthorized()
-
-        if not username or not api_key:
-            return self._unauthorized()
-
-        try:
-            user = User.objects.get(username=username)
-        except (User.DoesNotExist, User.MultipleObjectsReturned):
-            return self._unauthorized()
-
-        if not self.check_active(user):
-            return False
-        user.backend = "django.contrib.auth.backends.ModelBackend"
-        request.user = user
-        login(request,user)
-        set_current_user(user)
-        return self.get_key(user, api_key)
+        resp = super(ApiKeyAuthentication, self).is_authenticated(request, **kwargs)
 
-    def check_active(self, user):
-        """
-        Ensures the user has an active account.
-
-        Optimized for the ``django.contrib.auth.models.User`` case.
-        """
-        if not self.require_active:
-            # Ignore & move on.
-            return True
-
-        return user.is_active
-
+        if resp and not isinstance(resp, HttpUnauthorized) and request.user:
+            request.user.backend = "django.contrib.auth.backends.ModelBackend"
+            login(request, request.user)
+            set_current_user(request.user)
 
-    def get_key(self, user, api_key):
-        """
-        Attempts to find the API key for the user. Uses ``ApiKey`` by default
-        but can be overridden.
-        """
-        from tastypie.models import ApiKey
+        return resp
 
-        try:
-            ApiKey.objects.get(user=user, key=api_key)
-        except ApiKey.DoesNotExist:
-            return self._unauthorized()
-
-        return True
 
     def get_identifier(self, request):
         """
@@ -198,4 +72,4 @@
         This implementation returns the user's username.
         """
         username, _ = self.extract_credentials(request)
-        return username or 'nouser'        
\ No newline at end of file
+        return username or 'anon.'
--- a/src/ldt/ldt/api/ldt/resources/content.py	Thu Sep 17 17:49:45 2015 +0200
+++ b/src/ldt/ldt/api/ldt/resources/content.py	Thu Sep 17 19:45:35 2015 +0200
@@ -1,4 +1,9 @@
 from itertools import groupby
+from ldt.api.ldt.authentication import (SessionAuthentication, ApiKeyAuthentication)
+from ldt.indexation import get_results_list
+from ldt.ldt_utils.models import Content, Media, Project, Segment
+from ldt.ldt_utils.projectserializer import ProjectJsonSerializer, ProjectMerger
+from ldt.security import unprotect_models, protect_models
 import logging
 
 from django.conf.urls import url
@@ -6,15 +11,9 @@
 from django.shortcuts import get_object_or_404
 from guardian.shortcuts import get_objects_for_group
 from tastypie import fields
+from tastypie.authentication import MultiAuthentication
 from tastypie.resources import Bundle, ModelResource, ALL_WITH_RELATIONS, ALL
 
-from ldt.api.ldt.authentication import (SessionAuthentication,
-    MultiAuthentication, ApiKeyAuthentication)
-from ldt.indexation import get_results_list
-from ldt.ldt_utils.models import Content, Media, Project, Segment
-from ldt.ldt_utils.projectserializer import ProjectJsonSerializer, ProjectMerger
-from ldt.security import unprotect_models, protect_models
-
 
 logger = logging.getLogger(__name__)
 
@@ -123,4 +122,4 @@
         
         return self.create_response(request, data)
         
-            
\ No newline at end of file
+            
--- a/src/ldt/ldt/api/ldt/resources/project.py	Thu Sep 17 17:49:45 2015 +0200
+++ b/src/ldt/ldt/api/ldt/resources/project.py	Thu Sep 17 19:45:35 2015 +0200
@@ -1,5 +1,4 @@
-from ldt.api.ldt.authentication import (SessionAuthentication,
-    MultiAuthentication, ApiKeyAuthentication)
+from ldt.api.ldt.authentication import (SessionAuthentication, ApiKeyAuthentication)
 from ldt.api.ldt.resources import ContentResource
 from ldt.api.ldt.resources.user import UserResource
 from ldt.api.ldt.serializers.cinelabserializer import CinelabSerializer
@@ -15,6 +14,7 @@
 from django.db import transaction
 from guardian.shortcuts import assign_perm
 from tastypie import fields, http
+from tastypie.authentication import MultiAuthentication
 from tastypie.authorization import Authorization
 from tastypie.exceptions import BadRequest
 from tastypie.resources import Bundle, ModelResource, ALL