threads.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. from rest_framework import viewsets
  2. from rest_framework.decorators import detail_route, list_route
  3. from rest_framework.response import Response
  4. from django.core.exceptions import PermissionDenied
  5. from django.db import transaction
  6. from django.utils.translation import gettext as _
  7. from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
  8. from misago.core.shortcuts import get_int_or_404
  9. from misago.threads.models import Post, Thread
  10. from misago.threads.moderation import threads as moderation
  11. from misago.threads.permissions import allow_use_private_threads
  12. from misago.threads.viewmodels import ForumThread, PrivateThread
  13. from .postingendpoint import PostingEndpoint
  14. from .threadendpoints.editor import thread_start_editor
  15. from .threadendpoints.list import private_threads_list_endpoint, threads_list_endpoint
  16. from .threadendpoints.merge import thread_merge_endpoint, threads_merge_endpoint
  17. from .threadendpoints.patch import thread_patch_endpoint
  18. from .threadendpoints.read import read_private_threads, read_threads
  19. class ViewSet(viewsets.ViewSet):
  20. thread = None
  21. def get_thread(
  22. self, request, pk, read_aware=True, subscription_aware=True, select_for_update=False
  23. ):
  24. return self.thread(
  25. request, get_int_or_404(pk), None, read_aware, subscription_aware, select_for_update
  26. )
  27. def get_thread_for_update(self, request, pk):
  28. return self.get_thread(
  29. request, pk, read_aware=False, subscription_aware=False, select_for_update=True
  30. )
  31. def retrieve(self, request, pk):
  32. thread = self.get_thread(request, pk)
  33. return Response(thread.get_frontend_context())
  34. @transaction.atomic
  35. def partial_update(self, request, pk):
  36. thread = self.get_thread_for_update(request, pk).unwrap()
  37. return thread_patch_endpoint(request, thread)
  38. @transaction.atomic
  39. def destroy(self, request, pk):
  40. thread = self.get_thread_for_update(request, pk)
  41. if thread.acl.get('can_hide') == 2:
  42. moderation.delete_thread(request.user, thread)
  43. return Response({'detail': 'ok'})
  44. else:
  45. raise PermissionDenied(_("You don't have permission to delete this thread."))
  46. class ThreadViewSet(ViewSet):
  47. thread = ForumThread
  48. def list(self, request):
  49. return threads_list_endpoint(request)
  50. @transaction.atomic
  51. def create(self, request):
  52. # Initialize empty instances for new thread
  53. thread = Thread()
  54. post = Post(thread=thread)
  55. # Put them through posting pipeline
  56. posting = PostingEndpoint(
  57. request, PostingEndpoint.START, tree_name=THREADS_ROOT_NAME, thread=thread, post=post
  58. )
  59. if posting.is_valid():
  60. posting.save()
  61. return Response({
  62. 'id': thread.pk,
  63. 'title': thread.title,
  64. 'url': thread.get_absolute_url()
  65. })
  66. else:
  67. return Response(posting.errors, status=400)
  68. @detail_route(methods=['post'], url_path='merge')
  69. @transaction.atomic
  70. def thread_merge(self, request, pk):
  71. thread = self.get_thread_for_update(request, pk).unwrap()
  72. return thread_merge_endpoint(request, thread, self.thread)
  73. @list_route(methods=['post'], url_path='merge')
  74. @transaction.atomic
  75. def threads_merge(self, request):
  76. return threads_merge_endpoint(request)
  77. @list_route(methods=['get'])
  78. def editor(self, request):
  79. return thread_start_editor(request)
  80. @list_route(methods=['post'])
  81. @transaction.atomic
  82. def read(self, request):
  83. read_threads(request.user, request.GET.get('category'))
  84. return Response({'detail': 'ok'})
  85. class PrivateThreadViewSet(ViewSet):
  86. thread = PrivateThread
  87. def list(self, request):
  88. return private_threads_list_endpoint(request)
  89. @transaction.atomic
  90. def create(self, request):
  91. allow_use_private_threads(request.user)
  92. if not request.user.acl_cache['can_start_private_threads']:
  93. raise PermissionDenied(_("You can't start private threads."))
  94. # Initialize empty instances for new thread
  95. thread = Thread()
  96. post = Post(thread=thread)
  97. # Put them through posting pipeline
  98. posting = PostingEndpoint(
  99. request,
  100. PostingEndpoint.START,
  101. tree_name=PRIVATE_THREADS_ROOT_NAME,
  102. thread=thread,
  103. post=post
  104. )
  105. if posting.is_valid():
  106. posting.save()
  107. return Response({
  108. 'id': thread.pk,
  109. 'title': thread.title,
  110. 'url': thread.get_absolute_url()
  111. })
  112. else:
  113. return Response(posting.errors, status=400)
  114. @list_route(methods=['post'])
  115. @transaction.atomic
  116. def read(self, request):
  117. allow_use_private_threads(request.user)
  118. read_private_threads(request.user)
  119. return Response({'detail': 'ok'})