test_users.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. import pytest
  2. from django.contrib.auth import get_user_model
  3. from django.core import mail
  4. from django.urls import reverse
  5. from ....acl.models import Role
  6. from ....admin.test import AdminTestCase
  7. from ....categories.models import Category
  8. from ....legal.models import Agreement
  9. from ....legal.utils import save_user_agreement_acceptance
  10. from ....test import assert_contains
  11. from ....threads.test import post_thread, reply_thread
  12. from ...datadownloads import request_user_data_download
  13. from ...models import Ban, DataDownload, Rank
  14. from ...test import create_test_user
  15. User = get_user_model()
  16. def test_link_is_registered_in_admin_nav(admin_client):
  17. response = admin_client.get(reverse("misago:admin:index"))
  18. assert_contains(response, reverse("misago:admin:users:accounts:index"))
  19. def test_list_renders_with_item(admin_client, users_admin_link, superuser):
  20. response = admin_client.get(users_admin_link)
  21. assert_contains(response, superuser.username)
  22. class UserAdminTests(AdminTestCase):
  23. AJAX_HEADER = {"HTTP_X_REQUESTED_WITH": "XMLHttpRequest"}
  24. def test_new_view(self):
  25. """new user view creates account"""
  26. response = self.client.get(reverse("misago:admin:users:accounts:new"))
  27. self.assertEqual(response.status_code, 200)
  28. default_rank = Rank.objects.get_default()
  29. authenticated_role = Role.objects.get(special_role="authenticated")
  30. response = self.client.post(
  31. reverse("misago:admin:users:accounts:new"),
  32. data={
  33. "username": "NewUsername",
  34. "rank": str(default_rank.pk),
  35. "roles": str(authenticated_role.pk),
  36. "email": "edited@example.com",
  37. "new_password": "pass123",
  38. "staff_level": "0",
  39. },
  40. )
  41. self.assertEqual(response.status_code, 302)
  42. User.objects.get_by_username("NewUsername")
  43. test_user = User.objects.get_by_email("edited@example.com")
  44. self.assertTrue(test_user.check_password("pass123"))
  45. def test_new_view_password_with_whitespaces(self):
  46. """new user view creates account with whitespaces password"""
  47. response = self.client.get(reverse("misago:admin:users:accounts:new"))
  48. self.assertEqual(response.status_code, 200)
  49. default_rank = Rank.objects.get_default()
  50. authenticated_role = Role.objects.get(special_role="authenticated")
  51. response = self.client.post(
  52. reverse("misago:admin:users:accounts:new"),
  53. data={
  54. "username": "NewUsername",
  55. "rank": str(default_rank.pk),
  56. "roles": str(authenticated_role.pk),
  57. "email": "edited@example.com",
  58. "new_password": " pass123 ",
  59. "staff_level": "0",
  60. },
  61. )
  62. self.assertEqual(response.status_code, 302)
  63. User.objects.get_by_username("NewUsername")
  64. test_user = User.objects.get_by_email("edited@example.com")
  65. self.assertTrue(test_user.check_password(" pass123 "))
  66. def test_edit_view(self):
  67. """edit user view changes account"""
  68. test_user = create_test_user("User", "user@example.com")
  69. test_link = reverse(
  70. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  71. )
  72. response = self.client.get(test_link)
  73. self.assertEqual(response.status_code, 200)
  74. response = self.client.post(
  75. test_link,
  76. data={
  77. "username": "NewUsername",
  78. "rank": str(test_user.rank_id),
  79. "roles": str(test_user.roles.all()[0].pk),
  80. "email": "edited@example.com",
  81. "new_password": "newpass123",
  82. "staff_level": "0",
  83. "signature": "Hello world!",
  84. "is_signature_locked": "1",
  85. "is_hiding_presence": "0",
  86. "limits_private_thread_invites_to": "0",
  87. "signature_lock_staff_message": "Staff message",
  88. "signature_lock_user_message": "User message",
  89. "subscribe_to_started_threads": "2",
  90. "subscribe_to_replied_threads": "2",
  91. },
  92. )
  93. self.assertEqual(response.status_code, 302)
  94. updated_user = User.objects.get(pk=test_user.pk)
  95. self.assertTrue(updated_user.check_password("newpass123"))
  96. self.assertEqual(updated_user.username, "NewUsername")
  97. self.assertEqual(updated_user.slug, "newusername")
  98. User.objects.get_by_username("NewUsername")
  99. User.objects.get_by_email("edited@example.com")
  100. def test_edit_dont_change_username(self):
  101. """
  102. If username wasn't changed, don't touch user's username, slug or history
  103. This is regression test for issue #640
  104. """
  105. test_user = create_test_user("User", "user@example.com")
  106. test_link = reverse(
  107. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  108. )
  109. response = self.client.get(test_link)
  110. self.assertEqual(response.status_code, 200)
  111. response = self.client.post(
  112. test_link,
  113. data={
  114. "username": "User",
  115. "rank": str(test_user.rank_id),
  116. "roles": str(test_user.roles.all()[0].pk),
  117. "email": "edited@example.com",
  118. "signature": "Hello world!",
  119. "is_signature_locked": "1",
  120. "is_hiding_presence": "0",
  121. "limits_private_thread_invites_to": "0",
  122. "signature_lock_staff_message": "Staff message",
  123. "signature_lock_user_message": "User message",
  124. "subscribe_to_started_threads": "2",
  125. "subscribe_to_replied_threads": "2",
  126. },
  127. )
  128. self.assertEqual(response.status_code, 302)
  129. updated_user = User.objects.get(pk=test_user.pk)
  130. self.assertEqual(updated_user.username, "User")
  131. self.assertEqual(updated_user.slug, "user")
  132. self.assertEqual(updated_user.namechanges.count(), 0)
  133. def test_edit_change_password_whitespaces(self):
  134. """edit user view changes account password to include whitespaces"""
  135. test_user = create_test_user("User", "user@example.com")
  136. test_link = reverse(
  137. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  138. )
  139. response = self.client.get(test_link)
  140. self.assertEqual(response.status_code, 200)
  141. response = self.client.post(
  142. test_link,
  143. data={
  144. "username": "NewUsername",
  145. "rank": str(test_user.rank_id),
  146. "roles": str(test_user.roles.all()[0].pk),
  147. "email": "edited@example.com",
  148. "new_password": " newpass123 ",
  149. "staff_level": "0",
  150. "signature": "Hello world!",
  151. "is_signature_locked": "1",
  152. "is_hiding_presence": "0",
  153. "limits_private_thread_invites_to": "0",
  154. "signature_lock_staff_message": "Staff message",
  155. "signature_lock_user_message": "User message",
  156. "subscribe_to_started_threads": "2",
  157. "subscribe_to_replied_threads": "2",
  158. },
  159. )
  160. self.assertEqual(response.status_code, 302)
  161. updated_user = User.objects.get(pk=test_user.pk)
  162. self.assertTrue(updated_user.check_password(" newpass123 "))
  163. self.assertEqual(updated_user.username, "NewUsername")
  164. self.assertEqual(updated_user.slug, "newusername")
  165. User.objects.get_by_username("NewUsername")
  166. User.objects.get_by_email("edited@example.com")
  167. def test_edit_make_admin(self):
  168. """edit user view allows super admin to make other user admin"""
  169. test_user = create_test_user("User", "user@example.com")
  170. test_link = reverse(
  171. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  172. )
  173. response = self.client.get(test_link)
  174. self.assertContains(response, 'id="id_is_staff_1"')
  175. self.assertContains(response, 'id="id_is_superuser_1"')
  176. response = self.client.post(
  177. test_link,
  178. data={
  179. "username": "NewUsername",
  180. "rank": str(test_user.rank_id),
  181. "roles": str(test_user.roles.all()[0].pk),
  182. "email": "edited@example.com",
  183. "is_staff": "1",
  184. "is_superuser": "0",
  185. "signature": "Hello world!",
  186. "is_signature_locked": "1",
  187. "is_hiding_presence": "0",
  188. "limits_private_thread_invites_to": "0",
  189. "signature_lock_staff_message": "Staff message",
  190. "signature_lock_user_message": "User message",
  191. "subscribe_to_started_threads": "2",
  192. "subscribe_to_replied_threads": "2",
  193. },
  194. )
  195. self.assertEqual(response.status_code, 302)
  196. updated_user = User.objects.get(pk=test_user.pk)
  197. self.assertTrue(updated_user.is_staff)
  198. self.assertFalse(updated_user.is_superuser)
  199. def test_edit_make_superadmin_admin(self):
  200. """edit user view allows super admin to make other user super admin"""
  201. test_user = create_test_user("User", "user@example.com")
  202. test_link = reverse(
  203. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  204. )
  205. response = self.client.get(test_link)
  206. self.assertContains(response, 'id="id_is_staff_1"')
  207. self.assertContains(response, 'id="id_is_superuser_1"')
  208. response = self.client.post(
  209. test_link,
  210. data={
  211. "username": "NewUsername",
  212. "rank": str(test_user.rank_id),
  213. "roles": str(test_user.roles.all()[0].pk),
  214. "email": "edited@example.com",
  215. "is_staff": "0",
  216. "is_superuser": "1",
  217. "signature": "Hello world!",
  218. "is_signature_locked": "1",
  219. "is_hiding_presence": "0",
  220. "limits_private_thread_invites_to": "0",
  221. "signature_lock_staff_message": "Staff message",
  222. "signature_lock_user_message": "User message",
  223. "subscribe_to_started_threads": "2",
  224. "subscribe_to_replied_threads": "2",
  225. },
  226. )
  227. self.assertEqual(response.status_code, 302)
  228. updated_user = User.objects.get(pk=test_user.pk)
  229. self.assertFalse(updated_user.is_staff)
  230. self.assertTrue(updated_user.is_superuser)
  231. def test_edit_denote_superadmin(self):
  232. """edit user view allows super admin to denote other super admin"""
  233. test_user = create_test_user(
  234. "User", "user@example.com", is_staff=True, is_superuser=True
  235. )
  236. test_link = reverse(
  237. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  238. )
  239. response = self.client.get(test_link)
  240. self.assertContains(response, 'id="id_is_staff_1"')
  241. self.assertContains(response, 'id="id_is_superuser_1"')
  242. response = self.client.post(
  243. test_link,
  244. data={
  245. "username": "NewUsername",
  246. "rank": str(test_user.rank_id),
  247. "roles": str(test_user.roles.all()[0].pk),
  248. "email": "edited@example.com",
  249. "is_staff": "0",
  250. "is_superuser": "0",
  251. "signature": "Hello world!",
  252. "is_signature_locked": "1",
  253. "is_hiding_presence": "0",
  254. "limits_private_thread_invites_to": "0",
  255. "signature_lock_staff_message": "Staff message",
  256. "signature_lock_user_message": "User message",
  257. "subscribe_to_started_threads": "2",
  258. "subscribe_to_replied_threads": "2",
  259. },
  260. )
  261. self.assertEqual(response.status_code, 302)
  262. updated_user = User.objects.get(pk=test_user.pk)
  263. self.assertFalse(updated_user.is_staff)
  264. self.assertFalse(updated_user.is_superuser)
  265. def test_edit_cant_make_admin(self):
  266. """edit user view forbids admins from making other admins"""
  267. self.user.is_superuser = False
  268. self.user.save()
  269. test_user = create_test_user("User", "user@example.com")
  270. test_link = reverse(
  271. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  272. )
  273. response = self.client.get(test_link)
  274. self.assertNotContains(response, 'id="id_is_staff_1"')
  275. self.assertNotContains(response, 'id="id_is_superuser_1"')
  276. response = self.client.post(
  277. test_link,
  278. data={
  279. "username": "NewUsername",
  280. "rank": str(test_user.rank_id),
  281. "roles": str(test_user.roles.all()[0].pk),
  282. "email": "edited@example.com",
  283. "is_staff": "1",
  284. "is_superuser": "1",
  285. "signature": "Hello world!",
  286. "is_signature_locked": "1",
  287. "is_hiding_presence": "0",
  288. "limits_private_thread_invites_to": "0",
  289. "signature_lock_staff_message": "Staff message",
  290. "signature_lock_user_message": "User message",
  291. "subscribe_to_started_threads": "2",
  292. "subscribe_to_replied_threads": "2",
  293. },
  294. )
  295. self.assertEqual(response.status_code, 302)
  296. updated_user = User.objects.get(pk=test_user.pk)
  297. self.assertFalse(updated_user.is_staff)
  298. self.assertFalse(updated_user.is_superuser)
  299. def test_edit_disable_user(self):
  300. """edit user view allows admin to disable non admin"""
  301. self.user.is_superuser = False
  302. self.user.save()
  303. test_user = create_test_user("User", "user@example.com")
  304. test_link = reverse(
  305. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  306. )
  307. response = self.client.get(test_link)
  308. self.assertContains(response, 'id="id_is_active_1"')
  309. self.assertContains(response, 'id="id_is_active_staff_message"')
  310. response = self.client.post(
  311. test_link,
  312. data={
  313. "username": "NewUsername",
  314. "rank": str(test_user.rank_id),
  315. "roles": str(test_user.roles.all()[0].pk),
  316. "email": "edited@example.com",
  317. "is_staff": "0",
  318. "is_superuser": "0",
  319. "signature": "Hello world!",
  320. "is_signature_locked": "1",
  321. "is_hiding_presence": "0",
  322. "limits_private_thread_invites_to": "0",
  323. "signature_lock_staff_message": "Staff message",
  324. "signature_lock_user_message": "User message",
  325. "subscribe_to_started_threads": "2",
  326. "subscribe_to_replied_threads": "2",
  327. "is_active": "0",
  328. "is_active_staff_message": "Disabled in test!",
  329. },
  330. )
  331. self.assertEqual(response.status_code, 302)
  332. updated_user = User.objects.get(pk=test_user.pk)
  333. self.assertFalse(updated_user.is_active)
  334. self.assertEqual(updated_user.is_active_staff_message, "Disabled in test!")
  335. def test_edit_superuser_disable_admin(self):
  336. """edit user view allows admin to disable non admin"""
  337. self.user.is_superuser = True
  338. self.user.save()
  339. test_user = create_test_user("User", "user@example.com")
  340. test_user.is_staff = True
  341. test_user.save()
  342. test_link = reverse(
  343. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  344. )
  345. response = self.client.get(test_link)
  346. self.assertContains(response, 'id="id_is_active_1"')
  347. self.assertContains(response, 'id="id_is_active_staff_message"')
  348. response = self.client.post(
  349. test_link,
  350. data={
  351. "username": "NewUsername",
  352. "rank": str(test_user.rank_id),
  353. "roles": str(test_user.roles.all()[0].pk),
  354. "email": "edited@example.com",
  355. "is_staff": "1",
  356. "is_superuser": "0",
  357. "signature": "Hello world!",
  358. "is_signature_locked": "1",
  359. "is_hiding_presence": "0",
  360. "limits_private_thread_invites_to": "0",
  361. "signature_lock_staff_message": "Staff message",
  362. "signature_lock_user_message": "User message",
  363. "subscribe_to_started_threads": "2",
  364. "subscribe_to_replied_threads": "2",
  365. "is_active": "0",
  366. "is_active_staff_message": "Disabled in test!",
  367. },
  368. )
  369. self.assertEqual(response.status_code, 302)
  370. updated_user = User.objects.get(pk=test_user.pk)
  371. self.assertFalse(updated_user.is_active)
  372. self.assertEqual(updated_user.is_active_staff_message, "Disabled in test!")
  373. def test_edit_admin_cant_disable_admin(self):
  374. """edit user view disallows admin to disable admin"""
  375. self.user.is_superuser = False
  376. self.user.save()
  377. test_user = create_test_user("User", "user@example.com")
  378. test_user.is_staff = True
  379. test_user.save()
  380. test_link = reverse(
  381. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  382. )
  383. response = self.client.get(test_link)
  384. self.assertNotContains(response, 'id="id_is_active_1"')
  385. self.assertNotContains(response, 'id="id_is_active_staff_message"')
  386. response = self.client.post(
  387. test_link,
  388. data={
  389. "username": "NewUsername",
  390. "rank": str(test_user.rank_id),
  391. "roles": str(test_user.roles.all()[0].pk),
  392. "email": "edited@example.com",
  393. "is_staff": "1",
  394. "is_superuser": "0",
  395. "signature": "Hello world!",
  396. "is_signature_locked": "1",
  397. "is_hiding_presence": "0",
  398. "limits_private_thread_invites_to": "0",
  399. "signature_lock_staff_message": "Staff message",
  400. "signature_lock_user_message": "User message",
  401. "subscribe_to_started_threads": "2",
  402. "subscribe_to_replied_threads": "2",
  403. "is_active": "0",
  404. "is_active_staff_message": "Disabled in test!",
  405. },
  406. )
  407. self.assertEqual(response.status_code, 302)
  408. updated_user = User.objects.get(pk=test_user.pk)
  409. self.assertTrue(updated_user.is_active)
  410. self.assertFalse(updated_user.is_active_staff_message)
  411. def test_edit_is_deleting_account_cant_reactivate(self):
  412. """users deleting own accounts can't be reactivated"""
  413. test_user = create_test_user("User", "user@example.com")
  414. test_user.mark_for_delete()
  415. test_link = reverse(
  416. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  417. )
  418. response = self.client.get(test_link)
  419. self.assertNotContains(response, 'id="id_is_active_1"')
  420. self.assertNotContains(response, 'id="id_is_active_staff_message"')
  421. response = self.client.post(
  422. test_link,
  423. data={
  424. "username": "NewUsername",
  425. "rank": str(test_user.rank_id),
  426. "roles": str(test_user.roles.all()[0].pk),
  427. "email": "edited@example.com",
  428. "is_staff": "1",
  429. "is_superuser": "0",
  430. "signature": "Hello world!",
  431. "is_signature_locked": "1",
  432. "is_hiding_presence": "0",
  433. "limits_private_thread_invites_to": "0",
  434. "signature_lock_staff_message": "Staff message",
  435. "signature_lock_user_message": "User message",
  436. "subscribe_to_started_threads": "2",
  437. "subscribe_to_replied_threads": "2",
  438. "is_active": "1",
  439. },
  440. )
  441. self.assertEqual(response.status_code, 302)
  442. updated_user = User.objects.get(pk=test_user.pk)
  443. self.assertFalse(updated_user.is_active)
  444. self.assertTrue(updated_user.is_deleting_account)
  445. def test_edit_unusable_password(self):
  446. """admin edit form handles unusable passwords and lets setting new password"""
  447. test_user = create_test_user("User", "user@example.com")
  448. self.assertFalse(test_user.has_usable_password())
  449. test_link = reverse(
  450. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  451. )
  452. response = self.client.get(test_link)
  453. self.assertContains(response, "alert-has-unusable-password")
  454. response = self.client.post(
  455. test_link,
  456. data={
  457. "username": "NewUsername",
  458. "rank": str(test_user.rank_id),
  459. "roles": str(test_user.roles.all()[0].pk),
  460. "email": "edited@example.com",
  461. "new_password": "pass123",
  462. "is_staff": "1",
  463. "is_superuser": "0",
  464. "signature": "Hello world!",
  465. "is_signature_locked": "1",
  466. "is_hiding_presence": "0",
  467. "limits_private_thread_invites_to": "0",
  468. "signature_lock_staff_message": "Staff message",
  469. "signature_lock_user_message": "User message",
  470. "subscribe_to_started_threads": "2",
  471. "subscribe_to_replied_threads": "2",
  472. "is_active": "1",
  473. },
  474. )
  475. self.assertEqual(response.status_code, 302)
  476. updated_user = User.objects.get(pk=test_user.pk)
  477. self.assertTrue(updated_user.has_usable_password())
  478. def test_edit_keep_unusable_password(self):
  479. """
  480. admin edit form handles unusable passwords and lets admin leave them unchanged
  481. """
  482. test_user = create_test_user("User", "user@example.com")
  483. self.assertFalse(test_user.has_usable_password())
  484. test_link = reverse(
  485. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  486. )
  487. response = self.client.get(test_link)
  488. self.assertContains(response, "alert-has-unusable-password")
  489. response = self.client.post(
  490. test_link,
  491. data={
  492. "username": "NewUsername",
  493. "rank": str(test_user.rank_id),
  494. "roles": str(test_user.roles.all()[0].pk),
  495. "email": "edited@example.com",
  496. "is_staff": "1",
  497. "is_superuser": "0",
  498. "signature": "Hello world!",
  499. "is_signature_locked": "1",
  500. "is_hiding_presence": "0",
  501. "limits_private_thread_invites_to": "0",
  502. "signature_lock_staff_message": "Staff message",
  503. "signature_lock_user_message": "User message",
  504. "subscribe_to_started_threads": "2",
  505. "subscribe_to_replied_threads": "2",
  506. "is_active": "1",
  507. },
  508. )
  509. self.assertEqual(response.status_code, 302)
  510. updated_user = User.objects.get(pk=test_user.pk)
  511. self.assertFalse(updated_user.has_usable_password())
  512. def test_edit_agreements_list(self):
  513. """edit view displays list of user's agreements"""
  514. test_user = create_test_user("User", "user@example.com")
  515. test_link = reverse(
  516. "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
  517. )
  518. agreement = Agreement.objects.create(
  519. type=Agreement.TYPE_TOS,
  520. title="Test agreement!",
  521. text="Lorem ipsum!",
  522. is_active=True,
  523. )
  524. response = self.client.get(test_link)
  525. self.assertEqual(response.status_code, 200)
  526. self.assertNotContains(response, agreement.title)
  527. save_user_agreement_acceptance(test_user, agreement, commit=True)
  528. response = self.client.get(test_link)
  529. self.assertEqual(response.status_code, 200)
  530. self.assertContains(response, agreement.title)