merge.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from rest_framework.response import Response
  2. from django.core.exceptions import PermissionDenied
  3. from django.utils import six
  4. from django.utils.translation import ugettext as _, ungettext
  5. from misago.acl import add_acl
  6. from misago.conf import settings
  7. from misago.core.utils import clean_ids_list
  8. from misago.threads.permissions import allow_merge_post, exclude_invisible_posts
  9. from misago.threads.serializers import MergePostsSerializer, PostSerializer
  10. MERGE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
  11. def posts_merge_endpoint(request, thread):
  12. if not thread.acl['can_merge_posts']:
  13. raise PermissionDenied(_("You can't merge posts in this thread."))
  14. serializer = MergePostsSerializer(
  15. data=request.data,
  16. context={
  17. 'thread': thread,
  18. 'user': request.user,
  19. },
  20. )
  21. if not serializer.is_valid():
  22. return Response(
  23. {
  24. 'detail': list(serializer.errors.values())[0][0],
  25. },
  26. status=400,
  27. )
  28. posts = serializer.posts_cache
  29. first_post, merged_posts = posts[0], posts[1:]
  30. for post in merged_posts:
  31. post.merge(first_post)
  32. post.delete()
  33. if first_post.pk == thread.first_post_id:
  34. first_post.set_search_document(thread.title)
  35. else:
  36. first_post.set_search_document()
  37. first_post.save()
  38. first_post.update_search_vector()
  39. first_post.save(update_fields=['search_vector'])
  40. thread.synchronize()
  41. thread.save()
  42. thread.category.synchronize()
  43. thread.category.save()
  44. first_post.thread = thread
  45. first_post.category = thread.category
  46. add_acl(request.user, first_post)
  47. return Response(PostSerializer(first_post, context={'user': request.user}).data)
  48. def clean_posts_for_merge(request, thread):
  49. posts_ids = clean_ids_list(
  50. request.data.get('posts', []),
  51. _("One or more post ids received were invalid."),
  52. )
  53. if len(posts_ids) < 2:
  54. raise PermissionDenied(_("You have to select at least two posts to merge."))
  55. elif len(posts_ids) > MERGE_LIMIT:
  56. message = ungettext(
  57. "No more than %(limit)s post can be merged at single time.",
  58. "No more than %(limit)s posts can be merged at single time.",
  59. MERGE_LIMIT,
  60. )
  61. raise PermissionDenied(message % {'limit': MERGE_LIMIT})
  62. posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set)
  63. posts_queryset = posts_queryset.filter(id__in=posts_ids).order_by('id')
  64. posts = []
  65. for post in posts_queryset:
  66. post.category = thread.category
  67. post.thread = thread
  68. allow_merge_post(request.user, post)
  69. if not posts:
  70. posts.append(post)
  71. else:
  72. authorship_error = _("Posts made by different users can't be merged.")
  73. if posts[0].poster_id:
  74. if post.poster_id != posts[0].poster_id:
  75. raise PermissionDenied(authorship_error)
  76. else:
  77. if post.poster_id or post.poster_name != posts[0].poster_name:
  78. raise PermissionDenied(authorship_error)
  79. if posts[0].pk != thread.first_post_id:
  80. if (posts[0].is_hidden != post.is_hidden or
  81. posts[0].is_unapproved != post.is_unapproved):
  82. raise PermissionDenied(_("Posts with different visibility can't be merged."))
  83. posts.append(post)
  84. if len(posts) != len(posts_ids):
  85. raise PermissionDenied(_("One or more posts to merge could not be found."))
  86. return posts