diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 295dd7c..8f9a8b9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,8 @@ 2.0.1 (unreleased) ------------------ -- Nothing changed yet. +- Being able to decode dates and datetimes when indexing custom + payloads from events. 2.0.0 (2024-01-23) diff --git a/guillotina_audit/tests/fixtures.py b/guillotina_audit/tests/fixtures.py index bd865bd..e186b7d 100644 --- a/guillotina_audit/tests/fixtures.py +++ b/guillotina_audit/tests/fixtures.py @@ -18,6 +18,7 @@ def base_settings_configurator(settings): settings["applications"] = [] settings["applications"].append("guillotina") settings["applications"].append("guillotina_audit") + settings["applications"].append("guillotina_audit.tests.test_package") settings["audit"] = { "connection_settings": { "hosts": [f"http://{annotations['elasticsearch']['host']}"] diff --git a/guillotina_audit/tests/test_audit_basic.py b/guillotina_audit/tests/test_audit_basic.py index 627bdbb..99a9912 100644 --- a/guillotina_audit/tests/test_audit_basic.py +++ b/guillotina_audit/tests/test_audit_basic.py @@ -1,3 +1,4 @@ +from datetime import date from datetime import datetime from datetime import timedelta from guillotina.component import query_utility @@ -125,6 +126,24 @@ async def test_audit_basic(guillotina_es): assert len(resp["hits"]["hits"]) == 1 assert status == 200 + response, status = await guillotina_es( + "POST", + "/db/guillotina/", + data=json.dumps( + { + "@type": "Item", + "id": "foo_item", + "title": "Foo Item", + "guillotina.behaviors.dublincore.IDublinCore": { + "effective_date": "2023-01-01" + }, + } + ), + ) + assert status == 201 + await asyncio.sleep(2) + resp, status = await guillotina_es("GET", "/db/guillotina/@audit") + async def test_audit_wildcard(guillotina_es): response, status = await guillotina_es( @@ -192,3 +211,16 @@ async def test_audit_wildcard(guillotina_es): assert resp["hits"]["hits"][0]["_source"]["creation_date"].startswith( "2023-05-12T21:45:32" ) + + +async def test_json_dumps(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) + json.dumps( + {"datetime": datetime.now(), "date": date.today()}, + default=audit_utility._custom_serializer, + ) diff --git a/guillotina_audit/tests/test_package.py b/guillotina_audit/tests/test_package.py new file mode 100644 index 0000000..b8bb974 --- /dev/null +++ b/guillotina_audit/tests/test_package.py @@ -0,0 +1,27 @@ +from guillotina import configure +from guillotina.content import Resource +from guillotina.interfaces import IContainer +from guillotina.interfaces import IResource +from guillotina.schema import Datetime +from zope.interface import implementer + + +class IFooContent(IResource): + foo_datetime = Datetime(title="Foo Datetime") + + +@implementer(IFooContent) +class FooContent(Resource): + pass + + +configure.register_configuration( + FooContent, + dict( + context=IContainer, + schema=IFooContent, + type_name="FooContent", + behaviors=["guillotina.behaviors.dublincore.IDublinCore"], + ), + "contenttype", +) diff --git a/guillotina_audit/utility.py b/guillotina_audit/utility.py index d022e4b..b7f3765 100644 --- a/guillotina_audit/utility.py +++ b/guillotina_audit/utility.py @@ -33,6 +33,13 @@ async def initialize(self, app): **app_settings.get("audit", {}).get("connection_settings") ) + def _custom_serializer(self, obj): + if isinstance(obj, datetime.datetime): + return obj.strftime("%Y-%m-%d %H:%M:%S") + if isinstance(obj, datetime.date): + return obj.strftime("%Y-%m-%d") + raise TypeError("Object of type %s is not JSON serializable" % type(obj)) + async def create_index(self): try: await self.async_es.indices.create( @@ -91,12 +98,16 @@ def log_entry(self, obj, event): document["action"] = "modified" document["creation_date"] = obj.modification_date if self._settings.get("save_payload", False) is True: - document["payload"] = json.dumps(event.payload) + document["payload"] = json.dumps( + event.payload, default=self._custom_serializer + ) elif IObjectAddedEvent.providedBy(event): document["action"] = "added" document["creation_date"] = obj.creation_date if self._settings.get("save_payload", False) is True: - document["payload"] = json.dumps(event.payload) + document["payload"] = json.dumps( + event.payload, default=self._custom_serializer + ) elif IObjectRemovedEvent.providedBy(event): document["action"] = "removed" document["creation_date"] = datetime.datetime.now(timezone.utc)