I am using Django with React, I am implementing a method to reset user password when users forget their password. My basic idea is to:
1) Users give their email address
2) Send an email to their email adress with the link to reset their password(with SendGrid api)
3) Users type in new password to reset their password
below is my serializers, views, urls and React code
//views.py
class PasswordResetConfirmSerializer(serializers.Serializer):
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 = {}
try:
self.user = UserModel._default_manager.get(pk=attrs['uid'])
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
raise ValidationError({'uid': ['Invalid value']})
self.custom_validation(attrs)
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)
return attrs
def save(self):
return self.set_password_form.save()
// serializers.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.")}
)
//urls.py
path('api/passwordreset/confirm/',views.PasswordResetConfirmView.as_view(), name = 'password_reset_confirm')
// React
const config = {
headers: {
"Content-Type": "application/json"
}
};
const body = JSON.stringify({
new_password1: this.state.new_password,
new_password2: this.state.confirm_password,
uid: this.state.fetched_data.pk,
token: this.state.fetched_data.token
})
axios.post(API_URL + 'users/api/passwordreset/confirm/', body, config)
My reset password function itself works fine. But the main problem I am having here is that the reset password API requires 'uid' and 'token'. In order to get these two values, users have to be either logged in, which makes no sense since they forget their password, or to call an api to get the 'uid' and the 'token'. I tried the below method to get those two values:
// views.py
class CustomObtainAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
return Response({'token': token.key, 'id': token.user_id})
// urls.py
path('api/authenticate/', CustomObtainAuthToken.as_view())
// React
const body = {
password: 'mike',
username: 'Abcd1234'
}
await axios.post(API_URL + 'users/api/authenticate/', body)
The function does return the corret 'uid' and 'token', but the problem is that the only thing I am getting from the user is the email address. There is no way for me to also get the password and username to call this API. So I am not really sure how to do this.
Can someone show me the correct way to make this work? Thanks a lot.