Я пытаюсь реализовать функцию сброса пароля в моем приложении React с помощью django rest framework.Я использую rest_auth.
Проблема: После того, как я попытался сбросить пароль с веб-сайта, он отправляет ссылку для сброса пароля на электронную почту.Но при нажатии на эту ссылку он перенаправляет на страницу сброса пароля по умолчанию в DRF, а не на желаемую страницу сброса пароля моего сайта.Он работает нормально, когда я попробовал это с localhost.Но после развертывания в Heroku он не работает.
Некоторые наблюдения: рассмотрите ссылку ниже, которую я получил по электронной почте
https://mysite.herokuapp.com/password/reset/confirm/MQ/5a1-f42302b192f38cf29a3/
ЕслиЯ принудительно удалил косую черту (/) в URL, затем он перенаправляет на страницу сброса пароля моего сайта, и затем он работает как положено.Я попытался удалить косую черту из запроса axios из React, но он не работает.
Нужно ли что-то настраивать в Heroku?
Вот мой маршрут React для страницы сброса пароля
<Route path='/password/reset/confirm/:uid/:token/' component={PasswordRestConfirm} />
Это действие ниже запускается при отправке формы.
export const setNewPassword = (new_password1, new_password2, uid, token) => (dispatch, getState) => {
dispatch({ type: SET_NEW_PASSWORD_START });
var bodyFormData = new FormData();
bodyFormData.append('new_password1', new_password1);
bodyFormData.append('new_password2', new_password2);
bodyFormData.append('uid', uid);
bodyFormData.append('token', token);
axios
.post(`https://mysite.herokuapp.com/password/reset/confirm/${uid}/${token}/`, bodyFormData)
.then(res => {
dispatch(createMessage({ passwordChangeSuccess: 'Your password was set successfully' }));
dispatch({
type: SET_NEW_PASSWORD,
payload: res.data
});
})
.catch(err => {
dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: SET_NEW_PASSWORD_FAIL
});
});
};
settings.py
ALLOWED_HOSTS = ['mysite.herokuapp.com']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'corsheaders',
'rest_auth',
'rest_auth.registration',
'rest_framework',
'rest_framework.authtoken',
# Some other app
]
SITE_ID = 1
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
}
REST_AUTH_SERIALIZERS = {
'PASSWORD_RESET_SERIALIZER': 'accounts.api.serializers.PasswordResetSerializer',
'PASSWORD_RESET_CONFIRM_SERIALIZER ': 'accounts.api.serializers.PasswordResetConfirmSerializer',
}
REST_SESSION_LOGIN = True
CORS_ORIGIN_ALLOW_ALL = True
ACCOUNT_EMAIL_REQUIRED = False
ACCOUNT_EMAIL_VERIFICATION = 'none'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_AUTHENTICATION_METHOD = 'username'
# ***********Email settings **************
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ['EMAIL_USER']
EMAIL_HOST_PASSWORD = os.environ['EMAIL_PASS']
urls.py
urlpatterns = [
path('password/reset/confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
]
view.py
class PasswordResetConfirmView(GenericAPIView):
serializer_class = PasswordResetConfirmSerializer
permission_classes = (AllowAny,)
@sensitive_post_parameters_m
def dispatch(self, *args, **kwargs):
return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(
{"detail": _("Password has been reset with the new password.")}
)
serializers.py
class PasswordResetConfirmSerializer(serializers.Serializer):
"""
Serializer for requesting a password reset e-mail.
"""
new_password1 = serializers.CharField(max_length=128)
new_password2 = serializers.CharField(max_length=128)
uid = serializers.CharField()
token = serializers.CharField()
set_password_form_class = SetPasswordForm
def custom_validation(self, attrs):
pass
def validate(self, attrs):
self._errors = {}
# Decode the uidb64 to uid to get User object
try:
uid = force_text(uid_decoder(attrs['uid']))
print(uid)
self.user = UserModel._default_manager.get(pk=uid)
print(self.user)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
raise ValidationError({'uid': ['Invalid value']})
self.custom_validation(attrs)
# Construct SetPasswordForm instance
self.set_password_form = self.set_password_form_class(
user=self.user, data=attrs
)
if not self.set_password_form.is_valid():
raise serializers.ValidationError(self.set_password_form.errors)
if not default_token_generator.check_token(self.user, attrs['token']):
raise ValidationError({'token': ['Invalid value']})
return attrs
def save(self):
return self.set_password_form.save()