Skip to content

Commit 32d4c8d

Browse files
Yuri ZmytrakovYuri Zmytrakov
authored andcommitted
feat: Adding a key for technical/private data in SFEOS
1 parent 1315ced commit 32d4c8d

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PRIVATE_FIELDS = [
2+
"product_location"
3+
]

stac_fastapi/core/stac_fastapi/core/serializers.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,30 @@
1414
from stac_fastapi.types import stac as stac_types
1515
from stac_fastapi.types.links import ItemLinks, resolve_links
1616

17+
from .private_fields_config import PRIVATE_FIELDS
18+
1719
logger = logging.getLogger(__name__)
1820

1921

22+
def filter_private_fields(data: dict) -> dict:
23+
"""Remove private fields from data dictionary."""
24+
if not PRIVATE_FIELDS:
25+
return data
26+
27+
filtered_data = deepcopy(data)
28+
29+
for field in PRIVATE_FIELDS:
30+
if field in filtered_data:
31+
del filtered_data[field]
32+
33+
if "properties" in filtered_data and isinstance(filtered_data["properties"], dict):
34+
for field in PRIVATE_FIELDS:
35+
if field in filtered_data["properties"]:
36+
del filtered_data["properties"][field]
37+
38+
return filtered_data
39+
40+
2041
@attr.s
2142
class Serializer(abc.ABC):
2243
"""Defines serialization methods between the API and the data model.
@@ -92,6 +113,7 @@ def db_to_stac(cls, item: dict, base_url: str) -> stac_types.Item:
92113
Returns:
93114
stac_types.Item: The STAC item object.
94115
"""
116+
item = filter_private_fields(item)
95117
item_id = item["id"]
96118
collection_id = item["collection"]
97119
item_links = ItemLinks(
@@ -168,6 +190,7 @@ def db_to_stac(
168190
Returns:
169191
stac_types.Collection: The STAC collection object.
170192
"""
193+
collection = filter_private_fields(collection)
171194
# Avoid modifying the input dict in-place ... doing so breaks some tests
172195
collection = deepcopy(collection)
173196

stac_fastapi/tests/resources/test_collection.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,36 @@ async def test_links_collection(app_client, ctx, txn_client):
229229
len([link for link in response.json()["links"] if link["rel"] == "license"])
230230
== 1
231231
)
232+
233+
234+
@pytest.mark.asyncio
235+
async def test_private_fields_excluded_from_collection(
236+
app_client, txn_client, load_test_data, monkeypatch
237+
):
238+
"""Test that private fields are excluded from collection API responses."""
239+
monkeypatch.setattr(
240+
"stac_fastapi.core.serializers.PRIVATE_FIELDS", ["test_field", "internal_data"]
241+
)
242+
243+
test_collection = load_test_data("test_collection.json")
244+
test_collection["id"] = "test-private-fields-collection"
245+
246+
test_collection["test_field"] = "this should be hidden in collection"
247+
test_collection["internal_data"] = {"secret": "confidential collection info"}
248+
test_collection["description"] = "This should be visible"
249+
250+
await create_collection(txn_client, test_collection)
251+
await refresh_indices(txn_client)
252+
253+
resp = await app_client.get(f"/collections/{test_collection['id']}")
254+
assert resp.status_code == 200
255+
256+
collection_data = resp.json()
257+
258+
assert "test_field" not in collection_data
259+
assert "internal_data" not in collection_data
260+
261+
assert "description" in collection_data
262+
assert collection_data["description"] == "This should be visible"
263+
assert "id" in collection_data
264+
assert "title" in collection_data

stac_fastapi/tests/resources/test_item.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,3 +1163,39 @@ async def test_search_datetime_with_null_datetime(
11631163
await txn_client.delete_collection(test_collection["id"])
11641164
except Exception as e:
11651165
logger.warning(f"Failed to delete collection: {e}")
1166+
1167+
1168+
@pytest.mark.asyncio
1169+
async def test_private_fields_excluded_from_item(
1170+
app_client, txn_client, load_test_data, monkeypatch
1171+
):
1172+
"""Test that private fields are excluded from item API responses."""
1173+
monkeypatch.setattr(
1174+
"stac_fastapi.core.serializers.PRIVATE_FIELDS", ["test_field", "internal_data"]
1175+
)
1176+
1177+
test_collection = load_test_data("test_collection.json")
1178+
test_item = load_test_data("test_item.json")
1179+
1180+
test_collection["id"] = "test-private-fields-collection"
1181+
test_item["collection"] = test_collection["id"]
1182+
test_item["id"] = "test-private-fields-item"
1183+
1184+
test_item["test_field"] = "test field to be hidden"
1185+
test_item["internal_data"] = {"secret": "confidential"}
1186+
1187+
await create_collection(txn_client, test_collection)
1188+
1189+
await create_item(txn_client, test_item)
1190+
await refresh_indices(txn_client)
1191+
1192+
resp = await app_client.get(
1193+
f"/collections/{test_item['collection']}/items/{test_item['id']}"
1194+
)
1195+
item_data = resp.json()
1196+
1197+
assert "test_field" not in item_data
1198+
assert "internal_data" not in item_data
1199+
1200+
assert "id" in item_data
1201+
assert item_data["id"] == "test-private-fields-item"

0 commit comments

Comments
 (0)