tests (unit/ap gateway): message/item retractation tests:
this patch adds 4 tests to check pubsub <=> AP item retractation and message <=> AP item retractation. rel 367
This commit is contained in:
parent
847780b473
commit
57c945dc9f
1 changed files with 203 additions and 1 deletions
|
|
@ -17,7 +17,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from copy import deepcopy
|
||||
from unittest.mock import MagicMock, AsyncMock, patch
|
||||
from unittest.mock import MagicMock, AsyncMock, patch, DEFAULT
|
||||
from urllib import parse
|
||||
from functools import partial
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ from twisted.words.protocols.jabber import jid
|
|||
from twisted.web.server import Request
|
||||
from twisted.words.xish import domish
|
||||
from wokkel import rsm, pubsub
|
||||
from treq.response import _Response as TReqResponse
|
||||
|
||||
from sat.core import exceptions
|
||||
from sat.core.constants import Const as C
|
||||
|
|
@ -35,10 +36,13 @@ from sat.plugins import plugin_comp_ap_gateway
|
|||
from sat.plugins.plugin_comp_ap_gateway import constants as ap_const
|
||||
from sat.plugins.plugin_comp_ap_gateway.http_server import HTTPServer
|
||||
from sat.plugins.plugin_xep_0277 import NS_ATOM
|
||||
from sat.plugins.plugin_xep_0422 import NS_FASTEN
|
||||
from sat.plugins.plugin_xep_0424 import NS_MESSAGE_RETRACT
|
||||
from sat.plugins.plugin_xep_0465 import NS_PPS
|
||||
from sat.tools.utils import xmpp_date
|
||||
from sat.tools import xml_tools
|
||||
from sat.plugins.plugin_comp_ap_gateway import TYPE_ACTOR
|
||||
from sat.memory.sqla_mapping import SubscriptionState
|
||||
|
||||
|
||||
TEST_BASE_URL = "https://example.org"
|
||||
|
|
@ -380,6 +384,10 @@ def getVirtualClient(jid):
|
|||
return client
|
||||
|
||||
|
||||
class FakeTReqPostResponse:
|
||||
code = 202
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def ap_gateway(host):
|
||||
gateway = plugin_comp_ap_gateway.APGateway(host)
|
||||
|
|
@ -886,3 +894,197 @@ class TestActivityPubGateway:
|
|||
assert sendMessage.called
|
||||
assert sendMessage.call_args.args[0] == TEST_JID
|
||||
assert sendMessage.call_args.args[1] == {"": "test direct message"}
|
||||
|
||||
@ed
|
||||
async def test_pubsub_retract_to_ap_delete(self, ap_gateway, monkeypatch):
|
||||
"""Pubsub retract requests are converted to AP delete activity"""
|
||||
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
|
||||
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
|
||||
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
|
||||
retract_id = "retract_123"
|
||||
retract_elt = domish.Element((pubsub.NS_PUBSUB_EVENT, "retract"))
|
||||
retract_elt["id"] = retract_id
|
||||
items_event = pubsub.ItemsEvent(
|
||||
sender=TEST_JID,
|
||||
recipient=ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT),
|
||||
nodeIdentifier=ap_gateway._m.namespace,
|
||||
items=[retract_elt],
|
||||
headers={}
|
||||
)
|
||||
with patch.object(ap_gateway, "signAndPost") as signAndPost:
|
||||
signAndPost.return_value = FakeTReqPostResponse()
|
||||
# we simulate the reception of a retract event
|
||||
await ap_gateway._itemsReceived(ap_gateway.client, items_event)
|
||||
url, actor_id, doc = signAndPost.call_args[0]
|
||||
jid_account = await ap_gateway.getAPAccountFromJidAndNode(TEST_JID, None)
|
||||
jid_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, jid_account)
|
||||
assert url == f"{TEST_BASE_URL}/users/{TEST_USER}/inbox"
|
||||
assert actor_id == jid_actor_id
|
||||
assert doc["type"] == "Delete"
|
||||
assert doc["actor"] == jid_actor_id
|
||||
obj = doc["object"]
|
||||
assert obj["type"] == ap_const.TYPE_TOMBSTONE
|
||||
url_item_id = ap_gateway.buildAPURL(ap_const.TYPE_ITEM, jid_account, retract_id)
|
||||
assert obj["id"] == url_item_id
|
||||
|
||||
@ed
|
||||
async def test_ap_delete_to_pubsub_retract(self, ap_gateway):
|
||||
"""AP delete activity is converted to pubsub retract"""
|
||||
client = ap_gateway.client.getVirtualClient(
|
||||
ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
|
||||
)
|
||||
|
||||
ap_item = {
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"actor": TEST_AP_ACTOR_ID,
|
||||
"id": "https://test.example/retract_123",
|
||||
"type": "Delete",
|
||||
"object": {"id": f"{TEST_AP_ACTOR_ID}/item/123",
|
||||
"type": "Tombstone"},
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
with patch.multiple(
|
||||
ap_gateway.host.memory.storage,
|
||||
get=DEFAULT,
|
||||
getPubsubNode=DEFAULT,
|
||||
deletePubsubItems=DEFAULT,
|
||||
) as mock_objs:
|
||||
mock_objs["get"].return_value=None
|
||||
cached_node = MagicMock()
|
||||
mock_objs["getPubsubNode"].return_value=cached_node
|
||||
subscription = MagicMock()
|
||||
subscription.state = SubscriptionState.SUBSCRIBED
|
||||
subscription.subscriber = TEST_JID
|
||||
cached_node.subscriptions = [subscription]
|
||||
with patch.object(
|
||||
ap_gateway.pubsub_service, "notifyRetract"
|
||||
) as notifyRetract:
|
||||
# we simulate a received Delete activity
|
||||
await ap_gateway.newAPDeleteItem(
|
||||
client=client,
|
||||
destinee=None,
|
||||
node=ap_gateway._m.namespace,
|
||||
item=ap_item
|
||||
)
|
||||
|
||||
# item is deleted from database
|
||||
deletePubsubItems = mock_objs["deletePubsubItems"]
|
||||
assert deletePubsubItems.call_count == 1
|
||||
assert deletePubsubItems.call_args.args[1] == [ap_item["id"]]
|
||||
|
||||
# retraction notification is sent to subscribers
|
||||
assert notifyRetract.call_count == 1
|
||||
assert notifyRetract.call_args.args[0] == client.jid
|
||||
assert notifyRetract.call_args.args[1] == ap_gateway._m.namespace
|
||||
notifications = notifyRetract.call_args.args[2]
|
||||
assert len(notifications) == 1
|
||||
subscriber, __, item_elts = notifications[0]
|
||||
assert subscriber == TEST_JID
|
||||
assert len(item_elts) == 1
|
||||
item_elt = item_elts[0]
|
||||
assert isinstance(item_elt, domish.Element)
|
||||
assert item_elt.name == "item"
|
||||
assert item_elt["id"] == ap_item["id"]
|
||||
|
||||
@ed
|
||||
async def test_message_retract_to_ap_delete(self, ap_gateway, monkeypatch):
|
||||
"""Message retract requests are converted to AP delete activity"""
|
||||
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
|
||||
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
|
||||
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
|
||||
# origin ID is the ID of the message to retract
|
||||
origin_id = "mess_retract_123"
|
||||
|
||||
# we call retractByOriginId to get the message element of a retraction request
|
||||
fake_client = MagicMock()
|
||||
fake_client.jid = TEST_JID
|
||||
dest_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
|
||||
ap_gateway._r.retractByOriginId(fake_client, dest_jid, origin_id)
|
||||
# message_retract_elt is the message which would be sent for a retraction
|
||||
message_retract_elt = fake_client.send.call_args.args[0]
|
||||
apply_to_elt = next(message_retract_elt.elements(NS_FASTEN, "apply-to"))
|
||||
retract_elt = apply_to_elt.retract
|
||||
|
||||
with patch.object(ap_gateway, "signAndPost") as signAndPost:
|
||||
signAndPost.return_value = FakeTReqPostResponse()
|
||||
fake_fastened_elts = MagicMock()
|
||||
fake_fastened_elts.id = origin_id
|
||||
# we simulate the reception of a retract event using the message element that
|
||||
# we generated above
|
||||
await ap_gateway._onMessageRetract(
|
||||
ap_gateway.client,
|
||||
message_retract_elt,
|
||||
retract_elt,
|
||||
fake_fastened_elts
|
||||
)
|
||||
url, actor_id, doc = signAndPost.call_args[0]
|
||||
|
||||
# the AP delete activity must have been sent through signAndPost
|
||||
# we check its values
|
||||
jid_account = await ap_gateway.getAPAccountFromJidAndNode(TEST_JID, None)
|
||||
jid_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, jid_account)
|
||||
assert url == f"{TEST_BASE_URL}/users/{TEST_USER}/inbox"
|
||||
assert actor_id == jid_actor_id
|
||||
assert doc["type"] == "Delete"
|
||||
assert doc["actor"] == jid_actor_id
|
||||
obj = doc["object"]
|
||||
assert obj["type"] == ap_const.TYPE_TOMBSTONE
|
||||
url_item_id = ap_gateway.buildAPURL(ap_const.TYPE_ITEM, jid_account, origin_id)
|
||||
assert obj["id"] == url_item_id
|
||||
|
||||
@ed
|
||||
async def test_ap_delete_to_message_retract(self, ap_gateway, monkeypatch):
|
||||
"""AP delete activity is converted to message retract"""
|
||||
# note: a message retract is used when suitable message is found in history,
|
||||
# otherwise it should be in pubsub cache and it's a pubsub retract (tested above
|
||||
# by ``test_ap_delete_to_pubsub_retract``)
|
||||
|
||||
# we don't want actual queries in database
|
||||
retractDBHistory = AsyncMock()
|
||||
monkeypatch.setattr(ap_gateway._r, "retractDBHistory", retractDBHistory)
|
||||
|
||||
client = ap_gateway.client.getVirtualClient(
|
||||
ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
|
||||
)
|
||||
fake_send = MagicMock()
|
||||
monkeypatch.setattr(client, "send", fake_send)
|
||||
|
||||
ap_item = {
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"actor": TEST_AP_ACTOR_ID,
|
||||
"id": "https://test.example/retract_123",
|
||||
"type": "Delete",
|
||||
"object": {"id": f"{TEST_AP_ACTOR_ID}/item/123",
|
||||
"type": "Tombstone"},
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
with patch.object(ap_gateway.host.memory.storage, "get") as storage_get:
|
||||
fake_history = MagicMock()
|
||||
fake_history.source_jid = client.jid
|
||||
fake_history.dest_jid = TEST_JID
|
||||
fake_history.origin_id = ap_item["id"]
|
||||
storage_get.return_value = fake_history
|
||||
# we simulate a received Delete activity
|
||||
await ap_gateway.newAPDeleteItem(
|
||||
client=client,
|
||||
destinee=None,
|
||||
node=ap_gateway._m.namespace,
|
||||
item=ap_item
|
||||
)
|
||||
|
||||
# item is deleted from database
|
||||
assert retractDBHistory.call_count == 1
|
||||
assert retractDBHistory.call_args.args[0] == client
|
||||
assert retractDBHistory.call_args.args[1] == fake_history
|
||||
|
||||
# retraction notification is sent to destinee
|
||||
assert fake_send.call_count == 1
|
||||
sent_elt = fake_send.call_args.args[0]
|
||||
assert sent_elt.name == "message"
|
||||
assert sent_elt["from"] == client.jid.full()
|
||||
assert sent_elt["to"] == TEST_JID.full()
|
||||
apply_to_elt = next(sent_elt.elements(NS_FASTEN, "apply-to"))
|
||||
assert apply_to_elt["id"] == ap_item["id"]
|
||||
retract_elt = apply_to_elt.retract
|
||||
assert retract_elt is not None
|
||||
assert retract_elt.uri == NS_MESSAGE_RETRACT
|
||||
|
|
|
|||
Loading…
Reference in a new issue