From 624cc42d100aa40e376659e3051f77029f2c5bbd Mon Sep 17 00:00:00 2001 From: nilbacardit26 Date: Mon, 21 Oct 2024 17:22:22 +0200 Subject: [PATCH] adding metadata as an object --- CHANGELOG.rst | 4 +- guillotina_audit/__init__.py | 5 ++- guillotina_audit/commands/__init__.py | 0 guillotina_audit/commands/mappings.py | 24 ++++++++++++ guillotina_audit/models.py | 1 + guillotina_audit/tests/test_audit_basic.py | 43 ++++++++++++++++++++++ guillotina_audit/tests/test_mappings.py | 19 ++++++++++ guillotina_audit/utility.py | 7 ++++ 8 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 guillotina_audit/commands/__init__.py create mode 100644 guillotina_audit/commands/mappings.py create mode 100644 guillotina_audit/tests/test_mappings.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e64482d..18e8fe6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,9 @@ 2.0.5 (unreleased) ------------------ -- Nothing changed yet. +- Adding metadata field as an object +- Adding command audit-update-mappings to update mappings + [nilbacardit26] 2.0.4 (2024-08-02) diff --git a/guillotina_audit/__init__.py b/guillotina_audit/__init__.py index 2dbf4f6..d9655a0 100644 --- a/guillotina_audit/__init__.py +++ b/guillotina_audit/__init__.py @@ -12,7 +12,10 @@ "index_permission_changes": False, }, } - } + }, + "commands": { + "audit-update-mappings": "guillotina_audit.commands.mappings.UpdateMappingsCommand" + }, } diff --git a/guillotina_audit/commands/__init__.py b/guillotina_audit/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/guillotina_audit/commands/mappings.py b/guillotina_audit/commands/mappings.py new file mode 100644 index 0000000..32ca0ee --- /dev/null +++ b/guillotina_audit/commands/mappings.py @@ -0,0 +1,24 @@ +from guillotina.commands import Command +from guillotina.component import get_utility +from guillotina.interfaces import ICatalogUtility + +import asyncio +import logging + + +logger = logging.getLogger("guillotina_elasticsearch") + + +class UpdateMappingsCommand(Command): + description = "Update Mappings Command" + migrator = None + reindexer = None + + def get_parser(self): + parser = super(UpdateMappingsCommand, self).get_parser() + return parser + + async def run(self, arguments, settings, app): + search = get_utility(ICatalogUtility) + await asyncio.sleep(1) + await search.update_mappings() diff --git a/guillotina_audit/models.py b/guillotina_audit/models.py index 7dc2417..8ad8962 100644 --- a/guillotina_audit/models.py +++ b/guillotina_audit/models.py @@ -16,6 +16,7 @@ class AuditDocument(BaseModel): creator: Optional[str] = None creation_date: datetime = Field(default=datetime.now(timezone.utc)) type_name: Optional[str] = None + metadata: Optional[dict] = None @field_serializer("payload") def serialize_payload(self, payload: dict, _info): diff --git a/guillotina_audit/tests/test_audit_basic.py b/guillotina_audit/tests/test_audit_basic.py index 71e6807..80a4d3d 100644 --- a/guillotina_audit/tests/test_audit_basic.py +++ b/guillotina_audit/tests/test_audit_basic.py @@ -329,3 +329,46 @@ async def test_permissions_modified_with_indexing(guillotina_es): # There should be one more document since indexing_permission_changes is True assert len(resp["hits"]["hits"]) == 3 assert resp["hits"]["hits"][-1]["_source"]["action"] == "permissions_changed" + + +async def test_metadata_field(guillotina_es): + response, status = await guillotina_es( + "POST", "/db/guillotina/@addons", data=json.dumps({"id": "audit"}) + ) + assert status == 200 + await asyncio.sleep(2) + audit_utility = query_utility(IAuditUtility) + payload = AuditDocument( + action="CreatingMetadata", + metadata={ + "foo_number": 120, + "foo_string": "foo_string", + "foo_boolean": True, + "foo_list": [1, 2, 3, 4], + "foo_dict": { + "foo_number": 100, + "foo_string": "foo_string", + "foo_dict": {"foo_key": "foo_value"}, + }, + }, + ) + audit_utility.log_wildcard(payload) + # Let's check the index has been created + resp = await audit_utility.async_es.indices.get_alias() + await asyncio.sleep(2) + resp, status = await guillotina_es( + "GET", + "/db/guillotina/@audit?action=CreatingMetadata", + ) + assert resp["hits"]["hits"][0]["_source"]["action"] == "CreatingMetadata" + assert resp["hits"]["hits"][0]["_source"]["metadata"] == { + "foo_boolean": True, + "foo_dict": { + "foo_dict": {"foo_key": "foo_value"}, + "foo_number": 100, + "foo_string": "foo_string", + }, + "foo_list": [1, 2, 3, 4], + "foo_number": 120, + "foo_string": "foo_string", + } diff --git a/guillotina_audit/tests/test_mappings.py b/guillotina_audit/tests/test_mappings.py new file mode 100644 index 0000000..bce45c6 --- /dev/null +++ b/guillotina_audit/tests/test_mappings.py @@ -0,0 +1,19 @@ +from guillotina.component import query_utility +from guillotina_audit.interfaces import IAuditUtility + +import asyncio +import json +import pytest + + +pytestmark = pytest.mark.asyncio + + +async def test_mappings(guillotina_es): + response, status = await guillotina_es( + "POST", "/db/guillotina/@addons", data=json.dumps({"id": "audit"}) + ) + assert status == 200 + await asyncio.sleep(2) + audit_utility = query_utility(IAuditUtility) + await audit_utility.update_mappings() diff --git a/guillotina_audit/utility.py b/guillotina_audit/utility.py index e900c19..0e17bc0 100644 --- a/guillotina_audit/utility.py +++ b/guillotina_audit/utility.py @@ -41,6 +41,12 @@ def _custom_serializer(self, obj): return obj.strftime("%Y-%m-%d") raise TypeError("Object of type %s is not JSON serializable" % type(obj)) + async def update_mappings(self): + await self.async_es.indices.put_mapping( + body=self.default_mappings(), index=self.index + ) + logger.info(f"Updating mappings {self.default_mappings()}") + async def create_index(self): try: await self.async_es.indices.create( @@ -76,6 +82,7 @@ def default_mappings(self): "creator": {"type": "keyword"}, "creation_date": {"type": "date", "store": True}, "payload": {"type": "text", "store": True}, + "metadata": {"type": "object", "dynamic": True}, }, }