post.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. from django.contrib import messages
  2. from django.core.exceptions import PermissionDenied
  3. from django.db.transaction import atomic
  4. from django.http import JsonResponse
  5. from django.shortcuts import render, redirect
  6. from django.utils.translation import ugettext as _
  7. from misago.acl import add_acl
  8. from misago.core.errorpages import not_allowed
  9. from misago.threads import permissions, moderation, goto
  10. from misago.threads.forms.report import ReportPostForm
  11. from misago.threads.reports import user_has_reported_post, report_post
  12. from misago.threads.views.generic.base import ViewBase
  13. __all__ = [
  14. 'QuotePostView',
  15. 'ApprovePostView',
  16. 'UnhidePostView',
  17. 'HidePostView',
  18. 'DeletePostView',
  19. 'ReportPostView'
  20. ]
  21. class PostView(ViewBase):
  22. is_atomic = True
  23. require_post = True
  24. def dispatch(self, request, *args, **kwargs):
  25. if self.require_post and request.method != "POST":
  26. return not_allowed(request)
  27. post = None
  28. response = None
  29. if self.is_atomic:
  30. with atomic():
  31. post = self.get_post(request, True, **kwargs)
  32. response = self.real_dispatch(request, post)
  33. else:
  34. post = self.get_post(request, **kwargs)
  35. response = self.real_dispatch(request, post)
  36. if response:
  37. return response
  38. else:
  39. return self.redirect_to_post(request.user, post)
  40. def real_dispatch(self, request, post):
  41. raise NotImplementedError(
  42. "post views have to override real_dispatch method")
  43. def redirect_to_post(self, user, post):
  44. posts_qs = self.exclude_invisible_posts(post.thread.post_set,
  45. user,
  46. post.forum,
  47. post.thread)
  48. return redirect(goto.post(post.thread, posts_qs, post))
  49. class QuotePostView(PostView):
  50. is_atomic = False
  51. require_post = False
  52. def real_dispatch(self, request, post):
  53. quote_tpl = u'[quote="%s, post:%s, topic:%s"]\n%s\n[/quote]'
  54. formats = (post.poster_name, post.pk, post.thread_id, post.original)
  55. return JsonResponse({
  56. 'quote': quote_tpl % formats
  57. })
  58. class ApprovePostView(PostView):
  59. def real_dispatch(self, request, post):
  60. if not post.acl['can_approve']:
  61. raise PermissionDenied(_("You can't approve this post."))
  62. if post.id == post.thread.first_post_id:
  63. moderation.approve_thread(request.user, post.thread)
  64. messages.success(request, _("Thread has been approved."))
  65. else:
  66. moderation.approve_post(request.user, post)
  67. messages.success(request, _("Post has been approved."))
  68. post.thread.synchronize()
  69. post.thread.save()
  70. post.forum.synchronize()
  71. post.forum.save()
  72. class UnhidePostView(PostView):
  73. is_atomic = False
  74. def real_dispatch(self, request, post):
  75. permissions.allow_unhide_post(request.user, post)
  76. moderation.unhide_post(request.user, post)
  77. messages.success(request, _("Post has been made visible."))
  78. class HidePostView(PostView):
  79. is_atomic = False
  80. def real_dispatch(self, request, post):
  81. permissions.allow_hide_post(request.user, post)
  82. moderation.hide_post(request.user, post)
  83. messages.success(request, _("Post has been hidden."))
  84. class DeletePostView(PostView):
  85. def real_dispatch(self, request, post):
  86. post_id = post.id
  87. permissions.allow_delete_post(request.user, post)
  88. moderation.delete_post(request.user, post)
  89. post.thread.synchronize()
  90. post.thread.save()
  91. post.forum.synchronize()
  92. post.forum.save()
  93. posts_qs = self.exclude_invisible_posts(post.thread.post_set,
  94. request.user,
  95. post.forum,
  96. post.thread)
  97. posts_qs = posts_qs.select_related('thread', 'forum')
  98. if post_id < post.thread.last_post_id:
  99. target_post = posts_qs.order_by('id').filter(id__gt=post_id)
  100. else:
  101. target_post = posts_qs.order_by('-id').filter(id__lt=post_id)
  102. target_post = target_post[:1][0]
  103. target_post.thread.forum = target_post.forum
  104. add_acl(request.user, target_post.forum)
  105. add_acl(request.user, target_post.thread)
  106. add_acl(request.user, target_post)
  107. messages.success(request, _("Post has been deleted."))
  108. return self.redirect_to_post(request.user, target_post)
  109. class ReportPostView(PostView):
  110. require_post = False
  111. template = 'misago/thread/report_modal.html'
  112. alerts_template = 'misago/thread/post_alerts.html'
  113. def dispatch(self, request, *args, **kwargs):
  114. if not request.is_ajax():
  115. return not_allowed(request)
  116. return super(ReportPostView, self).dispatch(request, *args, **kwargs)
  117. def real_dispatch(self, request, post):
  118. if not post.acl['can_report']:
  119. raise PermissionDenied(_("You can't report posts."))
  120. if user_has_reported_post(request.user, post):
  121. return JsonResponse({
  122. 'is_reported': True,
  123. 'message': _("You have already reported this post.")})
  124. form = ReportPostForm()
  125. if request.method == 'POST':
  126. form = ReportPostForm(request.POST)
  127. if form.is_valid():
  128. report_post(request,
  129. post,
  130. form.cleaned_data['report_message'])
  131. message = _("%(user)s's post has been "
  132. "reported to moderators.")
  133. message = message % {'user': post.poster_name}
  134. return JsonResponse({
  135. 'message': message,
  136. 'label': _("Reported"),
  137. 'alerts': self.render_alerts(request, post)
  138. })
  139. else:
  140. field_errors = form.errors.get('report_message')
  141. if field_errors:
  142. field_error = field_errors[0]
  143. else:
  144. field_error = _("Error reporting post.")
  145. return JsonResponse({'is_error': True, 'message': field_error})
  146. return self.render(request, {'form': form})
  147. def render_alerts(self, request, post):
  148. return render(request, self.alerts_template, {
  149. 'forum': post.forum,
  150. 'thread': post.thread,
  151. 'post': post
  152. }).content