pythondjangodj-rest-auth

dj-rest-auth Reset email link keeps pointing to the backend


I'm using dj-rest-auth with react and i'm trying to use the frontend url instead of the backend url. The solution i am using for the account creation confirmation email affects the reset password email too but only partially. It does not effect the port. It only tries to add a key to the reset link where there is none and throws me an error.

So i was wondering if there is a way to change the url from port 8000 to port 3000. This is what i have tried:

class AccountAdapter(DefaultAccountAdapter):
    def is_open_for_signup(self, request: HttpRequest):
        return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)

    def send_mail(self, template_prefix, email, context):
        if settings.DEBUG:
            context["activate_url"] = (
                "http://localhost:3000/accounts/confirm-email/" + context["key"]
            )
        else:
            context["activate_url"] = (
                settings.FRONTEND_URL + "/accounts/confirm-email/" + context["key"]
            )
        return super().send_mail(template_prefix, email, context)

If i get rid of the key part it doesn't give me an error but keeps port 8000 and breaks my account confirmation emails. If i don't get rid of the key it gives me:

django          |     "http://localhost:3000/accounts/confirm-email/" + context["key"]
django          | KeyError: 'key'


Solution

  • This fixed it for me: https://stackoverflow.com/a/70624462/3530084

    serializers.py

    class CustomAllAuthPasswordResetForm(AllAuthPasswordResetForm):
        def save(self, request, **kwargs):
            current_site = get_current_site(request)
            email = self.cleaned_data['email']
            token_generator = kwargs.get('token_generator',
                                         default_token_generator)
    
            for user in self.users:
    
                temp_key = token_generator.make_token(user)
    
                # save it to the password reset model
                # password_reset = PasswordReset(user=user, temp_key=temp_key)
                # password_reset.save()
    
                # send the password reset email
                path = reverse(
                    'password_reset_confirm',
                    args=[user_pk_to_url_str(user), temp_key],
                )
                url = build_absolute_uri(None, path) # PASS NONE INSTEAD OF REQUEST
    
                context = {
                    'current_site': current_site,
                    'user': user,
                    'password_reset_url': url,
                    'request': request,
                }
                if app_settings.AUTHENTICATION_METHOD != app_settings.AuthenticationMethod.EMAIL:
                    context['username'] = user_username(user)
                get_adapter(request).send_mail('account/email/password_reset_key',
                                               email, context)
            return self.cleaned_data['email']
    
    class CustomPasswordResetSerializer(PasswordResetSerializer):
        @property
        def password_reset_form_class(self):
            return CustomAllAuthPasswordResetForm
    

    settings.py

    REST_AUTH_SERIALIZERS = {
        'PASSWORD_RESET_SERIALIZER':
        'seniorpark.users.api.serializers.CustomPasswordResetSerializer',
    }