delete.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. from django.core.urlresolvers import reverse
  2. from django.shortcuts import redirect
  3. from django.utils import timezone
  4. from django.utils.translation import ugettext as _
  5. from misago.acl.exceptions import ACLError403, ACLError404
  6. from misago.apps.errors import error403, error404
  7. from misago.messages import Message
  8. from misago.models import Forum, Thread, Post, Checkpoint
  9. from misago.apps.threadtype.base import ViewBase
  10. class DeleteHideBaseView(ViewBase):
  11. def set_context(self):
  12. pass
  13. def _set_context(self):
  14. self.thread = Thread.objects.get(pk=self.kwargs.get('thread'))
  15. self.forum = self.thread.forum
  16. self.proxy = Forum.objects.parents_aware_forum(self.forum)
  17. if self.forum.level:
  18. self.parents = Forum.objects.forum_parents(self.forum.pk)
  19. self.check_forum_type()
  20. self.request.acl.forums.allow_forum_view(self.forum)
  21. self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
  22. if self.kwargs.get('post'):
  23. self.post = self.thread.post_set.get(id=self.kwargs.get('post'))
  24. self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
  25. if self.kwargs.get('checkpoint'):
  26. self.checkpoint = self.post.checkpoint_set.get(id=self.kwargs.get('checkpoint'))
  27. self.request.acl.threads.allow_checkpoint_view(self.forum, self.checkpoint)
  28. self.set_context()
  29. def __call__(self, request, **kwargs):
  30. self.request = request
  31. self.kwargs = kwargs
  32. self.parents = []
  33. try:
  34. self._type_available()
  35. self._set_context()
  36. self._check_permissions()
  37. self.delete()
  38. self.message()
  39. return self.response()
  40. except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist, Checkpoint.DoesNotExist):
  41. return error404(request)
  42. except ACLError403 as e:
  43. return error403(request, unicode(e))
  44. except ACLError404 as e:
  45. return error404(request, unicode(e))
  46. class DeleteThreadBaseView(DeleteHideBaseView):
  47. def set_context(self):
  48. self.request.acl.threads.allow_delete_thread(self.request.user, self.proxy,
  49. self.thread, self.thread.start_post, True)
  50. def delete(self):
  51. self.thread.delete()
  52. self.forum.sync()
  53. self.forum.save(force_update=True)
  54. def message(self):
  55. self.request.messages.set_flash(Message(_('Thread "%(thread)s" has been deleted.') % {'thread': self.thread.name}), 'success', 'threads')
  56. def response(self):
  57. return self.threads_list_redirect()
  58. class HideThreadBaseView(DeleteHideBaseView):
  59. def set_context(self):
  60. self.request.acl.threads.allow_delete_thread(self.request.user, self.proxy,
  61. self.thread, self.thread.start_post)
  62. # Assert we are not user trying to delete thread with replies
  63. acl = self.request.acl.threads.get_role(self.thread.forum_id)
  64. if not acl['can_delete_threads']:
  65. if self.thread.post_set.exclude(user_id=self.request.user.id).count() > 0:
  66. raise ACLError403(_("Somebody has already replied to this thread. You cannot delete it."))
  67. def delete(self):
  68. self.thread.start_post.deleted = True
  69. self.thread.start_post.save(force_update=True)
  70. self.thread.last_post.set_checkpoint(self.request, 'deleted')
  71. self.thread.last_post.save(force_update=True)
  72. self.thread.sync()
  73. self.thread.save(force_update=True)
  74. self.forum.sync()
  75. self.forum.save(force_update=True)
  76. def message(self):
  77. self.request.messages.set_flash(Message(_('Thread "%(thread)s" has been deleted.') % {'thread': self.thread.name}), 'success', 'threads')
  78. def response(self):
  79. if self.request.acl.threads.can_see_deleted_threads(self.thread.forum):
  80. return redirect(reverse(self.type_prefix, kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
  81. return self.threads_list_redirect()
  82. class ShowThreadBaseView(DeleteHideBaseView):
  83. def set_context(self):
  84. acl = self.request.acl.threads.get_role(self.thread.forum_id)
  85. if not acl['can_delete_threads']:
  86. raise ACLError403(_("You cannot undelete this thread."))
  87. if not self.thread.start_post.deleted:
  88. raise ACLError403(_('This thread is already visible!'))
  89. def delete(self):
  90. self.thread.start_post.deleted = False
  91. self.thread.start_post.save(force_update=True)
  92. self.thread.last_post.set_checkpoint(self.request, 'undeleted')
  93. self.thread.last_post.save(force_update=True)
  94. self.thread.sync()
  95. self.thread.save(force_update=True)
  96. self.forum.sync()
  97. self.forum.save(force_update=True)
  98. def message(self):
  99. self.request.messages.set_flash(Message(_('Thread "%(thread)s" has been restored.') % {'thread': self.thread.name}), 'success', 'threads')
  100. def response(self):
  101. if self.request.acl.threads.can_see_deleted_threads(self.thread.forum):
  102. return redirect(reverse(self.type_prefix, kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
  103. return self.threads_list_redirect()
  104. class DeleteReplyBaseView(DeleteHideBaseView):
  105. def set_context(self):
  106. self.request.acl.threads.allow_delete_post(self.request.user, self.forum,
  107. self.thread, self.post, True)
  108. def delete(self):
  109. self.post.delete()
  110. self.thread.sync()
  111. self.thread.save(force_update=True)
  112. self.forum.sync()
  113. self.forum.save(force_update=True)
  114. def message(self):
  115. self.request.messages.set_flash(Message(_("Selected reply has been deleted.")), 'success', 'threads')
  116. def response(self):
  117. return redirect(reverse(self.type_prefix, kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
  118. class HideReplyBaseView(DeleteHideBaseView):
  119. def set_context(self):
  120. self.request.acl.threads.allow_delete_post(self.request.user, self.forum,
  121. self.thread, self.post)
  122. acl = self.request.acl.threads.get_role(self.thread.forum_id)
  123. if not acl['can_delete_posts'] and self.thread.post_set.filter(id__gt=self.post.pk).count() > 0:
  124. raise ACLError403(_("Somebody has already replied to this post, you cannot delete it."))
  125. def delete(self):
  126. self.post.deleted = True
  127. self.post.edit_date = timezone.now()
  128. self.post.edit_user = self.request.user
  129. self.post.edit_user_name = self.request.user.username
  130. self.post.edit_user_slug = self.request.user.username_slug
  131. self.post.save(force_update=True)
  132. self.thread.sync()
  133. self.thread.save(force_update=True)
  134. self.forum.sync()
  135. self.forum.save(force_update=True)
  136. def message(self):
  137. self.request.messages.set_flash(Message(_("Selected reply has been deleted.")), 'success', 'threads_%s' % self.post.pk)
  138. def response(self):
  139. return self.redirect_to_post(self.post)
  140. class ShowReplyBaseView(DeleteHideBaseView):
  141. def set_context(self):
  142. acl = self.request.acl.threads.get_role(self.thread.forum_id)
  143. if not acl['can_delete_posts']:
  144. raise ACLError403(_("You cannot undelete this reply."))
  145. if not self.post.deleted:
  146. raise ACLError403(_('This reply is already visible!'))
  147. def delete(self):
  148. self.post.deleted = False
  149. self.post.edit_date = timezone.now()
  150. self.post.edit_user = self.request.user
  151. self.post.edit_user_name = self.request.user.username
  152. self.post.edit_user_slug = self.request.user.username_slug
  153. self.post.save(force_update=True)
  154. self.thread.sync()
  155. self.thread.save(force_update=True)
  156. self.forum.sync()
  157. self.forum.save(force_update=True)
  158. def message(self):
  159. self.request.messages.set_flash(Message(_("Selected reply has been restored.")), 'success', 'threads_%s' % self.post.pk)
  160. def response(self):
  161. return self.redirect_to_post(self.post)
  162. class DeleteCheckpointBaseView(DeleteHideBaseView):
  163. def set_context(self):
  164. self.request.acl.threads.allow_checkpoint_delete(self.forum)
  165. def delete(self):
  166. self.checkpoint.delete()
  167. self.post.checkpoints = self.post.checkpoint_set.count() > 0
  168. self.post.save(force_update=True)
  169. def message(self):
  170. self.request.messages.set_flash(Message(_("Selected checkpoint has been deleted.")), 'success', 'threads_%s' % self.post.pk)
  171. def response(self):
  172. return self.redirect_to_post(self.post)
  173. class HideCheckpointBaseView(DeleteHideBaseView):
  174. def set_context(self):
  175. self.request.acl.threads.allow_checkpoint_hide(self.forum)
  176. if self.checkpoint.deleted:
  177. raise ACLError403(_('This checkpoint is already hidden!'))
  178. def delete(self):
  179. self.checkpoint.deleted = True
  180. self.checkpoint.save(force_update=True)
  181. def message(self):
  182. self.request.messages.set_flash(Message(_("Selected checkpoint has been hidden.")), 'success', 'threads_%s' % self.post.pk)
  183. def response(self):
  184. return self.redirect_to_post(self.post)
  185. class ShowCheckpointBaseView(DeleteHideBaseView):
  186. def set_context(self):
  187. self.request.acl.threads.allow_checkpoint_show(self.forum)
  188. if self.checkpoint.deleted:
  189. raise ACLError403(_('This checkpoint is already visible!'))
  190. def delete(self):
  191. self.checkpoint.deleted = False
  192. self.checkpoint.save(force_update=True)
  193. def message(self):
  194. self.request.messages.set_flash(Message(_("Selected checkpoint has been restored.")), 'success', 'threads_%s' % self.post.pk)
  195. def response(self):
  196. return self.redirect_to_post(self.post)