Skip to content

Commit 54a6f16

Browse files
committed
Merge branch 'develop' into dev-r85-v2-pull
2 parents 3a51545 + d19d5d1 commit 54a6f16

File tree

17 files changed

+448
-142
lines changed

17 files changed

+448
-142
lines changed

server/Pipfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ flask-migrate = "==2.6.0" # 3.1.0
2626
wtforms-json = "==0.3.5"
2727
pytz = "==2022.2.1"
2828
scikit-build = "==0.18.1"
29-
pygeodiff = "==1.0.6"
29+
pygeodiff = "==2.0.4"
3030
pathvalidate = "==3.2.0"
3131
celery= "==5.4.0"
3232
redis= "==5.0.1"
@@ -40,6 +40,7 @@ psycogreen = "==1.0.2"
4040
importlib-metadata = "==8.4.0" # https://github.com/pallets/flask/issues/4502
4141
typing_extensions = "==4.12.2"
4242
python-magic = "==0.4.27"
43+
click = "==8.2.0"
4344
# requirements for development on windows
4445
colorama = "==0.4.5"
4546

server/Pipfile.lock

Lines changed: 77 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/mergin/auth/forms.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (C) Lutra Consulting Limited
22
#
33
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
4+
45
import re
56
import safe
67
from flask_wtf import FlaskForm
@@ -48,18 +49,22 @@ class ExtendedEmail(Email):
4849
1. spaces,
4950
2. special characters ,:;()<>[]\"
5051
3, multiple @ symbols,
51-
4, leading, trailing, or consecutive dots in the local part
52-
5, invalid domain part - missing top level domain (user@example), consecutive dots
53-
Custom check for additional invalid characters disallows |'— because they make our email sending service to fail
52+
4, leading, trailing, or consecutive dots in the local part,
53+
5, invalid domain part - missing top level domain (user@example), consecutive dots,
54+
The extended validation checks email addresses using the regex provided by Brevo,
55+
so that we stay consistent with their validation rules and avoid API failures.
5456
"""
5557

5658
def __call__(self, form, field):
5759
super().__call__(form, field)
5860

59-
if re.search(r"[|'—]", field.data):
60-
raise ValidationError(
61-
f"Email address '{field.data}' contains an invalid character."
62-
)
61+
email = field.data.strip()
62+
63+
pattern = r"^[\x60#&*\/=?^{!}~'+\w-]+(\.[\x60#&*\/=?^{!}~'+\w-]+)*\.?@([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*\.)[a-zA-Z0-9-]*[a-zA-Z0-9]{2,}$"
64+
email_regexp = re.compile(pattern, re.IGNORECASE)
65+
66+
if not email_regexp.match(email):
67+
raise ValidationError(f"Email address '{email}' is invalid.")
6368

6469

6570
class PasswordValidator:

server/mergin/sync/files.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
from .utils import (
2222
is_file_name_blacklisted,
23-
is_qgis,
2423
is_supported_extension,
2524
is_valid_path,
2625
is_versioned_file,
26+
has_trailing_space,
2727
)
2828
from ..app import DateTimeWithZ, ma
2929

@@ -219,14 +219,21 @@ def validate(self, data, **kwargs):
219219

220220
if not is_valid_path(file_path):
221221
raise ValidationError(
222-
f"Unsupported file name detected: {file_path}. Please remove the invalid characters."
222+
f"Unsupported file name detected: '{file_path}'. Please remove the invalid characters."
223223
)
224224

225225
if not is_supported_extension(file_path):
226226
raise ValidationError(
227-
f"Unsupported file type detected: {file_path}. "
227+
f"Unsupported file type detected: '{file_path}'. "
228228
f"Please remove the file or try compressing it into a ZIP file before uploading.",
229229
)
230+
# new checks must restrict only new files not to block existing projects
231+
for file in data["added"]:
232+
file_path = file["path"]
233+
if has_trailing_space(file_path):
234+
raise ValidationError(
235+
f"Folder name contains a trailing space. Please remove the space in: '{file_path}'."
236+
)
230237

231238

232239
class ProjectFileSchema(FileSchema):
@@ -239,7 +246,7 @@ class ProjectFileSchema(FileSchema):
239246
def patch_field(self, data, **kwargs):
240247
# drop 'diff' key entirely if empty or None as clients would expect
241248
if not data.get("diff"):
242-
data.pop("diff")
249+
data.pop("diff", None)
243250
return data
244251

245252

server/mergin/sync/public_api_controller.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@
7979
get_user_agent,
8080
generate_location,
8181
is_valid_uuid,
82-
gpkg_wkb_to_wkt,
8382
get_device_id,
8483
prepare_download_response,
84+
get_device_id,
85+
wkb2wkt,
8586
)
8687
from .errors import StorageLimitHit, ProjectLocked
8788
from ..utils import format_time_delta
@@ -944,7 +945,7 @@ def push_finish(transaction_id):
944945
if len(unsupported_files):
945946
abort(
946947
400,
947-
f"Unsupported file type detected: {unsupported_files[0]}. "
948+
f"Unsupported file type detected: '{unsupported_files[0]}'. "
948949
f"Please remove the file or try compressing it into a ZIP file before uploading.",
949950
)
950951

@@ -1000,14 +1001,6 @@ def push_finish(transaction_id):
10001001
# let's move uploaded files where they are expected to be
10011002
os.renames(files_dir, version_dir)
10021003

1003-
# remove used chunks
1004-
for file in upload.changes["added"] + upload.changes["updated"]:
1005-
file_chunks = file.get("chunks", [])
1006-
for chunk_id in file_chunks:
1007-
chunk_file = os.path.join(upload.upload_dir, "chunks", chunk_id)
1008-
if os.path.exists(chunk_file):
1009-
move_to_tmp(chunk_file)
1010-
10111004
logging.info(
10121005
f"Push finished for project: {project.id}, project version: {v_next_version}, transaction id: {transaction_id}."
10131006
)
@@ -1300,7 +1293,10 @@ def get_resource_changeset(project_name, namespace, version_id, path): # noqa:
13001293
if key not in geom_change:
13011294
continue
13021295
gpkg_wkb = base64.b64decode(geom_change[key], validate=True)
1303-
wkt = gpkg_wkb_to_wkt(gpkg_wkb)
1296+
wkb = version.project.storage.geodiff.create_wkb_from_gpkg_header(
1297+
gpkg_wkb
1298+
)
1299+
wkt = wkb2wkt(wkb)
13041300
if wkt:
13051301
geom_change[key] = wkt
13061302
except (binascii.Error, TypeError, ValueError):

0 commit comments

Comments
 (0)