From ec1213505bff64dcf2048f58b747775660ab862c Mon Sep 17 00:00:00 2001 From: Johanna England Date: Mon, 24 Jun 2024 14:29:35 +0200 Subject: [PATCH 1/4] Add API command to delete event --- changelog.d/270.added.md | 1 + src/zino/api/legacy.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 changelog.d/270.added.md diff --git a/changelog.d/270.added.md b/changelog.d/270.added.md new file mode 100644 index 00000000..82470eb4 --- /dev/null +++ b/changelog.d/270.added.md @@ -0,0 +1 @@ +Add API command to delete an event \ No newline at end of file diff --git a/src/zino/api/legacy.py b/src/zino/api/legacy.py index 48634ad1..b65a7029 100644 --- a/src/zino/api/legacy.py +++ b/src/zino/api/legacy.py @@ -17,6 +17,7 @@ from zino import version from zino.api import auth from zino.api.notify import Zino1NotificationProtocol +from zino.events import EventIndex from zino.scheduler import get_scheduler from zino.state import ZinoState, config from zino.statemodels import ( @@ -619,3 +620,21 @@ async def do_raiseerror(self): that exceptions that go unhandled by a command responder is handled by the protocol engine. """ 1 / 0 # noqa + + @requires_authentication + @Zino1ServerProtocol._translate_case_id_to_event + async def do_deleteevent(self, event: Event): + """Implements an DELETEEVENT command that did not exist in the Zino 1 protocol. This is just used for testing + the frontend. + """ + events = self._state.events + + index = EventIndex(event.router, event.subindex, type(event)) + + if events._events_by_index.get(index) and event.id == events._events_by_index[index].id: + del events._events_by_index[index] + if events._closed_events_by_index.get(index) and event.id == events._closed_events_by_index[index].id: + del events._closed_events_by_index[index] + del events.events[event.id] + + return self._respond_ok(f"event {event.id} deleted") From 67082e46b3217dd98d3a5b6fec3477e6cd573504 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Mon, 24 Jun 2024 14:29:53 +0200 Subject: [PATCH 2/4] Add tests for delete event API command --- tests/api/legacy_test.py | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/api/legacy_test.py b/tests/api/legacy_test.py index e5f0b6d1..f18ff2b2 100644 --- a/tests/api/legacy_test.py +++ b/tests/api/legacy_test.py @@ -25,6 +25,8 @@ ) from zino.time import now +DEVICE_NAME = "example-gw.example.org" + class TestZino1BaseServerProtocol: def test_should_init_without_error(self): @@ -892,6 +894,55 @@ async def test_when_authenticated_should_list_all_pm_ids(self, authenticated_pro assert re.search(pattern_string.format(id), response), f"Expected response to contain id {id}" +class TestZino1TestProtocolDeleteEventCommand: + @pytest.mark.asyncio + async def test_should_delete_open_event(self): + protocol = ZinoTestProtocol() + fake_transport = Mock() + protocol.connection_made(fake_transport) + protocol.user = "foo" + fake_transport.write = Mock() + + event = ReachabilityEvent(router=DEVICE_NAME, state=EventState.OPEN) + protocol._state.events.commit(event=event) + + command = f"DELETEEVENT {event.id}" + await protocol.message_received(command) + + assert fake_transport.write.called + response = fake_transport.write.call_args[0][0].decode("utf-8") + assert response.startswith("200 ") + assert event.id not in protocol._state.events.events.keys() + assert not protocol._state.events.get(device_name=DEVICE_NAME, subindex=None, event_class=ReachabilityEvent) + assert not protocol._state.events.get_closed_event( + device_name=DEVICE_NAME, subindex=None, event_class=ReachabilityEvent + ) + + @pytest.mark.asyncio + async def test_should_delete_closed_event(self): + protocol = ZinoTestProtocol() + fake_transport = Mock() + protocol.connection_made(fake_transport) + protocol.user = "foo" + fake_transport.write = Mock() + + event = ReachabilityEvent(router=DEVICE_NAME, state=EventState.CLOSED) + protocol._state.events.commit(event=event) + + command = f"DELETEEVENT {event.id}" + await protocol.message_received(command) + + assert fake_transport.write.called + response = fake_transport.write.call_args[0][0].decode("utf-8") + assert response.startswith("200 ") + assert response.startswith("200 ") + assert event.id not in protocol._state.events.events.keys() + assert not protocol._state.events.get(device_name=DEVICE_NAME, subindex=None, event_class=ReachabilityEvent) + assert not protocol._state.events.get_closed_event( + device_name=DEVICE_NAME, subindex=None, event_class=ReachabilityEvent + ) + + def test_requires_authentication_should_set_function_attribute(): @requires_authentication def throwaway(): From 9393fa79e45eb28d28bcc3712d955edcfd22acba Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 15 Aug 2024 10:28:52 +0200 Subject: [PATCH 3/4] Update src/zino/api/legacy.py Co-authored-by: stveit <31960753+stveit@users.noreply.github.com> --- src/zino/api/legacy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zino/api/legacy.py b/src/zino/api/legacy.py index b65a7029..500b61e9 100644 --- a/src/zino/api/legacy.py +++ b/src/zino/api/legacy.py @@ -631,9 +631,9 @@ async def do_deleteevent(self, event: Event): index = EventIndex(event.router, event.subindex, type(event)) - if events._events_by_index.get(index) and event.id == events._events_by_index[index].id: + if index in events._events_by_index and event.id == events._events_by_index[index].id: del events._events_by_index[index] - if events._closed_events_by_index.get(index) and event.id == events._closed_events_by_index[index].id: + if index in events._closed_events_by_index and event.id == events._closed_events_by_index[index].id: del events._closed_events_by_index[index] del events.events[event.id] From 8698dc8315b1b6c680b4bfba31426b77bb91befc Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 15 Aug 2024 10:29:48 +0200 Subject: [PATCH 4/4] Remove duplicate line --- tests/api/legacy_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/api/legacy_test.py b/tests/api/legacy_test.py index f18ff2b2..1c01f97a 100644 --- a/tests/api/legacy_test.py +++ b/tests/api/legacy_test.py @@ -935,7 +935,6 @@ async def test_should_delete_closed_event(self): assert fake_transport.write.called response = fake_transport.write.call_args[0][0].decode("utf-8") assert response.startswith("200 ") - assert response.startswith("200 ") assert event.id not in protocol._state.events.events.keys() assert not protocol._state.events.get(device_name=DEVICE_NAME, subindex=None, event_class=ReachabilityEvent) assert not protocol._state.events.get_closed_event(