dj-rest-аутентификация: УЧЕТНАЯ ЗАПИСЬ_ЛОГИН_ОН_ЭМАЙЛ_ПОДТВЕРЖДЕНИЕ не работает

#django #django-rest-auth #dj-rest-auth

Вопрос:

Я использую dj-rest-auth, allauth и simple jwt для реализации аутентификации.

В django-allauth установка ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION=True автоматически приведет к входу пользователя в систему после подтверждения электронной почты. Но отправка ключа в «/dj-rest-auth/регистрация/проверка электронной почты/» возвращает только {«подробности»:»ок»}.

В приведенном ниже исходном коде объясняется, почему:

 # allauth
class ConfirmEmailView(TemplateResponseMixin, LogoutFunctionalityMixin, View):
    # ...

    def post(self, *args, **kwargs):
        # ...

        if app_settings.LOGIN_ON_EMAIL_CONFIRMATION:
            resp = self.login_on_confirm(confirmation)
            if resp is not None:
                return resp # this is a HttpResponseRedirect object
 
 # ...
# dj-rest-auth
class VerifyEmailView(APIView, ConfirmEmailView):
    # ...

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.kwargs['key'] = serializer.validated_data['key']
        confirmation = self.get_object()
        confirmation.confirm(self.request)
        return Response({'detail': _('ok')}, status=status.HTTP_200_OK)
 

Поскольку я использую JWT, как я могу переопределить это представление для входа пользователя в систему после проверки и возврата кода доступа?

Ответ №1:

Вы должны взять этот объект подтверждения, написать confirmation.email_address , который является объектом модели адреса электронной почты django-allauth, а затем получить пользователя (т. Е. вашу модель пользователя). В общем, просто делай confirmation.email_address.user . Наконец, создайте JWT из объекта пользователя.

Чтобы сгенерировать правильный ответ JSON, создайте экземпляр класса LoginView, установите атрибут класса пользователя , выполнив view = LoginView(); view.user = confirmation.email_address.user; # TODO do view.login() but you need to customize it so that you don't call user , и захватите объект ответа, выполнив LoginView().get_response()

Убедитесь, что вы проверяете все крайние случаи, например, если адрес электронной почты не существует и т. Д.

В целом:

 class CustomVerifyEmailView(VerifyEmailView):
    # ...

    def post(self, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.kwargs['key'] = serializer.validated_data['key']
        confirmation = self.get_object()
        confirmation.confirm(self.request)
        login_view = LoginView()
        login_view.user = confirmation.email_address.user

        if getattr(settings, 'REST_USE_JWT', False):
            self.access_token, self.refresh_token = jwt_encode(self.user)
        else:
            self.token = create_token(
                self.token_model, self.user,
                self.serializer,
            )

        if getattr(settings, 'REST_SESSION_LOGIN', True):
            self.process_login()

        return login_view.get_response()
 

Дайте нам знать, если это сработает!

Рекомендации:

Я также опубликовал это в вашем выпуске GitHub. Так что, надеюсь, какие бы изменения ни происходили здесь, они также окажутся и там.

Ответ №2:

Мне пришлось иметь дело с точно таким же случаем, и то, что, кажется, очень хорошо работает для меня, заключается в следующем

  1. Создайте представление проверки электронной почты custome вместо использования предоставленного представления из dj_rest_auth.
  2. Скопируйте большую часть кода из собственного метода post исходного файла VerifyEmailView
  3. добавьте строку для получения токенов jwt (self.access_token, self.refresh_token = jwt_encode(подтверждение.адрес электронной почты.пользователь))
  4. Ответ с помощью токенов

все и все мое пользовательское представление выглядит так

 from dj_rest_auth.utils import jwt_encode
from dj_rest_auth.registration.views import VerifyEmailView

class CustomeVerifyEmailView(VerifyEmailView):
    
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.kwargs['key'] = serializer.validated_data['key']
        confirmation = self.get_object()
        confirmation.confirm(self.request)
       
        self.access_token, self.refresh_token = jwt_encode(confirmation.email_address.user)
        return Response({"refresh": str(self.refresh_token), "access": str(self.access_token)})