from rest_framework import viewsets from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response from django.core.exceptions import PermissionDenied from django.db import transaction from django.utils.translation import gettext as _ from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME from misago.core.shortcuts import get_int_or_404 from misago.threads.models import Post, Thread from misago.threads.moderation import threads as moderation from misago.threads.permissions import allow_use_private_threads from misago.threads.viewmodels import ForumThread, PrivateThread from .postingendpoint import PostingEndpoint from .threadendpoints.editor import thread_start_editor from .threadendpoints.list import private_threads_list_endpoint, threads_list_endpoint from .threadendpoints.merge import thread_merge_endpoint, threads_merge_endpoint from .threadendpoints.patch import thread_patch_endpoint from .threadendpoints.read import read_private_threads, read_threads class ViewSet(viewsets.ViewSet): thread = None def get_thread( self, request, pk, read_aware=True, subscription_aware=True, select_for_update=False ): return self.thread( request, get_int_or_404(pk), None, read_aware, subscription_aware, select_for_update ) def get_thread_for_update(self, request, pk): return self.get_thread( request, pk, read_aware=False, subscription_aware=False, select_for_update=True ) def retrieve(self, request, pk): thread = self.get_thread(request, pk) return Response(thread.get_frontend_context()) @transaction.atomic def partial_update(self, request, pk): thread = self.get_thread_for_update(request, pk).unwrap() return thread_patch_endpoint(request, thread) @transaction.atomic def destroy(self, request, pk): thread = self.get_thread_for_update(request, pk) if thread.acl.get('can_hide') == 2: moderation.delete_thread(request.user, thread) return Response({'detail': 'ok'}) else: raise PermissionDenied(_("You don't have permission to delete this thread.")) class ThreadViewSet(ViewSet): thread = ForumThread def list(self, request): return threads_list_endpoint(request) @transaction.atomic def create(self, request): # Initialize empty instances for new thread thread = Thread() post = Post(thread=thread) # Put them through posting pipeline posting = PostingEndpoint( request, PostingEndpoint.START, tree_name=THREADS_ROOT_NAME, thread=thread, post=post ) if posting.is_valid(): posting.save() return Response({ 'id': thread.pk, 'title': thread.title, 'url': thread.get_absolute_url() }) else: return Response(posting.errors, status=400) @detail_route(methods=['post'], url_path='merge') @transaction.atomic def thread_merge(self, request, pk): thread = self.get_thread_for_update(request, pk).unwrap() return thread_merge_endpoint(request, thread, self.thread) @list_route(methods=['post'], url_path='merge') @transaction.atomic def threads_merge(self, request): return threads_merge_endpoint(request) @list_route(methods=['get']) def editor(self, request): return thread_start_editor(request) @list_route(methods=['post']) @transaction.atomic def read(self, request): read_threads(request.user, request.GET.get('category')) return Response({'detail': 'ok'}) class PrivateThreadViewSet(ViewSet): thread = PrivateThread def list(self, request): return private_threads_list_endpoint(request) @transaction.atomic def create(self, request): allow_use_private_threads(request.user) if not request.user.acl_cache['can_start_private_threads']: raise PermissionDenied(_("You can't start private threads.")) # Initialize empty instances for new thread thread = Thread() post = Post(thread=thread) # Put them through posting pipeline posting = PostingEndpoint( request, PostingEndpoint.START, tree_name=PRIVATE_THREADS_ROOT_NAME, thread=thread, post=post ) if posting.is_valid(): posting.save() return Response({ 'id': thread.pk, 'title': thread.title, 'url': thread.get_absolute_url() }) else: return Response(posting.errors, status=400) @list_route(methods=['post']) @transaction.atomic def read(self, request): allow_use_private_threads(request.user) read_private_threads(request.user) return Response({'detail': 'ok'})