# HG changeset patch # User ymh # Date 1442511935 -7200 # Node ID 88f6b795bf950d633cd374fa1abc9da4f1aa45a5 # Parent e2cf46e32e9e175b99764ec4d470c913cf3142d7 simplify and clean ldt.api.authentication diff -r e2cf46e32e9e -r 88f6b795bf95 src/ldt/ldt/api/ldt/authentication.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.' diff -r e2cf46e32e9e -r 88f6b795bf95 src/ldt/ldt/api/ldt/resources/content.py --- 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 + diff -r e2cf46e32e9e -r 88f6b795bf95 src/ldt/ldt/api/ldt/resources/project.py --- 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