test_useradmin_views.py 23 KB

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