1. import re
    
  2. 
    
  3. from django.contrib.auth.views import (
    
  4.     INTERNAL_RESET_SESSION_TOKEN,
    
  5.     PasswordResetConfirmView,
    
  6. )
    
  7. from django.test import Client
    
  8. 
    
  9. 
    
  10. def extract_token_from_url(url):
    
  11.     token_search = re.search(r"/reset/.*/(.+?)/", url)
    
  12.     if token_search:
    
  13.         return token_search[1]
    
  14. 
    
  15. 
    
  16. class PasswordResetConfirmClient(Client):
    
  17.     """
    
  18.     This client eases testing the password reset flow by emulating the
    
  19.     PasswordResetConfirmView's redirect and saving of the reset token in the
    
  20.     user's session. This request puts 'my-token' in the session and redirects
    
  21.     to '/reset/bla/set-password/':
    
  22. 
    
  23.     >>> client = PasswordResetConfirmClient()
    
  24.     >>> client.get('/reset/bla/my-token/')
    
  25.     """
    
  26. 
    
  27.     reset_url_token = PasswordResetConfirmView.reset_url_token
    
  28. 
    
  29.     def _get_password_reset_confirm_redirect_url(self, url):
    
  30.         token = extract_token_from_url(url)
    
  31.         if not token:
    
  32.             return url
    
  33.         # Add the token to the session
    
  34.         session = self.session
    
  35.         session[INTERNAL_RESET_SESSION_TOKEN] = token
    
  36.         session.save()
    
  37.         return url.replace(token, self.reset_url_token)
    
  38. 
    
  39.     def get(self, path, *args, **kwargs):
    
  40.         redirect_url = self._get_password_reset_confirm_redirect_url(path)
    
  41.         return super().get(redirect_url, *args, **kwargs)
    
  42. 
    
  43.     def post(self, path, *args, **kwargs):
    
  44.         redirect_url = self._get_password_reset_confirm_redirect_url(path)
    
  45.         return super().post(redirect_url, *args, **kwargs)