test_thread_postdelete_api.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. from datetime import timedelta
  2. from django.urls import reverse
  3. from django.utils import timezone
  4. from misago.threads import test
  5. from misago.threads.models import Post, Thread
  6. from misago.threads.test import patch_category_acl
  7. from .test_threads_api import ThreadsApiTestCase
  8. class PostDeleteApiTests(ThreadsApiTestCase):
  9. def setUp(self):
  10. super().setUp()
  11. self.post = test.reply_thread(self.thread, poster=self.user)
  12. self.api_link = reverse(
  13. "misago:api:thread-post-detail",
  14. kwargs={"thread_pk": self.thread.pk, "pk": self.post.pk},
  15. )
  16. def test_delete_anonymous(self):
  17. """api validates if deleting user is authenticated"""
  18. self.logout_user()
  19. response = self.client.delete(self.api_link)
  20. self.assertEqual(response.status_code, 403)
  21. self.assertEqual(
  22. response.json(), {"detail": "This action is not available to guests."}
  23. )
  24. @patch_category_acl({"can_hide_posts": 1, "can_hide_own_posts": 1})
  25. def test_no_permission(self):
  26. """api validates permission to delete post"""
  27. response = self.client.delete(self.api_link)
  28. self.assertEqual(response.status_code, 403)
  29. self.assertEqual(
  30. response.json(), {"detail": "You can't delete posts in this category."}
  31. )
  32. @patch_category_acl(
  33. {"can_hide_posts": 1, "can_hide_own_posts": 2, "post_edit_time": 0}
  34. )
  35. def test_delete_other_user_post_no_permission(self):
  36. """api valdiates if user can delete other users posts"""
  37. self.post.poster = None
  38. self.post.save()
  39. response = self.client.delete(self.api_link)
  40. self.assertEqual(response.status_code, 403)
  41. self.assertEqual(
  42. response.json(),
  43. {"detail": "You can't delete other users posts in this category."},
  44. )
  45. @patch_category_acl(
  46. {"can_hide_posts": 1, "can_hide_own_posts": 2, "post_edit_time": 0}
  47. )
  48. def test_delete_protected_post_no_permission(self):
  49. """api validates if user can delete protected post"""
  50. self.post.is_protected = True
  51. self.post.save()
  52. response = self.client.delete(self.api_link)
  53. self.assertEqual(response.status_code, 403)
  54. self.assertEqual(
  55. response.json(), {"detail": "This post is protected. You can't delete it."}
  56. )
  57. @patch_category_acl(
  58. {"can_hide_posts": 1, "can_hide_own_posts": 2, "post_edit_time": 1}
  59. )
  60. def test_delete_protected_post_after_edit_time(self):
  61. """api validates if user can delete delete post after edit time"""
  62. self.post.posted_on = timezone.now() - timedelta(minutes=10)
  63. self.post.save()
  64. response = self.client.delete(self.api_link)
  65. self.assertEqual(response.status_code, 403)
  66. self.assertEqual(
  67. response.json(),
  68. {"detail": "You can't delete posts that are older than 1 minute."},
  69. )
  70. @patch_category_acl(
  71. {
  72. "can_hide_posts": 0,
  73. "can_hide_own_posts": 2,
  74. "post_edit_time": 0,
  75. "can_close_threads": False,
  76. }
  77. )
  78. def test_delete_post_closed_thread_no_permission(self):
  79. """api valdiates if user can delete posts in closed threads"""
  80. self.thread.is_closed = True
  81. self.thread.save()
  82. response = self.client.delete(self.api_link)
  83. self.assertEqual(response.status_code, 403)
  84. self.assertEqual(
  85. response.json(),
  86. {"detail": "This thread is closed. You can't delete posts in it."},
  87. )
  88. @patch_category_acl(
  89. {
  90. "can_hide_posts": 0,
  91. "can_hide_own_posts": 2,
  92. "post_edit_time": 0,
  93. "can_close_threads": False,
  94. }
  95. )
  96. def test_delete_post_closed_category_no_permission(self):
  97. """api valdiates if user can delete posts in closed categories"""
  98. self.category.is_closed = True
  99. self.category.save()
  100. response = self.client.delete(self.api_link)
  101. self.assertEqual(response.status_code, 403)
  102. self.assertEqual(
  103. response.json(),
  104. {"detail": "This category is closed. You can't delete posts in it."},
  105. )
  106. @patch_category_acl({"can_hide_posts": 2, "can_hide_own_posts": 2})
  107. def test_delete_first_post(self):
  108. """api disallows first post deletion"""
  109. api_link = reverse(
  110. "misago:api:thread-post-detail",
  111. kwargs={"thread_pk": self.thread.pk, "pk": self.thread.first_post_id},
  112. )
  113. response = self.client.delete(api_link)
  114. self.assertEqual(response.status_code, 403)
  115. self.assertEqual(
  116. response.json(), {"detail": "You can't delete thread's first post."}
  117. )
  118. @patch_category_acl({"can_hide_posts": 2, "can_hide_own_posts": 2})
  119. def test_delete_best_answer(self):
  120. """api disallows best answer deletion"""
  121. self.thread.set_best_answer(self.user, self.post)
  122. self.thread.save()
  123. response = self.client.delete(self.api_link)
  124. self.assertEqual(response.status_code, 403)
  125. self.assertEqual(
  126. response.json(),
  127. {"detail": "You can't delete this post because its marked as best answer."},
  128. )
  129. @patch_category_acl(
  130. {"can_hide_posts": 0, "can_hide_own_posts": 2, "post_edit_time": 0}
  131. )
  132. def test_delete_owned_post(self):
  133. """api deletes owned thread post"""
  134. response = self.client.delete(self.api_link)
  135. self.assertEqual(response.status_code, 200)
  136. self.thread = Thread.objects.get(pk=self.thread.pk)
  137. self.assertNotEqual(self.thread.last_post_id, self.post.pk)
  138. with self.assertRaises(Post.DoesNotExist):
  139. self.thread.post_set.get(pk=self.post.pk)
  140. @patch_category_acl({"can_hide_posts": 2, "can_hide_own_posts": 0})
  141. def test_delete_post(self):
  142. """api deletes thread post"""
  143. response = self.client.delete(self.api_link)
  144. self.assertEqual(response.status_code, 200)
  145. self.thread = Thread.objects.get(pk=self.thread.pk)
  146. self.assertNotEqual(self.thread.last_post_id, self.post.pk)
  147. with self.assertRaises(Post.DoesNotExist):
  148. self.thread.post_set.get(pk=self.post.pk)
  149. class EventDeleteApiTests(ThreadsApiTestCase):
  150. def setUp(self):
  151. super().setUp()
  152. self.event = test.reply_thread(
  153. self.thread, poster=self.user, is_event=True
  154. )
  155. self.api_link = reverse(
  156. "misago:api:thread-post-detail",
  157. kwargs={"thread_pk": self.thread.pk, "pk": self.event.pk},
  158. )
  159. def test_delete_anonymous(self):
  160. """api validates if deleting user is authenticated"""
  161. self.logout_user()
  162. response = self.client.delete(self.api_link)
  163. self.assertEqual(response.status_code, 403)
  164. self.assertEqual(
  165. response.json(), {"detail": "This action is not available to guests."}
  166. )
  167. @patch_category_acl(
  168. {"can_hide_posts": 2, "can_hide_own_posts": 0, "can_hide_events": 0}
  169. )
  170. def test_no_permission(self):
  171. """api validates permission to delete event"""
  172. response = self.client.delete(self.api_link)
  173. self.assertEqual(response.status_code, 403)
  174. self.assertEqual(
  175. response.json(), {"detail": "You can't delete events in this category."}
  176. )
  177. @patch_category_acl(
  178. {
  179. "can_hide_posts": 2,
  180. "can_hide_own_posts": 0,
  181. "can_hide_events": 2,
  182. "can_close_threads": False,
  183. }
  184. )
  185. def test_delete_event_closed_thread_no_permission(self):
  186. """api valdiates if user can delete events in closed threads"""
  187. self.thread.is_closed = True
  188. self.thread.save()
  189. response = self.client.delete(self.api_link)
  190. self.assertEqual(response.status_code, 403)
  191. self.assertEqual(
  192. response.json(),
  193. {"detail": "This thread is closed. You can't delete events in it."},
  194. )
  195. @patch_category_acl(
  196. {"can_hide_posts": 2, "can_hide_events": 2, "can_close_threads": False}
  197. )
  198. def test_delete_event_closed_category_no_permission(self):
  199. """api valdiates if user can delete events in closed categories"""
  200. self.category.is_closed = True
  201. self.category.save()
  202. response = self.client.delete(self.api_link)
  203. self.assertEqual(response.status_code, 403)
  204. self.assertEqual(
  205. response.json(),
  206. {"detail": "This category is closed. You can't delete events in it."},
  207. )
  208. @patch_category_acl({"can_hide_posts": 0, "can_hide_events": 2})
  209. def test_delete_event(self):
  210. """api differs posts from events"""
  211. response = self.client.delete(self.api_link)
  212. self.assertEqual(response.status_code, 200)
  213. self.thread = Thread.objects.get(pk=self.thread.pk)
  214. self.assertNotEqual(self.thread.last_post_id, self.event.pk)
  215. with self.assertRaises(Post.DoesNotExist):
  216. self.thread.post_set.get(pk=self.event.pk)