1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-11 16:01:20 +00:00

Merge branch '291-fixed-bug-where-the-backend-would-fail-hard-if-a-too-long-file-name-is-provided' into 'develop'

Resolve "Fixed bug where the backend would fail hard if a too long file name is provided"

Closes 

See merge request 
This commit is contained in:
Bram Wiepjes 2021-02-08 20:45:43 +00:00
commit 1f894cec85
6 changed files with 77 additions and 3 deletions
backend
src/baserow/core
tests/baserow/core
changelog.md
docs/getting-started

View file

@ -12,7 +12,7 @@ from django.conf import settings
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import SimpleUploadedFile
from baserow.core.utils import sha256_hash, stream_size, random_string
from baserow.core.utils import sha256_hash, stream_size, random_string, truncate_middle
from .exceptions import (
InvalidFileStreamError, FileSizeTooLargeError, FileURLCouldNotBeReached,
@ -171,6 +171,7 @@ class UserFileHandler:
storage = storage or default_storage
hash = sha256_hash(stream)
file_name = truncate_middle(file_name, 64)
try:
return UserFile.objects.get(original_name=file_name, sha256_hash=hash)

View file

@ -3,6 +3,7 @@ import re
import random
import string
import hashlib
import math
from collections import namedtuple
@ -213,3 +214,38 @@ def stream_size(stream):
size = stream.tell()
stream.seek(0)
return size
def truncate_middle(content, max_length, middle='...'):
"""
Truncates the middle part of the string if the total length if too long.
For example:
truncate_middle('testabcdecho', 8) == 'tes...ho'
:param content: The string that must be truncated.
:type: str
:param max_length: The maximum amount of characters the string can have.
:type max_length: int
:param middle: The part that must be added in the middle if the provided
content is too long.
:type middle str
:return: The truncated string.
:rtype: str
"""
if len(content) <= max_length:
return content
if max_length <= len(middle):
raise ValueError('The max_length cannot be lower than the length if the '
'middle string.')
total = max_length - len(middle)
start = math.ceil(total / 2)
end = math.floor(total / 2)
left = content[:start]
right = content[-end:] if end else ''
return f'{left}{middle}{right}'

View file

@ -1,9 +1,10 @@
from io import BytesIO
import pytest
from baserow.core.utils import (
extract_allowed, set_allowed_attrs, to_pascal_case, to_snake_case,
remove_special_characters, dict_to_object, random_string, sha256_hash,
stream_size
stream_size, truncate_middle
)
@ -77,3 +78,19 @@ def test_sha256_hash():
def test_stream_size():
assert stream_size(BytesIO(b'test')) == 4
def test_truncate_middle():
assert truncate_middle('testtesttest', 13) == 'testtesttest'
assert truncate_middle('testtesttest', 12) == 'testtesttest'
assert truncate_middle('testabcdecho', 11) == 'test...echo'
assert truncate_middle('testabcdecho', 10) == 'test...cho'
assert truncate_middle('testabcdecho', 9) == 'tes...cho'
assert truncate_middle('testabcdecho', 8) == 'tes...ho'
assert truncate_middle('testabcdecho', 7) == 'te...ho'
assert truncate_middle('testabcdecho', 6) == 'te...o'
assert truncate_middle('testabcdecho', 5) == 't...o'
assert truncate_middle('testabcdecho', 4) == 't...'
with pytest.raises(ValueError):
truncate_middle('testtesttest', 3) == '...'

View file

@ -238,6 +238,20 @@ def test_upload_user_file(data_fixture, tmpdir):
assert UserFile.objects.all().count() == 7
image = Image.new('RGB', (1, 1), color='red')
image_bytes = BytesIO()
image.save(image_bytes, format='PNG')
user_file = handler.upload_user_file(
user,
'this_file_has_an_extreme_long_file_name_that_should_not_make_the_system_'
'fail_hard_when_trying_to_upload.png',
image_bytes,
storage=storage
)
assert user_file.original_name == 'this_file_has_an_extreme_long_f...hard_when_' \
'trying_to_upload.png'
@pytest.mark.django_db
@responses.activate

View file

@ -2,6 +2,7 @@
## Unreleased
* Fixed error when a very long user file name is provided when uploading.
* Upgraded DRF Spectacular dependency to the latest version.
* Added single select field form option validation.
* Changed all cookies to SameSite=lax.

View file

@ -5,7 +5,12 @@ Baserow is divided into two components, the **backend** and the
contains some documentation about those endpoints and how to use them. These endpoints
should never be used to show data on your own website because that would mean you have
to expose your credentials or JWT token. They should only be used the make changes in
in your data. In the future there are going to be features that enable you to expose
in your data. You can publicly expose your data in a safe way by creating a
[database token](https://api.baserow.io/api/redoc/#operation/create_database_token)
token, set the permissions and follow the automatically generated api docs at
https://baserow.io/api/docs.
In the future there are going to be features that enable you to expose
your data publicly in a safe way.
## OpenAPI spec