test_user_changepassword_api.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. from django.core import mail
  2. from django.urls import reverse
  3. from ...conf.test import override_dynamic_settings
  4. from ..test import AuthenticatedUserTestCase
  5. class UserChangePasswordTests(AuthenticatedUserTestCase):
  6. """tests for user change password RPC (/api/users/1/change-password/)"""
  7. def setUp(self):
  8. super().setUp()
  9. self.link = "/api/users/%s/change-password/" % self.user.pk
  10. def test_unsupported_methods(self):
  11. """api isn't supporting GET"""
  12. response = self.client.get(self.link)
  13. self.assertEqual(response.status_code, 405)
  14. def test_empty_input(self):
  15. """api errors correctly for empty input"""
  16. response = self.client.post(self.link, data={})
  17. self.assertEqual(response.status_code, 400)
  18. self.assertEqual(
  19. response.json(),
  20. {
  21. "new_password": ["This field is required."],
  22. "password": ["This field is required."],
  23. },
  24. )
  25. def test_invalid_password(self):
  26. """api errors correctly for invalid password"""
  27. response = self.client.post(
  28. self.link, data={"new_password": "N3wP@55w0rd", "password": "Lor3mIpsum"}
  29. )
  30. self.assertEqual(response.status_code, 400)
  31. self.assertEqual(
  32. response.json(), {"password": ["Entered password is invalid."]}
  33. )
  34. def test_blank_input(self):
  35. """api errors correctly for blank input"""
  36. response = self.client.post(
  37. self.link, data={"new_password": "", "password": self.USER_PASSWORD}
  38. )
  39. self.assertEqual(response.status_code, 400)
  40. self.assertEqual(
  41. response.json(), {"new_password": ["This field may not be blank."]}
  42. )
  43. def test_short_new_pasword(self):
  44. """api errors correctly for short new password"""
  45. response = self.client.post(
  46. self.link, data={"new_password": "n", "password": self.USER_PASSWORD}
  47. )
  48. self.assertEqual(response.status_code, 400)
  49. self.assertEqual(
  50. response.json(),
  51. {
  52. "new_password": [
  53. "This password is too short. It must contain at least 7 characters."
  54. ]
  55. },
  56. )
  57. @override_dynamic_settings(enable_sso=True)
  58. def test_password_change_fails_when_sso_is_enabled(self):
  59. response = self.client.post(
  60. self.link,
  61. data={"new_password": "N3wP@55w0rd", "password": self.USER_PASSWORD},
  62. )
  63. self.assertEqual(response.status_code, 403)
  64. @override_dynamic_settings(forum_address="http://test.com/")
  65. def test_change_password(self):
  66. """api allows users to change their passwords"""
  67. new_password = "N3wP@55w0rd"
  68. response = self.client.post(
  69. self.link,
  70. data={"new_password": new_password, "password": self.USER_PASSWORD},
  71. )
  72. self.assertEqual(response.status_code, 200)
  73. self.assertIn("Confirm password change", mail.outbox[0].subject)
  74. for line in [l.strip() for l in mail.outbox[0].body.splitlines()]:
  75. if line.startswith("http://"):
  76. token = line.rstrip("/").split("/")[-1]
  77. break
  78. else:
  79. self.fail("E-mail sent didn't contain confirmation url")
  80. response = self.client.get(
  81. reverse("misago:options-confirm-password-change", kwargs={"token": token})
  82. )
  83. self.assertEqual(response.status_code, 200)
  84. self.reload_user()
  85. self.assertTrue(self.user.check_password(new_password))
  86. @override_dynamic_settings(forum_address="http://test.com/")
  87. def test_change_password_with_whitespaces(self):
  88. """api handles users with whitespaces around their passwords"""
  89. old_password = " old password "
  90. new_password = " N3wP@55w0rd "
  91. self.user.set_password(old_password)
  92. self.user.save()
  93. self.login_user(self.user)
  94. response = self.client.post(
  95. self.link, data={"new_password": new_password, "password": old_password}
  96. )
  97. self.assertEqual(response.status_code, 200)
  98. self.assertIn("Confirm password change", mail.outbox[0].subject)
  99. for line in [l.strip() for l in mail.outbox[0].body.splitlines()]:
  100. if line.startswith("http://"):
  101. token = line.rstrip("/").split("/")[-1]
  102. break
  103. else:
  104. self.fail("E-mail sent didn't contain confirmation url")
  105. response = self.client.get(
  106. reverse("misago:options-confirm-password-change", kwargs={"token": token})
  107. )
  108. self.assertEqual(response.status_code, 200)
  109. self.reload_user()
  110. self.assertTrue(self.user.check_password(new_password))