test_user_create_api.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. from django.contrib.auth import get_user_model
  2. from django.core import mail
  3. from django.test import override_settings
  4. from django.urls import reverse
  5. from misago.conf import settings
  6. from misago.users.models import Ban, Online
  7. from misago.users.testutils import UserTestCase
  8. UserModel = get_user_model()
  9. class UserCreateTests(UserTestCase):
  10. """tests for new user registration (POST to /api/users/)"""
  11. def setUp(self):
  12. super(UserCreateTests, self).setUp()
  13. self.api_link = '/api/users/'
  14. def test_empty_request(self):
  15. """empty request errors with code 400"""
  16. response = self.client.post(self.api_link)
  17. self.assertEqual(response.status_code, 400)
  18. self.assertEqual(response.json(), {
  19. 'email': ["This field is required."],
  20. 'password': ["This field is required."],
  21. 'username': ["This field is required."],
  22. })
  23. def test_invalid_data(self):
  24. """invalid request data errors with code 400"""
  25. response = self.client.post(
  26. self.api_link,
  27. 'false',
  28. content_type="application/json",
  29. )
  30. self.assertEqual(response.status_code, 400)
  31. self.assertEqual(response.json(), {
  32. 'non_field_errors': ["Invalid data. Expected a dictionary, but got bool."],
  33. })
  34. def test_authenticated_request(self):
  35. """authentiated user request errors with code 403"""
  36. self.login_user(self.get_authenticated_user())
  37. response = self.client.post(self.api_link)
  38. self.assertEqual(response.status_code, 403)
  39. self.assertEqual(response.json(), {
  40. 'detail': "This action is not available to signed in users.",
  41. })
  42. def test_registration_off_request(self):
  43. """registrations off request errors with code 403"""
  44. settings.override_setting('account_activation', 'closed')
  45. response = self.client.post(self.api_link)
  46. self.assertEqual(response.status_code, 403)
  47. self.assertEqual(response.json(), {
  48. 'detail': "New users registrations are currently closed.",
  49. })
  50. def test_registration_validates_ip_ban(self):
  51. """api validates ip ban"""
  52. Ban.objects.create(
  53. check_type=Ban.IP,
  54. banned_value='127.*',
  55. user_message="You can't register account like this.",
  56. )
  57. response = self.client.post(
  58. self.api_link,
  59. data={
  60. 'username': 'totallyNew',
  61. 'email': 'loremipsum@dolor.met',
  62. 'password': 'LoremP4ssword',
  63. },
  64. )
  65. self.assertEqual(response.status_code, 403)
  66. self.assertEqual(response.json(), {
  67. 'detail': {
  68. 'html': '<p>You can&#39;t register account like this.</p>',
  69. 'plain': "You can't register account like this."
  70. },
  71. 'expires_on': None,
  72. })
  73. def test_registration_validates_ip_registration_ban(self):
  74. """api validates ip registration-only ban"""
  75. Ban.objects.create(
  76. check_type=Ban.IP,
  77. banned_value='127.*',
  78. user_message="You can't register account like this.",
  79. registration_only=True,
  80. )
  81. response = self.client.post(
  82. self.api_link,
  83. data={
  84. 'username': 'totallyNew',
  85. 'email': 'loremipsum@dolor.met',
  86. 'password': 'LoremP4ssword',
  87. },
  88. )
  89. self.assertEqual(response.status_code, 403)
  90. self.assertEqual(
  91. response.json(), {
  92. 'detail': {
  93. 'html': '<p>You can&#39;t register account like this.</p>',
  94. 'plain': "You can't register account like this.",
  95. },
  96. 'expires_on': None,
  97. }
  98. )
  99. def test_registration_validates_username(self):
  100. """api validates usernames"""
  101. user = self.get_authenticated_user()
  102. response = self.client.post(
  103. self.api_link,
  104. data={
  105. 'username': user.username,
  106. 'email': 'loremipsum@dolor.met',
  107. 'password': 'LoremP4ssword',
  108. },
  109. )
  110. self.assertEqual(response.status_code, 400)
  111. self.assertEqual(response.json(), {
  112. 'username': ["This username is not available."],
  113. })
  114. def test_registration_validates_username_ban(self):
  115. """api validates username ban"""
  116. Ban.objects.create(
  117. banned_value='totally*',
  118. user_message="You can't register account like this.",
  119. )
  120. response = self.client.post(
  121. self.api_link,
  122. data={
  123. 'username': 'totallyNew',
  124. 'email': 'loremipsum@dolor.met',
  125. 'password': 'LoremP4ssword',
  126. },
  127. )
  128. self.assertEqual(response.status_code, 400)
  129. self.assertEqual(
  130. response.json(), {
  131. 'username': ["You can't register account like this."],
  132. }
  133. )
  134. def test_registration_validates_username_registration_ban(self):
  135. """api validates username registration-only ban"""
  136. Ban.objects.create(
  137. banned_value='totally*',
  138. user_message="You can't register account like this.",
  139. registration_only=True,
  140. )
  141. response = self.client.post(
  142. self.api_link,
  143. data={
  144. 'username': 'totallyNew',
  145. 'email': 'loremipsum@dolor.met',
  146. 'password': 'LoremP4ssword',
  147. },
  148. )
  149. self.assertEqual(response.status_code, 400)
  150. self.assertEqual(
  151. response.json(), {
  152. 'username': ["You can't register account like this."],
  153. }
  154. )
  155. def test_registration_validates_email(self):
  156. """api validates usernames"""
  157. user = self.get_authenticated_user()
  158. response = self.client.post(
  159. self.api_link,
  160. data={
  161. 'username': 'totallyNew',
  162. 'email': user.email,
  163. 'password': 'LoremP4ssword',
  164. },
  165. )
  166. self.assertEqual(response.status_code, 400)
  167. self.assertEqual(response.json(), {
  168. 'email': ["This e-mail address is not available."],
  169. })
  170. def test_registration_validates_email_ban(self):
  171. """api validates email ban"""
  172. Ban.objects.create(
  173. check_type=Ban.EMAIL,
  174. banned_value='lorem*',
  175. user_message="You can't register account like this.",
  176. )
  177. response = self.client.post(
  178. self.api_link,
  179. data={
  180. 'username': 'totallyNew',
  181. 'email': 'loremipsum@dolor.met',
  182. 'password': 'LoremP4ssword',
  183. },
  184. )
  185. self.assertEqual(response.status_code, 400)
  186. self.assertEqual(response.json(), {
  187. 'email': ["You can't register account like this."],
  188. })
  189. def test_registration_validates_email_registration_ban(self):
  190. """api validates email registration-only ban"""
  191. Ban.objects.create(
  192. check_type=Ban.EMAIL,
  193. banned_value='lorem*',
  194. user_message="You can't register account like this.",
  195. registration_only=True,
  196. )
  197. response = self.client.post(
  198. self.api_link,
  199. data={
  200. 'username': 'totallyNew',
  201. 'email': 'loremipsum@dolor.met',
  202. 'password': 'LoremP4ssword',
  203. },
  204. )
  205. self.assertEqual(response.status_code, 400)
  206. self.assertEqual(response.json(), {
  207. 'email': ["You can't register account like this."],
  208. })
  209. def test_registration_validates_password(self):
  210. """api uses django's validate_password to validate registrations"""
  211. response = self.client.post(
  212. self.api_link,
  213. data={
  214. 'username': 'Bob',
  215. 'email': 'l.o.r.e.m.i.p.s.u.m@gmail.com',
  216. 'password': '123',
  217. },
  218. )
  219. self.assertEqual(response.status_code, 400)
  220. self.assertEqual(response.json(), {
  221. 'password': [
  222. "This password is too short. It must contain at least 7 characters.",
  223. "This password is entirely numeric.",
  224. ],
  225. 'email': ["This email is not allowed."],
  226. })
  227. def test_registration_validates_password_similiarity(self):
  228. """api uses validate_password to validate registrations"""
  229. response = self.client.post(
  230. self.api_link,
  231. data={
  232. 'username': 'BobBoberson',
  233. 'email': 'l.o.r.e.m.i.p.s.u.m@gmail.com',
  234. 'password': 'BobBoberson',
  235. },
  236. )
  237. self.assertEqual(response.status_code, 400)
  238. self.assertEqual(response.json(), {
  239. 'password': ["The password is too similar to the username."],
  240. 'email': ["This email is not allowed."],
  241. })
  242. @override_settings(captcha_type='qa', qa_question='Test', qa_answers='Lorem\nIpsum')
  243. def test_registration_validates_captcha(self):
  244. """api validates captcha"""
  245. response = self.client.post(
  246. self.api_link,
  247. data={
  248. 'username': 'totallyNew',
  249. 'email': 'loremipsum@dolor.met',
  250. 'password': 'LoremP4ssword',
  251. 'captcha': 'dolor'
  252. },
  253. )
  254. self.assertEqual(response.status_code, 400)
  255. self.assertEqual(
  256. response.json(), {
  257. 'captcha': ['Entered answer is incorrect.'],
  258. }
  259. )
  260. # valid captcha
  261. response = self.client.post(
  262. self.api_link,
  263. data={
  264. 'username': 'totallyNew',
  265. 'email': 'loremipsum@dolor.met',
  266. 'password': 'LoremP4ssword',
  267. 'captcha': 'ipSUM'
  268. },
  269. )
  270. self.assertEqual(response.status_code, 200)
  271. def test_registration_calls_validate_new_registration(self):
  272. """api uses validate_new_registration to validate registrations"""
  273. response = self.client.post(
  274. self.api_link,
  275. data={
  276. 'username': 'Bob',
  277. 'email': 'l.o.r.e.m.i.p.s.u.m@gmail.com',
  278. 'password': 'pass1234',
  279. },
  280. )
  281. self.assertEqual(response.status_code, 400)
  282. self.assertEqual(response.json(), {
  283. 'email': ["This email is not allowed."]
  284. })
  285. def test_registration_creates_active_user(self):
  286. """api creates active and signed in user on POST"""
  287. settings.override_setting('account_activation', 'none')
  288. response = self.client.post(
  289. self.api_link,
  290. data={
  291. 'username': 'Bob',
  292. 'email': 'bob@bob.com',
  293. 'password': 'pass123',
  294. },
  295. )
  296. self.assertEqual(response.json(), {
  297. 'activation': None,
  298. 'username': 'Bob',
  299. 'email': 'bob@bob.com',
  300. })
  301. UserModel.objects.get_by_username('Bob')
  302. test_user = UserModel.objects.get_by_email('bob@bob.com')
  303. self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
  304. self.assertTrue(test_user.check_password('pass123'))
  305. response = self.client.get(reverse('misago:index'))
  306. self.assertContains(response, 'Bob')
  307. self.assertIn('Welcome', mail.outbox[0].subject)
  308. def test_registration_creates_inactive_user(self):
  309. """api creates inactive user on POST"""
  310. settings.override_setting('account_activation', 'user')
  311. response = self.client.post(
  312. self.api_link,
  313. data={
  314. 'username': 'Bob',
  315. 'email': 'bob@bob.com',
  316. 'password': 'pass123',
  317. },
  318. )
  319. self.assertEqual(response.json(), {
  320. 'activation': 'user',
  321. 'username': 'Bob',
  322. 'email': 'bob@bob.com',
  323. })
  324. UserModel.objects.get_by_username('Bob')
  325. UserModel.objects.get_by_email('bob@bob.com')
  326. self.assertIn('Welcome', mail.outbox[0].subject)
  327. def test_registration_creates_admin_activated_user(self):
  328. """api creates admin activated user on POST"""
  329. settings.override_setting('account_activation', 'admin')
  330. response = self.client.post(
  331. self.api_link,
  332. data={
  333. 'username': 'Bob',
  334. 'email': 'bob@bob.com',
  335. 'password': 'pass123',
  336. },
  337. )
  338. self.assertEqual(response.json(), {
  339. 'activation': 'admin',
  340. 'username': 'Bob',
  341. 'email': 'bob@bob.com',
  342. })
  343. UserModel.objects.get_by_username('Bob')
  344. UserModel.objects.get_by_email('bob@bob.com')
  345. self.assertIn('Welcome', mail.outbox[0].subject)
  346. def test_registration_creates_user_with_whitespace_password(self):
  347. """api creates user with spaces around password"""
  348. settings.override_setting('account_activation', 'none')
  349. response = self.client.post(
  350. self.api_link,
  351. data={
  352. 'username': 'Bob',
  353. 'email': 'bob@bob.com',
  354. 'password': ' pass123 ',
  355. },
  356. )
  357. self.assertEqual(response.json(), {
  358. 'activation': None,
  359. 'username': 'Bob',
  360. 'email': 'bob@bob.com',
  361. })
  362. UserModel.objects.get_by_username('Bob')
  363. test_user = UserModel.objects.get_by_email('bob@bob.com')
  364. self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
  365. self.assertTrue(test_user.check_password(' pass123 '))
  366. response = self.client.get(reverse('misago:index'))
  367. self.assertContains(response, 'Bob')
  368. self.assertIn('Welcome', mail.outbox[0].subject)