Esempio n. 1
0
    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
    def test_attachments_sync(self):
        """command synchronizes attachments"""
        filetype = AttachmentType.objects.order_by('id').last()

        # create 5 expired orphaned attachments
        cutoff = timezone.now() - timedelta(minutes=settings.MISAGO_ATTACHMENT_ORPHANED_EXPIRE)
        cutoff -= timedelta(minutes=5)

        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploaded_on=cutoff,
                uploader_name='bob',
                uploader_slug='bob',
                uploader_ip='127.0.0.1',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        # create 5 expired non-orphaned attachments
        category = Category.objects.get(slug='first-category')
        post = testutils.post_thread(category).first_post

        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploaded_on=cutoff,
                post=post,
                uploader_name='bob',
                uploader_slug='bob',
                uploader_ip='127.0.0.1',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        # create 5 fresh orphaned attachments
        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploader_name='bob',
                uploader_slug='bob',
                uploader_ip='127.0.0.1',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        command = clearattachments.Command()

        out = StringIO()
        call_command(command, stdout=out)

        command_output = out.getvalue().splitlines()[-1].strip()
        self.assertEqual(command_output, "Cleared 5 attachments")

        self.assertEqual(Attachment.objects.count(), 10)
Esempio n. 3
0
    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()
        add_acl(request.user, attachment)

        return Response(AttachmentSerializer(attachment, context={'user': request.user}).data)
Esempio n. 4
0
    def test_attachments_sync(self):
        """command synchronizes attachments"""
        filetype = AttachmentType.objects.order_by('id').last()

        # create 5 expired orphaned attachments
        cutoff = timezone.now() - timedelta(minutes=settings.MISAGO_ATTACHMENT_ORPHANED_EXPIRE)
        cutoff -= timedelta(minutes=5)

        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploaded_on=cutoff,
                uploader_name='bob',
                uploader_slug='bob',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        # create 5 expired non-orphaned attachments
        category = Category.objects.get(slug='first-category')
        post = testutils.post_thread(category).first_post

        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploaded_on=cutoff,
                post=post,
                uploader_name='bob',
                uploader_slug='bob',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        # create 5 fresh orphaned attachments
        for _ in range(5):
            Attachment.objects.create(
                secret=Attachment.generate_new_secret(),
                filetype=filetype,
                size=1000,
                uploader_name='bob',
                uploader_slug='bob',
                filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            )

        command = clearattachments.Command()

        out = StringIO()
        call_command(command, stdout=out)

        command_output = out.getvalue().splitlines()[-1].strip()
        self.assertEqual(command_output, "Cleared 5 attachments")

        self.assertEqual(Attachment.objects.count(), 10)
    def create_attachment(self, request):
        upload = request.FILES.get('upload')
        if not upload:
            raise ValidationError(_("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 ValidationError(_("Uploaded image was corrupted or invalid."))
        else:
            attachment.set_file(upload)

        attachment.save()
        add_acl(request.user, attachment)

        return Response(AttachmentSerializer(attachment, context={'user': request.user}).data)
 def mock_attachment(self, user=True, post=None):
     return Attachment.objects.create(
         secret=Attachment.generate_new_secret(),
         filetype=self.filetype,
         post=post,
         size=1000,
         uploader=self.user if user else None,
         uploader_name=self.user.username,
         uploader_slug=self.user.slug,
         filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
     )
 def mock_attachment(self, user=True, post=None):
     return Attachment.objects.create(
         secret=Attachment.generate_new_secret(),
         filetype=self.filetype,
         post=post,
         size=1000,
         uploader=self.user if user else None,
         uploader_name=self.user.username,
         uploader_slug=self.user.slug,
         uploader_ip='127.0.0.1',
         filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
     )
Esempio n. 8
0
 def mock_attachment(self,
                     post=None,
                     file=None,
                     image=None,
                     thumbnail=None):
     return Attachment.objects.create(
         secret=Attachment.generate_new_secret(),
         filetype=self.filetype,
         post=post,
         size=1000,
         uploader=self.user,
         uploader_name=self.user.username,
         uploader_slug=self.user.slug,
         filename='testfile_%s.zip' % (Attachment.objects.count() + 1),
         file=None,
         image=None,
         thumbnail=None,
     )
Esempio n. 9
0
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
Esempio n. 10
0
def move_attachments(stdout, style):
    query = 'SELECT * FROM misago_attachment ORDER BY id'

    posts = []

    attachment_types = {}
    for attachment_type in AttachmentType.objects.all():
        for mimetype in attachment_type.mimetypes_list:
            attachment_types[mimetype] = attachment_type

    for attachment in fetch_assoc(query):
        if attachment['content_type'] not in attachment_types:
            stdout.write(
                style.WARNING("Skipping attachment: %s (invalid type)" %
                              attachment['name']))
            continue

        if not attachment['post_id']:
            stdout.write(
                style.WARNING("Skipping attachment: %s (orphaned)" %
                              attachment['name']))
            continue

        filetype = attachment_types[attachment['content_type']]

        post_pk = movedids.get('post', attachment['post_id'])
        post = Post.objects.get(pk=post_pk)

        if post_pk not in posts:
            posts.append(post_pk)

        uploader = None
        if attachment['user_id']:
            uploader_pk = movedids.get('user', attachment['user_id'])
            uploader = UserModel.objects.get(pk=uploader_pk)

        file_path = os.path.join(OLD_FORUM['ATTACHMENTS'], attachment['path'])
        upload = OldAttachmentFile(open(file_path, 'rb'), attachment)

        new_attachment = Attachment(
            secret=Attachment.generate_new_secret(),
            filetype=filetype,
            post=post,
            uploaded_on=localise_datetime(attachment['date']),
            uploader=uploader,
            uploader_name=attachment['user_name'],
            uploader_slug=attachment['user_name_slug'],
            uploader_ip=attachment['ip'],
            filename=attachment['name'],
            size=attachment['size'],
        )

        if attachment['content_type'] in IMAGE_TYPES:
            new_attachment.set_image(upload)
        else:
            new_attachment.set_file(upload)

        new_attachment.save()

        movedids.set('attachment', attachment['id'], new_attachment.pk)

    update_attachments_caches(posts)