|
@@ -4,9 +4,10 @@ from django.conf import settings
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
|
|
from rest_framework import authentication, exceptions
|
|
from rest_framework import authentication, exceptions
|
|
|
|
+from rest_framework.compat import is_authenticated
|
|
from rest_framework.exceptions import APIException
|
|
from rest_framework.exceptions import APIException
|
|
from rest_framework.pagination import LimitOffsetPagination
|
|
from rest_framework.pagination import LimitOffsetPagination
|
|
-from rest_framework.permissions import DjangoModelPermissions, SAFE_METHODS
|
|
|
|
|
|
+from rest_framework.permissions import BasePermission, DjangoModelPermissions, SAFE_METHODS
|
|
from rest_framework.serializers import Field, ValidationError
|
|
from rest_framework.serializers import Field, ValidationError
|
|
|
|
|
|
from users.models import Token
|
|
from users.models import Token
|
|
@@ -20,6 +21,10 @@ class ServiceUnavailable(APIException):
|
|
default_detail = "Service temporarily unavailable, please try again later."
|
|
default_detail = "Service temporarily unavailable, please try again later."
|
|
|
|
|
|
|
|
|
|
|
|
+#
|
|
|
|
+# Authentication
|
|
|
|
+#
|
|
|
|
+
|
|
class TokenAuthentication(authentication.TokenAuthentication):
|
|
class TokenAuthentication(authentication.TokenAuthentication):
|
|
"""
|
|
"""
|
|
A custom authentication scheme which enforces Token expiration times.
|
|
A custom authentication scheme which enforces Token expiration times.
|
|
@@ -61,6 +66,20 @@ class TokenPermissions(DjangoModelPermissions):
|
|
return super(TokenPermissions, self).has_permission(request, view)
|
|
return super(TokenPermissions, self).has_permission(request, view)
|
|
|
|
|
|
|
|
|
|
|
|
+class IsAuthenticatedOrLoginNotRequired(BasePermission):
|
|
|
|
+ """
|
|
|
|
+ Returns True if the user is authenticated or LOGIN_REQUIRED is False.
|
|
|
|
+ """
|
|
|
|
+ def has_permission(self, request, view):
|
|
|
|
+ if not settings.LOGIN_REQUIRED:
|
|
|
|
+ return True
|
|
|
|
+ return request.user and is_authenticated(request.user)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#
|
|
|
|
+# Serializers
|
|
|
|
+#
|
|
|
|
+
|
|
class ChoiceFieldSerializer(Field):
|
|
class ChoiceFieldSerializer(Field):
|
|
"""
|
|
"""
|
|
Represent a ChoiceField as {'value': <DB value>, 'label': <string>}.
|
|
Represent a ChoiceField as {'value': <DB value>, 'label': <string>}.
|
|
@@ -98,6 +117,10 @@ class ContentTypeFieldSerializer(Field):
|
|
raise ValidationError("Invalid content type")
|
|
raise ValidationError("Invalid content type")
|
|
|
|
|
|
|
|
|
|
|
|
+#
|
|
|
|
+# Mixins
|
|
|
|
+#
|
|
|
|
+
|
|
class ModelValidationMixin(object):
|
|
class ModelValidationMixin(object):
|
|
"""
|
|
"""
|
|
Enforce a model's validation through clean() when validating serializer data. This is necessary to ensure we're
|
|
Enforce a model's validation through clean() when validating serializer data. This is necessary to ensure we're
|
|
@@ -119,6 +142,10 @@ class WritableSerializerMixin(object):
|
|
return self.serializer_class
|
|
return self.serializer_class
|
|
|
|
|
|
|
|
|
|
|
|
+#
|
|
|
|
+# Pagination
|
|
|
|
+#
|
|
|
|
+
|
|
class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
|
class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
|
"""
|
|
"""
|
|
Override the stock paginator to allow setting limit=0 to disable pagination for a request. This returns all objects
|
|
Override the stock paginator to allow setting limit=0 to disable pagination for a request. This returns all objects
|