serializers.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. from django.conf import settings
  2. from django.utils.translation import gettext_lazy as _
  3. from rest_framework import serializers, exceptions
  4. from allauth.account.forms import default_token_generator
  5. from dj_rest_auth.serializers import PasswordResetSerializer
  6. from dj_rest_auth.registration.serializers import (
  7. SocialAccountSerializer as BaseSocialAccountSerializer,
  8. )
  9. from allauth.socialaccount.models import SocialApp
  10. from allauth.account.adapter import get_adapter
  11. from allauth.account import app_settings
  12. from allauth.account.utils import filter_users_by_email
  13. from allauth.account.models import EmailAddress
  14. from .utils import is_user_registration_open
  15. from .models import User
  16. from .forms import PasswordSetAndResetForm
  17. class SocialAccountSerializer(BaseSocialAccountSerializer):
  18. email = serializers.SerializerMethodField()
  19. username = serializers.SerializerMethodField()
  20. class Meta(BaseSocialAccountSerializer.Meta):
  21. fields = (
  22. "id",
  23. "provider",
  24. "uid",
  25. "last_login",
  26. "date_joined",
  27. "email",
  28. "username",
  29. )
  30. def get_email(self, obj):
  31. if obj.extra_data:
  32. if "email" in obj.extra_data:
  33. return obj.extra_data.get("email")
  34. return obj.extra_data.get("userPrincipalName") # MS oauth uses this
  35. def get_username(self, obj):
  36. if obj.extra_data:
  37. return obj.extra_data.get("username")
  38. class SocialAppSerializer(serializers.ModelSerializer):
  39. class Meta:
  40. model = SocialApp
  41. fields = ("provider", "name", "client_id")
  42. class ConfirmEmailAddressSerializer(serializers.Serializer):
  43. email = serializers.EmailField()
  44. class EmailAddressSerializer(serializers.ModelSerializer):
  45. isPrimary = serializers.BooleanField(source="primary", read_only=True)
  46. email = serializers.EmailField() # Remove default unique validation
  47. isVerified = serializers.BooleanField(source="verified", read_only=True)
  48. class Meta:
  49. model = EmailAddress
  50. fields = ("isPrimary", "email", "isVerified")
  51. def clean_email(self):
  52. """ Validate email as done in allauth.account.forms.AddEmailForm """
  53. value = self.cleaned_data["email"]
  54. value = get_adapter().clean_email(value)
  55. errors = {
  56. "this_account": _(
  57. "This e-mail address is already associated" " with this account."
  58. ),
  59. "different_account": _(
  60. "This e-mail address is already associated" " with another account."
  61. ),
  62. }
  63. users = filter_users_by_email(value)
  64. on_this_account = [u for u in users if u.pk == self.user.pk]
  65. on_diff_account = [u for u in users if u.pk != self.user.pk]
  66. if on_this_account:
  67. raise serializers.ValidationError(errors["this_account"])
  68. if on_diff_account and app_settings.UNIQUE_EMAIL:
  69. raise serializers.ValidationError(errors["different_account"])
  70. return value
  71. def validate(self, data):
  72. if self.context["request"].method == "POST":
  73. # Run extra validation on create
  74. self.user = self.context["request"].user
  75. self.cleaned_data = data
  76. data["email"] = self.clean_email()
  77. return data
  78. def create(self, validated_data):
  79. return EmailAddress.objects.add_email(
  80. self.context["request"], self.user, validated_data["email"], confirm=True
  81. )
  82. def update(self, instance, validated_data):
  83. instance.primary = True
  84. instance.save()
  85. return instance
  86. class UserSerializer(serializers.ModelSerializer):
  87. username = serializers.CharField(source="email", read_only=True)
  88. lastLogin = serializers.DateTimeField(source="last_login", read_only=True)
  89. isSuperuser = serializers.BooleanField(source="is_superuser")
  90. emails = EmailAddressSerializer(many=True, default=[])
  91. identities = SocialAccountSerializer(
  92. source="socialaccount_set", many=True, read_only=True
  93. )
  94. id = serializers.CharField()
  95. isActive = serializers.BooleanField(source="is_active")
  96. dateJoined = serializers.DateTimeField(source="created", read_only=True)
  97. hasPasswordAuth = serializers.BooleanField(
  98. source="has_usable_password", read_only=True
  99. )
  100. class Meta:
  101. model = User
  102. fields = (
  103. "username",
  104. "lastLogin",
  105. "isSuperuser",
  106. "emails",
  107. "identities",
  108. "id",
  109. "isActive",
  110. "name",
  111. "dateJoined",
  112. "hasPasswordAuth",
  113. "email",
  114. )
  115. class UserNotificationsSerializer(serializers.ModelSerializer):
  116. subscribeByDefault = serializers.BooleanField(source="subscribe_by_default")
  117. class Meta:
  118. model = User
  119. fields = ("subscribeByDefault",)
  120. class NoopTokenSerializer(serializers.Serializer):
  121. """ dj-rest-auth requires tokens, but we don't use them. """
  122. class PasswordSetResetSerializer(PasswordResetSerializer):
  123. password_reset_form_class = PasswordSetAndResetForm
  124. def save(self):
  125. request = self.context.get("request")
  126. opts = {
  127. "use_https": request.is_secure(),
  128. "from_email": getattr(settings, "DEFAULT_FROM_EMAIL"),
  129. "request": request,
  130. "token_generator": default_token_generator,
  131. "subject_template_name": "registration/password_reset_subject.txt",
  132. "email_template_name": "registration/password_reset_email.txt",
  133. "html_email_template_name": "registration/password_reset_email.html",
  134. }
  135. opts.update(self.get_email_options())
  136. self.reset_form.save(**opts)