Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion api/howler/odm/models/ecs/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ class Related(odm.Model):
)

# Extra fields not defined in ECS but added for outline purposes
id = odm.Optional(odm.Keyword(description="The id related to the event."))
id = odm.Optional(
odm.Keyword(
description="The id related to the event.",
deprecated=True,
deprecated_description="related.ids should be used instead of related.id.",
)
)

uri = odm.Optional(odm.List(odm.URI(), description="All of the URIs related to the event."))

Expand All @@ -43,3 +49,20 @@ class Related(odm.Model):
description="All the signatures/rules that were triggered by the event.",
)
)

def __init__(self, data: dict = None, *args, **kwargs):
if data and "id" in data and data["id"] is not None:
existing_ids = data.get("ids")
if isinstance(existing_ids, list):
merged_ids = list(existing_ids)
elif existing_ids is None:
merged_ids = []
else:
merged_ids = [existing_ids]

if data["id"] not in merged_ids:
merged_ids.append(data["id"])

data["ids"] = merged_ids

super().__init__(data, *args, **kwargs)
Comment thread
Copilot marked this conversation as resolved.
23 changes: 23 additions & 0 deletions api/test/unit/odm/test_related.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from howler.odm.models.ecs.related import Related
from howler.odm.models.hit import Hit


class TestRelated:
def test_related_id_is_copied_to_ids(self):
related = Related({"id": "indicator-1"})

assert related.id == "indicator-1"
assert related.ids == ["indicator-1"]

def test_related_id_merges_into_existing_ids_without_duplicates(self):
related = Related({"id": "indicator-2", "ids": ["indicator-1", "indicator-2"]})

assert related.id == "indicator-2"
assert related.ids == ["indicator-1", "indicator-2"]

def test_parent_odm_related_id_key_is_copied_to_related_ids(self):
hit = Hit({"howler.analytic": "Test Analytic", "howler.hash": "a", "related.id": "indicator-3"})

assert hit.related is not None
assert hit.related.id == "indicator-3"
assert hit.related.ids == ["indicator-3"]
Comment thread
Copilot marked this conversation as resolved.
Loading