threads.py 4.7 KB

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