Skip to content

Commit a23dab2

Browse files
author
Andrei Neagu
committed
ensure same parent is in palce
1 parent 14dc446 commit a23dab2

File tree

4 files changed

+41
-2
lines changed

4 files changed

+41
-2
lines changed

services/storage/src/simcore_service_storage/exceptions/errors.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from common_library.errors_classes import OsparcErrorMixin
22

33

4-
class StorageRuntimeError(OsparcErrorMixin, RuntimeError):
5-
...
4+
class StorageRuntimeError(OsparcErrorMixin, RuntimeError): ...
65

76

87
class ConfigurationError(StorageRuntimeError):
@@ -45,3 +44,7 @@ class InvalidFileIdentifierError(AccessLayerError):
4544

4645
class DatCoreCredentialsMissingError(StorageRuntimeError):
4746
msg_template: str = "DatCore credentials are incomplete. TIP: Check your settings"
47+
48+
49+
class SelectionNotAllowedError(StorageRuntimeError):
50+
msg_template: str = "Selection='{selection}' must share the same parent folder"

services/storage/src/simcore_service_storage/simcore_s3_dsm.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
LinkAlreadyExistsError,
6262
ProjectAccessRightError,
6363
ProjectNotFoundError,
64+
SelectionNotAllowedError,
6465
)
6566
from .models import (
6667
DatasetMetaData,
@@ -85,6 +86,7 @@
8586
compute_file_id_prefix,
8687
create_and_upload_export,
8788
create_random_export_name,
89+
ensure_same_paret_in_user_selection,
8890
expand_directory,
8991
get_accessible_project_ids,
9092
get_directory_file_id,
@@ -1252,6 +1254,10 @@ async def create_s3_export(
12521254
) -> StorageFileID:
12531255
source_object_keys: set[tuple[UserSelection, StorageFileID]] = set()
12541256

1257+
# ensure all selected items have the same parent
1258+
if not ensure_same_paret_in_user_selection(object_keys):
1259+
raise SelectionNotAllowedError(selection=object_keys)
1260+
12551261
# check access rights
12561262
for object_key in object_keys:
12571263
project_id = None

services/storage/src/simcore_service_storage/utils/simcore_s3_dsm_utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ def create_random_export_name(user_id: UserID) -> StorageFileID:
145145
)
146146

147147

148+
def ensure_same_paret_in_user_selection(object_keys: list[S3ObjectKey]) -> bool:
149+
parents = [Path(x).parent for x in object_keys]
150+
return len(set(parents)) <= 1
151+
152+
148153
UserSelection: TypeAlias = str
149154

150155

services/storage/tests/unit/test_simcore_s3_dsm_utils.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
UserSelection,
77
_strip_parent,
88
compute_file_id_prefix,
9+
ensure_same_paret_in_user_selection,
910
)
1011

1112

@@ -46,3 +47,27 @@ def test__strip_parent(selection: Path, s3_object: Path, expected: str):
4647
_strip_parent(UserSelection(f"{selection}"), S3ObjectKey(f"{s3_object}"))
4748
== expected
4849
)
50+
51+
52+
@pytest.mark.parametrize(
53+
"user_slection, expected",
54+
[
55+
([], True),
56+
(["folder"], True),
57+
(["folder", "folder"], True),
58+
(["", ""], True),
59+
([""], True),
60+
([_FOLDERS_PATH / "a", _FOLDERS_PATH / "b"], True),
61+
(["a.txt", "b.txt"], True),
62+
(["a/a.txt"], True),
63+
# not same parent
64+
(["firsta/file", "second/file"], False),
65+
(["a/a.txt", "a.txt", "c.txt", "a/d.txt"], False),
66+
],
67+
)
68+
def test_ensure_same_paret_in_user_selection(
69+
user_slection: list[S3ObjectKey | Path], expected: bool
70+
):
71+
assert (
72+
ensure_same_paret_in_user_selection([f"{x}" for x in user_slection]) == expected
73+
)

0 commit comments

Comments
 (0)