test_thread_postdelete_api.py 9.0 KB

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