privatethreads.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. from django.http import Http404
  2. from django.shortcuts import get_object_or_404, render
  3. from django.utils.translation import ugettext as _
  4. from misago.acl import add_acl
  5. from misago.forums.models import Forum
  6. from misago.threads.models import Thread, ThreadParticipant
  7. from misago.threads.permissions import (allow_use_private_threads,
  8. allow_see_private_thread,
  9. allow_see_private_post,
  10. exclude_invisible_private_threads)
  11. from misago.threads.views import generic
  12. def private_threads_view(klass):
  13. """
  14. decorator for making views check allow_use_private_threads
  15. """
  16. def decorator(f):
  17. def dispatch(self, request, *args, **kwargs):
  18. allow_use_private_threads(request.user)
  19. return f(self, request, *args, **kwargs)
  20. return dispatch
  21. klass.dispatch = decorator(klass.dispatch)
  22. return klass
  23. class PrivateThreadsMixin(object):
  24. """
  25. Mixin is used to make views use different permission tests
  26. """
  27. def get_forum(self, request, lock=False, **kwargs):
  28. forum = Forum.objects.private_threads()
  29. add_acl(request.user, forum)
  30. return forum
  31. def check_forum_permissions(self, request, forum):
  32. add_acl(request.user, forum)
  33. allow_use_private_threads(request.user)
  34. def fetch_thread(self, request, lock=False, select_related=None,
  35. queryset=None, **kwargs):
  36. queryset = queryset or Thread.objects
  37. if lock:
  38. queryset = queryset.select_for_update()
  39. select_related = select_related or []
  40. if not 'forum' in select_related:
  41. select_related.append('forum')
  42. queryset = queryset.select_related(*select_related)
  43. where = {'id': kwargs.get('thread_id')}
  44. thread = get_object_or_404(queryset, **where)
  45. if thread.forum.special_role != 'private_threads':
  46. raise Http404()
  47. return thread
  48. def fetch_thread_participants(self, user, thread):
  49. thread.participants_list = []
  50. thread.participant = None
  51. participants_qs = ThreadParticipant.objects.filter(thread=thread)
  52. participants_qs = participants_qs.select_related('user')
  53. for participant in participants_qs:
  54. participant.thread = thread
  55. thread.participants_list.append(participant)
  56. if participant.user == user:
  57. thread.participant = participant
  58. return thread.participants_list
  59. def check_thread_permissions(self, request, thread):
  60. add_acl(request.user, thread.forum)
  61. add_acl(request.user, thread)
  62. self.fetch_thread_participants(request.user, thread)
  63. allow_see_private_thread(request.user, thread)
  64. allow_use_private_threads(request.user)
  65. def check_post_permissions(self, request, post):
  66. add_acl(request.user, post.forum)
  67. add_acl(request.user, post.thread)
  68. add_acl(request.user, post)
  69. self.fetch_thread_participants(request.user, post.thread)
  70. allow_see_private_post(request.user, post)
  71. allow_see_private_thread(request.user, post.thread)
  72. allow_use_private_threads(request.user)
  73. def exclude_invisible_posts(self, queryset, user, forum, thread):
  74. return queryset
  75. class PrivateThreads(generic.Threads):
  76. def get_queryset(self):
  77. threads_qs = Forum.objects.private_threads().thread_set
  78. return exclude_invisible_private_threads(threads_qs, self.user)
  79. def clean_threads_activity(self, user, threads):
  80. pass
  81. class PrivateThreadsFiltering(generic.ThreadsFiltering):
  82. def get_available_filters(self):
  83. filters = super(PrivateThreadsFiltering, self).get_available_filters()
  84. if self.user.acl['can_moderate_private_threads']:
  85. filters.append({
  86. 'type': 'reported',
  87. 'name': _("With reported posts"),
  88. 'is_label': False,
  89. })
  90. return filters
  91. @private_threads_view
  92. class PrivateThreadsView(generic.ThreadsView):
  93. link_name = 'misago:private_threads'
  94. template = 'misago/privatethreads/list.html'
  95. Threads = PrivateThreads
  96. Filtering = PrivateThreadsFiltering
  97. @private_threads_view
  98. class ThreadParticipantsView(PrivateThreadsMixin, generic.ViewBase):
  99. template = 'misago/privatethreads/participants.html'
  100. def dispatch(self, request, *args, **kwargs):
  101. thread = self.get_thread(request, **kwargs)
  102. if not request.is_ajax():
  103. response = render(request, 'misago/errorpages/wrong_way.html')
  104. response.status_code = 405
  105. return response
  106. participants_qs = thread.threadparticipant_set
  107. participants_qs = participants_qs.select_related('user')
  108. return self.render(request, {
  109. 'participants': participants_qs.order_by('-is_owner', 'user__slug')
  110. })
  111. """
  112. Generics
  113. """
  114. @private_threads_view
  115. class ThreadView(PrivateThreadsMixin, generic.ThreadView):
  116. pass
  117. @private_threads_view
  118. class GotoLastView(PrivateThreadsMixin, generic.GotoLastView):
  119. pass
  120. @private_threads_view
  121. class GotoNewView(PrivateThreadsMixin, generic.GotoNewView):
  122. pass
  123. @private_threads_view
  124. class GotoPostView(PrivateThreadsMixin, generic.GotoPostView):
  125. pass
  126. @private_threads_view
  127. class ReportedPostsListView(PrivateThreadsMixin, generic.ReportedPostsListView):
  128. pass
  129. @private_threads_view
  130. class QuotePostView(PrivateThreadsMixin, generic.QuotePostView):
  131. pass
  132. @private_threads_view
  133. class UnhidePostView(PrivateThreadsMixin, generic.UnhidePostView):
  134. pass
  135. @private_threads_view
  136. class HidePostView(PrivateThreadsMixin, generic.HidePostView):
  137. pass
  138. @private_threads_view
  139. class DeletePostView(PrivateThreadsMixin, generic.DeletePostView):
  140. pass
  141. @private_threads_view
  142. class EventsView(PrivateThreadsMixin, generic.EventsView):
  143. pass
  144. @private_threads_view
  145. class PostingView(PrivateThreadsMixin, generic.PostingView):
  146. pass