from django.contrib.auth import get_user_model
from rest_framework import serializers as rfs
from .models import AuthToken, Client
from .settings import durin_settings
User = get_user_model()
username_field = User.USERNAME_FIELD if hasattr(User, "USERNAME_FIELD") else "username"
[docs]class UserSerializer(rfs.ModelSerializer):
class Meta:
model = User
fields = (username_field,)
[docs]class TokenSessionsSerializer(rfs.ModelSerializer):
"""
Used in :class:`durin.views.TokenSessionsViewSet`.
.. versionadded:: 1.0.0
"""
class Meta:
model = AuthToken
fields = [
"id",
"client",
"created",
"expiry",
"has_expired",
"is_current",
"expires_in_str",
]
read_only_fields = [
"token",
"client",
"user",
"created",
"expiry",
"expires_in_str",
]
client = rfs.SlugRelatedField(
slug_field="name",
read_only=True,
)
expires_in_str = rfs.CharField(source="expires_in")
is_current = rfs.SerializerMethodField()
def get_is_current(self, obj: AuthToken) -> bool:
request = self.context["request"]
return obj.pk == request.auth.pk
[docs]class APIAccessTokenSerializer(rfs.ModelSerializer):
"""
Used in :class:`durin.views.APIAccessTokenView`.
.. versionadded:: 1.0.0
"""
class Meta:
model = AuthToken
fields = [
"client",
"created",
"expiry",
"has_expired",
"expires_in_str",
]
read_only_fields = [
"token",
"client",
"user",
"created",
"expiry",
"expires_in_str",
]
client = rfs.SlugRelatedField(
slug_field="name",
read_only=True,
)
expires_in_str = rfs.CharField(source="expires_in", read_only=True)
def get_field_names(self, declared_fields, info):
"""
:meta private:
"""
fields = super().get_field_names(declared_fields, info)
if (
durin_settings.API_ACCESS_RESPONSE_INCLUDE_TOKEN
or self.context["request"].method.upper() == "POST"
):
# only send token on POST/create request, or
# if `API_ACCESS_RESPONSE_INCLUDE_TOKEN` setting is True
fields.append("token")
return fields
def create(self, validated_data):
"""
:meta private:
"""
user = self.context["request"].user
client_name = self.context["client_name"]
if AuthToken.objects.filter(user=user, client__name=client_name).exists():
raise rfs.ValidationError("An API token was already issued to you.")
validated_data["user"] = user
validated_data["client"] = Client.objects.get(name=client_name)
return super().create(validated_data)