Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/basic message deletion #52

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
20 changes: 20 additions & 0 deletions basicmessage_storage/basicmessage_storage/v1_0/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
INDY_ISO8601_DATETIME_VALIDATE,
)
from marshmallow import fields
from aries_cloudagent.storage.base import BaseStorage


class BasicMessageRecord(BaseRecord):
Expand Down Expand Up @@ -62,6 +63,25 @@ def record_tags(self) -> dict:
"""Get tags for record."""
return {"connection_id": self.connection_id, "message_id": self.message_id}


async def delete_record(self, session: ProfileSession):
"""Perform connection record deletion actions.

Args:
session (ProfileSession): session

"""
await super().delete_record(session)

# Delete metadata
if self.message_id:
storage = session.inject(BaseStorage)
await storage.delete_all_records(
self.RECORD_TYPE,
{"message_id": self.message_id},
)


@classmethod
async def retrieve_by_message_id(
cls, session: ProfileSession, message_id: str
Expand Down
42 changes: 42 additions & 0 deletions basicmessage_storage/basicmessage_storage/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from aries_cloudagent.messaging.models.base import BaseModelError
from aries_cloudagent.messaging.models.openapi import OpenAPISchema
from aries_cloudagent.messaging.util import time_now, str_to_epoch
from aries_cloudagent.messaging.valid import UUID4_EXAMPLE
from aries_cloudagent.multitenant.error import WalletKeyMissingError
from aries_cloudagent.protocols.basicmessage.v1_0.message_types import SPEC_URI
from aries_cloudagent.protocols.basicmessage.v1_0.routes import (
Expand Down Expand Up @@ -60,6 +61,18 @@ class BasicMessageListSchema(OpenAPISchema):
description="List of basic message records",
)

class BasicMessageIdMatchInfoSchema(OpenAPISchema):
"""Path parameters and validators for request taking message id."""

message_id = fields.Str(
required=True,
metadata={"description": "Message identifier", "example": UUID4_EXAMPLE},
)


class DeleteResponseSchema(OpenAPISchema):
"""Response schema for DELETE endpoint."""


class BasicMessageListQueryStringSchema(OpenAPISchema):
"""Basic Messages List query string schema."""
Expand Down Expand Up @@ -167,6 +180,34 @@ async def all_messages_list(request: web.BaseRequest):
return web.json_response({"results": results})


@docs(
tags=["basicmessage"],
summary="delete stored message by message_id",
)
@match_info_schema(BasicMessageIdMatchInfoSchema())
@response_schema(DeleteResponseSchema(), 200, description="")
@error_handler
async def delete_message(request: web.BaseRequest):
"""Request handler for searching basic message record by id.

Args:
request: aiohttp request object
"""
context: AdminRequestContext = request["context"]
profile = context.profile
message_id = request.match_info["message_id"]
try:
async with profile.session() as session:
record = await BasicMessageRecord.retrieve_by_message_id(session, message_id)
await record.delete_record(session)

except StorageNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
except (StorageError, BaseModelError) as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err
return web.json_response({})


async def register(app: web.Application):
"""Register routes."""
# we want to save messages when sent, so replace the default send message endpoint
Expand Down Expand Up @@ -200,6 +241,7 @@ async def register(app: web.Application):

# add in the message list(s) route
app.add_routes([web.get("/basicmessages", all_messages_list, allow_head=False)])
app.add_routes([web.delete("/basicmessages/{message_id}", delete_message)])


def post_process_routes(app: web.Application):
Expand Down
11 changes: 11 additions & 0 deletions basicmessage_storage/integration/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def post(agent: str, path: str, **kwargs):
"""Post."""
return requests.post(f"{agent}{path}", **kwargs)

def delete(agent: str, path: str, **kwargs):
"""Post."""
return requests.delete(f"{agent}{path}", **kwargs)


def fail_if_not_ok(message: str):
"""Fail the current test if wrapped call fails with message."""
Expand Down Expand Up @@ -80,6 +84,13 @@ def accept_invite(self, connection_id: str):
def retrieve_basicmessages(self, **kwargs):
"""Retrieve connections."""
return get(self.url, "/basicmessages", params=kwargs)


@unwrap_json_response
@fail_if_not_ok("Failed to delete basic messages")
def delete_basicmessage(self, message_id, **kwargs):
"""Retrieve connections."""
return delete(self.url, f"/basicmessages/{message_id}", params=kwargs)

@unwrap_json_response
@fail_if_not_ok("Failed to send basic message")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,29 @@ def test_storage(bob, alice, established_connection):
# alice should have 1 sent and 1 received (auto-reponse)
alice_messages = alice.retrieve_basicmessages()
assert len(alice_messages["results"]) == 2

def test_deletion(bob, alice, established_connection):
# make sure connection is active...
time.sleep(2)

# alice send bob a message (alice will store their sent message)
resp = alice.send_message(established_connection, "hello bob")
assert True

# make sure auto-respond messages have been exchanged
time.sleep(2)

# bob should have 1 received
bob_messages = bob.retrieve_basicmessages()
assert len(bob_messages["results"]) == 2

# alice should have 1 sent and 1 received (auto-reponse)
alice_messages = alice.retrieve_basicmessages()
assert len(alice_messages["results"]) == 4
time.sleep(2)


alice.delete_basicmessage(alice_messages["results"][0]["message_id"])
time.sleep(2)
alice_messages = alice.retrieve_basicmessages()
assert len(alice_messages["results"]) == 3