attachments.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from django.conf import settings
  2. from django.utils.translation import ugettext as _, ungettext
  3. from rest_framework import serializers
  4. from misago.acl import add_acl
  5. from . import PostingEndpoint, PostingInterrupt, PostingMiddleware
  6. from ...serializers import AttachmentSerializer
  7. class AttachmentsMiddleware(PostingMiddleware):
  8. def use_this_middleware(self):
  9. return bool(self.user.acl['max_attachment_size'])
  10. def get_serializer(self):
  11. return AttachmentsSerializer(data=self.request.data, context={
  12. 'mode': self.mode,
  13. 'user': self.user,
  14. 'post': self.post,
  15. })
  16. def save(self, serializer):
  17. serializer.save()
  18. class AttachmentsSerializer(serializers.Serializer):
  19. attachments = serializers.ListField(
  20. child=serializers.IntegerField(),
  21. required=False
  22. )
  23. def validate_attachments(self, ids):
  24. self.update_attachments = False
  25. self.removed_attachments = []
  26. self.final_attachments = []
  27. ids = list(set(ids))
  28. validate_attachments_count(ids)
  29. attachments = self.get_initial_attachments(
  30. self.context['mode'], self.context['user'], self.context['post'])
  31. new_attachments = self.get_new_attachments(self.context['user'], ids)
  32. if not attachments and not new_attachments:
  33. return [] # no attachments
  34. # clean existing attachments
  35. for attachment in attachments:
  36. if attachment.pk in ids:
  37. self.final_attachments.append(attachment)
  38. else:
  39. if attachment.acl['can_delete']:
  40. self.update_attachments = True
  41. self.removed_attachments.append(attachment)
  42. else:
  43. message = _("You don't have permission to remove \"%(attachment)s\" attachment.")
  44. raise serializers.ValidationError(message % {'attachment': attachment.filename})
  45. if new_attachments:
  46. self.update_attachments = True
  47. self.final_attachments += new_attachments
  48. self.final_attachments.sort(key=lambda a: a.pk, reverse=True)
  49. def get_initial_attachments(self, mode, user, post):
  50. attachments = []
  51. if mode == PostingEndpoint.EDIT:
  52. queryset = post.attachment_set.select_related('filetype')
  53. attachments = list(queryset)
  54. add_acl(user, attachments)
  55. return attachments
  56. def get_new_attachments(self, user, ids):
  57. if not ids:
  58. return []
  59. queryset = user.attachment_set.select_related('filetype').filter(
  60. post__isnull=True,
  61. id__in=ids
  62. )
  63. return list(queryset)
  64. def save(self):
  65. if not self.update_attachments:
  66. return
  67. if self.removed_attachments:
  68. self.context['post'].attachment_set.filter(
  69. id__in=[a.id for a in self.removed_attachments]
  70. ).update(post=None)
  71. if self.final_attachments:
  72. # sort final attachments by id, descending
  73. self.final_attachments.sort(key=lambda a: a.pk, reverse=True)
  74. self.context['user'].attachment_set.filter(
  75. id__in=[a.id for a in self.final_attachments]
  76. ).update(post=self.context['post'])
  77. self.sync_attachments_cache(self.context['post'], self.final_attachments)
  78. def sync_attachments_cache(self, post, attachments):
  79. if attachments:
  80. post.attachments_cache = AttachmentSerializer(attachments, many=True).data
  81. for attachment in post.attachments_cache:
  82. del attachment['acl']
  83. del attachment['post']
  84. del attachment['uploader_ip']
  85. else:
  86. post.attachments_cache = None
  87. post.update_fields.append('attachments_cache')
  88. def validate_attachments_count(data):
  89. total_attachments = len(data)
  90. if total_attachments > settings.MISAGO_POST_ATTACHMENTS_LIMIT:
  91. message = ungettext(
  92. "You can't attach more than %(limit_value)s file to single post (added %(show_value)s).",
  93. "You can't attach more than %(limit_value)s flies to single post (added %(show_value)s).",
  94. settings.MISAGO_POST_ATTACHMENTS_LIMIT)
  95. raise serializers.ValidationError(message % {
  96. 'limit_value': settings.MISAGO_POST_ATTACHMENTS_LIMIT,
  97. 'show_value': total_attachments
  98. })