def handle(self, *args, **options): # datetime.now minus expiry hours now_minus_expiry_time = timezone.now() - timedelta( hours=get_password_reset_token_expiry_time()) clear_expired(now_minus_expiry_time)
def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) email = serializer.validated_data.get("email") # before we continue, delete all existing expired tokens password_reset_token_validation_time = get_password_reset_token_expiry_time() # datetime.now minus expiry hours now_minus_expiry_time = timezone.now() - timedelta( hours=password_reset_token_validation_time ) # delete all tokens where created_at < now - 24 hours clear_expired(now_minus_expiry_time) # construct the condition # q = Q(username__iexact=email) | Q(email__iexact=email) # the hack is from https://stackoverflow.com/questions/28610144/q-object-parameters filters = get_password_reset_lookup_fields() filter_params = Q() for filter_obj in filters: filter_params |= Q(**{filter_obj: email}) # find a user by specified resetting field(case insensitive search) users = User.objects.filter(filter_params) active_user_found = False # iterate over all users and check if there is any user that is active # also check whether the password can be changed (is useable), as there could be users that are not allowed # to change their password (e.g., LDAP user) for user in users: if user.eligible_for_reset(): active_user_found = True # No active user found, raise a validation error # but not if DJANGO_REST_RESETPASSWORD_NO_INFORMATION_LEAKAGE == True if not active_user_found and not getattr( settings, "DJANGO_REST_RESETPASSWORD_NO_INFORMATION_LEAKAGE", False ): raise exceptions.ValidationError( { "email": [ _( "There is no active user associated with this e-mail address or username or the password can not be changed" ) ], } ) # last but not least: iterate over all users that are active and can change their password # and create a Reset Password Token and send a signal with the created token for user in users: if user.eligible_for_reset(): # define the token as none for now token = None # check if the user already has a token if user.password_reset_tokens.all().count() > 0: # yes, already has a token, re-use this token token = user.password_reset_tokens.all()[0] else: # no token exists, generate a new token token = ResetPasswordToken.objects.create( user=user, user_agent=request.META.get(HTTP_USER_AGENT_HEADER, ""), ip_address=request.META.get(HTTP_IP_ADDRESS_HEADER, ""), ) # send a signal that the password token was created # let whoever receives this signal handle sending the email for the password reset reset_password_token_created.send( sender=self.__class__, instance=self, reset_password_token=token ) # done response_format[ "message" ] = "A password reset token has been sent to the provided email address" response_format["status"] = True response_format["error"] = [] return Response(response_format)
def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data) try: serializer.is_valid(raise_exception=True) email = serializer.validated_data['email'] except: email = '' user = request.data.get('email') # before we continue, delete all existing expired tokens password_reset_token_validation_time = get_password_reset_token_expiry_time( ) # datetime.now minus expiry hours now_minus_expiry_time = timezone.now() - timedelta( hours=password_reset_token_validation_time) # delete all tokens where created_at < now - 24 hours clear_expired(now_minus_expiry_time) # find a user by email address (case insensitive search) users = AdvUser.objects.filter( **{'{}__iexact'.format(get_password_reset_lookup_field()): email}) if not users: users = AdvUser.objects.filter(username=user) active_user_found = False # iterate over all users and check if there is any user that is active # also check whether the password can be changed (is useable), as there could be users that are not allowed # to change their password (e.g., LDAP user) for user in users: if user.eligible_for_reset(): active_user_found = True # No active user found, raise a validation error # but not if DJANGO_REST_RESETPASSWORD_NO_INFORMATION_LEAKAGE == True if not active_user_found and not getattr( settings, 'DJANGO_REST_RESETPASSWORD_NO_INFORMATION_LEAKAGE', False): response_data = { 'email': 'There is no user with this email or username' } return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # last but not least: iterate over all users that are active and can change their password # and create a Reset Password Token and send a signal with the created token for user in users: if user.eligible_for_reset(): # define the token as none for now token = None # check if the user already has a token if user.password_reset_tokens.all().count() > 0: # yes, already has a token, re-use this token token = user.password_reset_tokens.all()[0] else: # no token exists, generate a new token token = ResetPasswordToken.objects.create( user=user, user_agent=request.META.get(HTTP_USER_AGENT_HEADER, ''), ip_address=request.META.get(HTTP_IP_ADDRESS_HEADER, ''), ) # send a signal that the password token was created # let whoever receives this signal handle sending the email for the password reset reset_password_token_created.send(sender=self.__class__, instance=self, reset_password_token=token, username=user.username, email=user.email) # done response_format = HttpRes().response response_format[ 'message'] = "A password reset token has been sent to the provided email address" response_format['status'] = True response_format['error'] = [] return Response(response_format)