|
@@ -2,115 +2,22 @@ from rest_framework import viewsets
|
|
from rest_framework.response import Response
|
|
from rest_framework.response import Response
|
|
|
|
|
|
from django.core.exceptions import PermissionDenied
|
|
from django.core.exceptions import PermissionDenied
|
|
-from django.template.defaultfilters import filesizeformat
|
|
|
|
-from django.utils import six
|
|
|
|
from django.utils.translation import ugettext as _
|
|
from django.utils.translation import ugettext as _
|
|
|
|
|
|
from misago.acl import add_acl
|
|
from misago.acl import add_acl
|
|
-from misago.threads.models import Attachment, AttachmentType
|
|
|
|
-from misago.threads.serializers import AttachmentSerializer
|
|
|
|
|
|
+from misago.threads.serializers import AttachmentSerializer, NewAttachmentSerializer
|
|
|
|
|
|
|
|
|
|
IMAGE_EXTENSIONS = ('jpg', 'jpeg', 'png', 'gif')
|
|
IMAGE_EXTENSIONS = ('jpg', 'jpeg', 'png', 'gif')
|
|
|
|
|
|
|
|
|
|
-class UploadError(Exception):
|
|
|
|
- pass
|
|
|
|
-
|
|
|
|
-
|
|
|
|
class AttachmentViewSet(viewsets.ViewSet):
|
|
class AttachmentViewSet(viewsets.ViewSet):
|
|
def create(self, request):
|
|
def create(self, request):
|
|
if not request.user.acl_cache['max_attachment_size']:
|
|
if not request.user.acl_cache['max_attachment_size']:
|
|
raise PermissionDenied(_("You don't have permission to upload new files."))
|
|
raise PermissionDenied(_("You don't have permission to upload new files."))
|
|
- try:
|
|
|
|
- return self.create_attachment(request)
|
|
|
|
- except UploadError as e:
|
|
|
|
- return Response({'upload': e.args}, status=400)
|
|
|
|
-
|
|
|
|
- def create_attachment(self, request):
|
|
|
|
- upload = request.FILES.get('upload')
|
|
|
|
- if not upload:
|
|
|
|
- raise UploadError(_("No file has been uploaded."))
|
|
|
|
-
|
|
|
|
- user_roles = set(r.pk for r in request.user.get_roles())
|
|
|
|
- filetype = validate_filetype(upload, user_roles)
|
|
|
|
- validate_filesize(upload, filetype, request.user.acl_cache['max_attachment_size'])
|
|
|
|
-
|
|
|
|
- attachment = Attachment(
|
|
|
|
- secret=Attachment.generate_new_secret(),
|
|
|
|
- filetype=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 is_upload_image(upload):
|
|
|
|
- try:
|
|
|
|
- attachment.set_image(upload)
|
|
|
|
- except IOError:
|
|
|
|
- raise UploadError(_("Uploaded image was corrupted or invalid."))
|
|
|
|
- else:
|
|
|
|
- attachment.set_file(upload)
|
|
|
|
-
|
|
|
|
- attachment.save()
|
|
|
|
|
|
+ serializer = NewAttachmentSerializer(data=request.data, context={'request': request})
|
|
|
|
+ serializer.is_valid(raise_exception=True)
|
|
|
|
+ attachment = serializer.save()
|
|
add_acl(request.user, attachment)
|
|
add_acl(request.user, attachment)
|
|
-
|
|
|
|
return Response(AttachmentSerializer(attachment, context={'user': request.user}).data)
|
|
return Response(AttachmentSerializer(attachment, context={'user': request.user}).data)
|
|
-
|
|
|
|
-
|
|
|
|
-def validate_filetype(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 UploadError(_("You can't upload files of this type."))
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def validate_filesize(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 UploadError(
|
|
|
|
- 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 UploadError(
|
|
|
|
- message % {
|
|
|
|
- 'upload': filesizeformat(upload.size).rstrip('.0'),
|
|
|
|
- 'limit': filesizeformat(filetype.size_limit * 1024).rstrip('.0'),
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def is_upload_image(upload):
|
|
|
|
- filename = upload.name.strip().lower()
|
|
|
|
-
|
|
|
|
- for extension in IMAGE_EXTENSIONS:
|
|
|
|
- if filename.endswith('.%s' % extension):
|
|
|
|
- return True
|
|
|
|
- return False
|
|
|