123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- from rest_framework import serializers
- from django.template.defaultfilters import filesizeformat
- from django.urls import reverse
- from django.utils.translation import ugettext as _
- from misago.threads.models import Attachment, AttachmentType
- IMAGE_EXTENSIONS = ('jpg', 'jpeg', 'png', 'gif')
- class AttachmentSerializer(serializers.ModelSerializer):
- post = serializers.PrimaryKeyRelatedField(read_only=True)
- acl = serializers.SerializerMethodField()
- is_image = serializers.SerializerMethodField()
- filetype = serializers.SerializerMethodField()
- uploader_ip = serializers.SerializerMethodField()
- url = serializers.SerializerMethodField()
- class Meta:
- model = Attachment
- fields = [
- 'id',
- 'filetype',
- 'post',
- 'uploaded_on',
- 'uploader_name',
- 'uploader_ip',
- 'filename',
- 'size',
- 'acl',
- 'is_image',
- 'url',
- ]
- def get_acl(self, obj):
- try:
- return obj.acl
- except AttributeError:
- return None
- def get_is_image(self, obj):
- return obj.is_image
- def get_filetype(self, obj):
- return obj.filetype.name
- def get_uploader_ip(self, obj):
- user = self.context.get('user')
- if user and user.acl_cache['can_see_users_ips']:
- return obj.uploader_ip
- else:
- return None
- def get_url(self, obj):
- return {
- 'index': obj.get_absolute_url(),
- 'thumb': obj.get_thumbnail_url(),
- 'uploader': self.get_uploader_url(obj),
- }
- def get_uploader_url(self, obj):
- if obj.uploader_id:
- return reverse(
- 'misago:user', kwargs={
- 'slug': obj.uploader_slug,
- 'pk': obj.uploader_id,
- }
- )
- else:
- return None
- class NewAttachmentSerializer(serializers.Serializer):
- upload = serializers.FileField()
- def validate_upload(self, upload):
- user = self.context['request'].user
- user_roles = set(r.pk for r in user.get_roles())
- max_attachment_size = user.acl_cache['max_attachment_size']
-
- self.filetype = self.validate_filetype(upload, user_roles)
- self.validate_filesize(upload, self.filetype, max_attachment_size)
- return upload
- def validate_filetype(self, upload, user_roles):
- filename = upload.name.strip().lower()
- queryset = AttachmentType.objects.filter(status=AttachmentType.ENABLED)
- for filetype in queryset.prefetch_related('limit_uploads_to'):
- for extension in filetype.extensions_list:
- if filename.endswith('.%s' % extension):
- break
- else:
- continue
- if filetype.mimetypes_list and upload.content_type not in filetype.mimetypes_list:
- continue
- if filetype.limit_uploads_to.exists():
- allowed_roles = set(r.pk for r in filetype.limit_uploads_to.all())
- if not user_roles & allowed_roles:
- continue
- return filetype
- raise serializers.ValidationError(_("You can't upload files of this type."))
- def validate_filesize(self, upload, filetype, hard_limit):
- if upload.size > hard_limit * 1024:
- message = _("You can't upload files larger than %(limit)s (your file has %(upload)s).")
- raise serializers.ValidationError(
- message % {
- 'upload': filesizeformat(upload.size).rstrip('.0'),
- 'limit': filesizeformat(hard_limit * 1024).rstrip('.0'),
- }
- )
- if filetype.size_limit and upload.size > filetype.size_limit * 1024:
- message = _(
- "You can't upload files of this type larger than %(limit)s (your file has %(upload)s)."
- )
- raise serializers.ValidationError(
- message % {
- 'upload': filesizeformat(upload.size).rstrip('.0'),
- 'limit': filesizeformat(filetype.size_limit * 1024).rstrip('.0'),
- }
- )
- def is_upload_image(self, upload):
- filename = upload.name.strip().lower()
- for extension in IMAGE_EXTENSIONS:
- if filename.endswith('.%s' % extension):
- return True
- return False
- def save(self):
- request = self.context['request']
- upload = self.validated_data['upload']
- self.instance = Attachment(
- secret=Attachment.generate_new_secret(),
- filetype=self.filetype,
- size=upload.size,
- uploader=request.user,
- uploader_name=request.user.username,
- uploader_slug=request.user.slug,
- uploader_ip=request.user_ip,
- filename=upload.name,
- )
- if self.is_upload_image(upload):
- try:
- self.instance.set_image(upload)
- except IOError:
- raise serializers.ValidationError({
- 'upload': [_("Uploaded image was corrupted or invalid.")],
- })
- else:
- self.instance.set_file(upload)
- self.instance.save()
- return self.instance
|