test_threads_api.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. from misago.acl.testutils import override_acl
  2. from misago.categories.models import THREADS_ROOT_NAME, Category
  3. from misago.users.testutils import AuthenticatedUserTestCase
  4. from .. import testutils
  5. from ..models import Thread
  6. from ..threadtypes import trees_map
  7. class ThreadsApiTestCase(AuthenticatedUserTestCase):
  8. def setUp(self):
  9. super(ThreadsApiTestCase, self).setUp()
  10. threads_tree_id = trees_map.get_tree_id_for_root(THREADS_ROOT_NAME)
  11. self.root = Category.objects.get(tree_id=threads_tree_id, level=0)
  12. self.category = Category.objects.get(slug='first-category')
  13. self.thread = testutils.post_thread(category=self.category)
  14. self.api_link = self.thread.get_api_url()
  15. def override_acl(self, acl=None):
  16. final_acl = self.user.acl['categories'][self.category.pk]
  17. final_acl.update({
  18. 'can_see': 1,
  19. 'can_browse': 1,
  20. 'can_see_all_threads': 1,
  21. 'can_see_own_threads': 0,
  22. 'can_hide_threads': 0,
  23. 'can_approve_content': 0,
  24. 'can_edit_posts': 0,
  25. 'can_hide_posts': 0,
  26. 'can_hide_own_posts': 0,
  27. 'can_merge_threads': 0
  28. })
  29. if acl:
  30. final_acl.update(acl)
  31. override_acl(self.user, {
  32. 'categories': {
  33. self.category.pk: final_acl
  34. }
  35. })
  36. def get_thread_json(self):
  37. response = self.client.get(self.thread.get_api_url())
  38. self.assertEqual(response.status_code, 200)
  39. return response.json()
  40. class ThreadRetrieveApiTests(ThreadsApiTestCase):
  41. def setUp(self):
  42. super(ThreadRetrieveApiTests, self).setUp()
  43. self.tested_links = [
  44. self.api_link,
  45. '%sposts/' % self.api_link,
  46. '%sposts/?page=1' % self.api_link,
  47. ]
  48. def test_api_returns_thread(self):
  49. """api endpoint has no showstoppers"""
  50. for link in self.tested_links:
  51. self.override_acl()
  52. response = self.client.get(link)
  53. self.assertEqual(response.status_code, 200)
  54. response_json = response.json()
  55. self.assertEqual(response_json['id'], self.thread.pk)
  56. self.assertEqual(response_json['title'], self.thread.title)
  57. if 'posts' in link:
  58. self.assertIn('post_set', response_json)
  59. def test_api_shows_owned_thread(self):
  60. """api handles "owned threads only"""
  61. for link in self.tested_links:
  62. self.override_acl({
  63. 'can_see_all_threads': 0
  64. })
  65. response = self.client.get(link)
  66. self.assertEqual(response.status_code, 404)
  67. self.thread.starter = self.user
  68. self.thread.save()
  69. for link in self.tested_links:
  70. self.override_acl({
  71. 'can_see_all_threads': 0
  72. })
  73. response = self.client.get(link)
  74. self.assertEqual(response.status_code, 200)
  75. def test_api_validates_category_permissions(self):
  76. """api endpoint validates category visiblity"""
  77. for link in self.tested_links:
  78. self.override_acl({
  79. 'can_see': 0
  80. })
  81. response = self.client.get(link)
  82. self.assertEqual(response.status_code, 404)
  83. for link in self.tested_links:
  84. self.override_acl({
  85. 'can_browse': 0
  86. })
  87. response = self.client.get(link)
  88. self.assertEqual(response.status_code, 404)
  89. def test_api_validates_posts_visibility(self):
  90. """api endpoint validates posts visiblity"""
  91. self.override_acl({
  92. 'can_hide_posts': 0
  93. })
  94. hidden_post = testutils.reply_thread(self.thread, is_hidden=True, message="I'am hidden test message!")
  95. response = self.client.get(self.tested_links[1])
  96. self.assertNotContains(response, hidden_post.parsed) # post's body is hidden
  97. # add permission to see hidden posts
  98. self.override_acl({
  99. 'can_hide_posts': 1
  100. })
  101. response = self.client.get(self.tested_links[1])
  102. self.assertContains(response, hidden_post.parsed) # hidden post's body is visible with permission
  103. self.override_acl({
  104. 'can_approve_content': 0
  105. })
  106. # unapproved posts shouldn't show at all
  107. unapproved_post = testutils.reply_thread(self.thread, is_unapproved=True)
  108. response = self.client.get(self.tested_links[1])
  109. self.assertNotContains(response, unapproved_post.get_absolute_url())
  110. # add permission to see unapproved posts
  111. self.override_acl({
  112. 'can_approve_content': 1
  113. })
  114. response = self.client.get(self.tested_links[1])
  115. self.assertContains(response, unapproved_post.get_absolute_url())
  116. class ThreadDeleteApiTests(ThreadsApiTestCase):
  117. def test_delete_thread_no_permission(self):
  118. """DELETE to API link with no permission to delete fails"""
  119. self.override_acl({
  120. 'can_hide_threads': 1
  121. })
  122. response = self.client.delete(self.api_link)
  123. self.assertEqual(response.status_code, 403)
  124. self.override_acl({
  125. 'can_hide_threads': 0
  126. })
  127. response_json = response.json()
  128. self.assertEqual(response_json['detail'],
  129. "You don't have permission to delete this thread.")
  130. response = self.client.delete(self.api_link)
  131. self.assertEqual(response.status_code, 403)
  132. def test_delete_thread(self):
  133. """DELETE to API link with permission deletes thread"""
  134. self.override_acl({
  135. 'can_hide_threads': 2
  136. })
  137. response = self.client.delete(self.api_link)
  138. self.assertEqual(response.status_code, 200)
  139. with self.assertRaises(Thread.DoesNotExist):
  140. Thread.objects.get(pk=self.thread.pk)