component AP Gateway: implement HTTP GET signature.

This commit is contained in:
Goffi 2024-06-05 22:34:09 +02:00
commit b402be2a7a
5 changed files with 615 additions and 263 deletions

View file

@ -339,7 +339,11 @@ for item in TEST_AP_ITEMS:
AP_REQUESTS[item["id"]] = item
async def mock_ap_get(url):
async def mock_treq_get(url):
return deepcopy(AP_REQUESTS[url])
async def mock_ap_get(url, requestor_actor_id):
return deepcopy(AP_REQUESTS[url])
@ -514,13 +518,15 @@ class TestActivityPubGateway:
@ed
async def test_ap_to_pubsub_conversion(self, ap_gateway, monkeypatch):
"""AP requests are converted to pubsub"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
actor_data = await ap_gateway.get_ap_actor_data_from_account(TEST_AP_ACCOUNT)
outbox = await ap_gateway.ap_get_object(actor_data, "outbox")
items, rsm_resp = await ap_gateway.get_ap_items(outbox, 2)
actor_data = await ap_gateway.get_ap_actor_data_from_account(
TEST_AP_ACTOR_ID, TEST_AP_ACCOUNT
)
outbox = await ap_gateway.ap_get_object(TEST_AP_ACTOR_ID, actor_data, "outbox")
items, rsm_resp = await ap_gateway.get_ap_items(TEST_AP_ACTOR_ID, outbox, 2)
assert rsm_resp.count == 4
assert rsm_resp.index == 0
@ -552,6 +558,7 @@ class TestActivityPubGateway:
assert str(items[1].entry.published) == "2021-12-16T17:26:03Z"
items, rsm_resp = await ap_gateway.get_ap_items(
TEST_AP_ACTOR_ID,
outbox,
max_items=2,
after_id="https://example.org/users/test_user/statuses/3",
@ -586,7 +593,9 @@ class TestActivityPubGateway:
assert author_uri == "xmpp:test_user\\40example.org@ap.test.example"
assert str(items[1].entry.published) == "2021-12-16T17:28:03Z"
items, rsm_resp = await ap_gateway.get_ap_items(outbox, max_items=1, start_index=2)
items, rsm_resp = await ap_gateway.get_ap_items(
TEST_AP_ACTOR_ID, outbox, max_items=1, start_index=2
)
assert rsm_resp.count == 4
assert rsm_resp.index == 2
@ -603,7 +612,7 @@ class TestActivityPubGateway:
assert str(items[0].entry.published) == "2021-12-16T17:27:03Z"
items, rsm_resp = await ap_gateway.get_ap_items(
outbox, max_items=3, chronological_pagination=False
TEST_AP_ACTOR_ID, outbox, max_items=3, chronological_pagination=False
)
assert rsm_resp.count == 4
assert rsm_resp.index == 1
@ -670,6 +679,8 @@ class TestActivityPubGateway:
"ap_url": ap_url,
"signing_actor": signing_actor,
}
if type_ not in (ap_const.TYPE_ACTOR, "outbox", "following", "followers"):
kwargs["requestor_actor_id"] = TEST_AP_ACTOR_ID
if type_ == "outbox" and query_data:
kwargs["query_data"] = query_data
# signing_actor is not used for page requests
@ -722,7 +733,7 @@ class TestActivityPubGateway:
@ed
async def test_following_to_pps(self, ap_gateway, monkeypatch):
"""AP following items are converted to Public Pubsub Subscription subscriptions"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -746,7 +757,7 @@ class TestActivityPubGateway:
@ed
async def test_followers_to_pps(self, ap_gateway, monkeypatch):
"""AP followers items are converted to Public Pubsub Subscription subscribers"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -846,7 +857,7 @@ class TestActivityPubGateway:
@ed
async def test_xmpp_message_to_ap_direct_message(self, ap_gateway, monkeypatch):
"""XMPP message are sent as AP direct message"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
mess_data = {
@ -856,9 +867,9 @@ class TestActivityPubGateway:
"message": {"": "This is a test message."},
"extra": {"origin-id": "123"},
}
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
await ap_gateway.onMessage(ap_gateway.client, mess_data)
url, actor_id, doc = sign_and_post.call_args[0]
with patch.object(ap_gateway, "ap_post") as ap_post:
await ap_gateway.on_message(ap_gateway.client, mess_data)
url, actor_id, doc = ap_post.call_args[0]
assert url == "https://example.org/users/test_user/inbox"
assert actor_id == "https://test.example/_ap/actor/some_user@test.example"
obj = doc["object"]
@ -880,7 +891,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_direct_message_to_xmpp_message(self, ap_gateway, monkeypatch):
"""AP direct message are sent as XMPP message (not Pubsub)"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
# we have to patch DeferredList to not wait forever
@ -914,7 +925,7 @@ class TestActivityPubGateway:
@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, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
retract_id = "retract_123"
@ -927,11 +938,11 @@ class TestActivityPubGateway:
items=[retract_elt],
headers={},
)
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value = FakeTReqPostResponse()
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.return_value = FakeTReqPostResponse()
# we simulate the reception of a retract event
await ap_gateway._items_received(ap_gateway.client, items_event)
url, actor_id, doc = sign_and_post.call_args[0]
url, actor_id, doc = ap_post.call_args[0]
jid_account = await ap_gateway.get_ap_account_from_jid_and_node(TEST_JID, None)
jid_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, jid_account)
assert url == f"{TEST_BASE_URL}/inbox"
@ -1004,7 +1015,7 @@ class TestActivityPubGateway:
@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, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
# origin ID is the ID of the message to retract
@ -1021,8 +1032,8 @@ class TestActivityPubGateway:
message_retract_elt = fake_client.send.call_args.args[0]
retract_elt = next(message_retract_elt.elements(NS_MESSAGE_RETRACT, "retract"))
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value = FakeTReqPostResponse()
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.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
@ -1030,9 +1041,9 @@ class TestActivityPubGateway:
await ap_gateway._on_message_retract(
ap_gateway.client, message_retract_elt, retract_elt, fake_fastened_elts
)
url, actor_id, doc = sign_and_post.call_args[0]
url, actor_id, doc = ap_post.call_args[0]
# the AP delete activity must have been sent through sign_and_post
# the AP delete activity must have been sent through ap_post
# we check its values
jid_account = await ap_gateway.get_ap_account_from_jid_and_node(TEST_JID, None)
jid_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, jid_account)
@ -1101,7 +1112,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_actor_metadata_to_vcard(self, ap_gateway, monkeypatch):
"""AP actor metadata are converted to XMPP/vCard4"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1141,7 +1152,7 @@ class TestActivityPubGateway:
@ed
async def test_direct_addressing_mention_to_reference(self, ap_gateway, monkeypatch):
"""AP mentions by direct addressing are converted to XEP-0372 references"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1182,7 +1193,7 @@ class TestActivityPubGateway:
@ed
async def test_tag_mention_to_reference(self, ap_gateway, monkeypatch):
"""AP mentions in "tag" field are converted to XEP-0372 references"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1224,7 +1235,7 @@ class TestActivityPubGateway:
@ed
async def test_auto_mentions(self, ap_gateway, monkeypatch):
"""Check that mentions in body are converted to AP mentions"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1252,7 +1263,7 @@ class TestActivityPubGateway:
"""Check that no mention is send when the message is not public"""
# this is the same test as test_auto_mentions above, except that public is not set
# in mb_data_2_ap_item
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1273,7 +1284,7 @@ class TestActivityPubGateway:
@ed
async def test_xmpp_reference_to_ap_mention(self, ap_gateway, monkeypatch):
"""Check that XEP-0372 references are converted to AP mention"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1312,16 +1323,16 @@ class TestActivityPubGateway:
mock_pubsub_item = MagicMock
mock_pubsub_item.data = item_elt
get_items.return_value = ([mock_pubsub_item], {})
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value.code = 202
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.return_value.code = 202
await ap_gateway._on_reference_received(
ap_gateway.client, message_elt, ref_data
)
# when reference is received, the referencing item must be sent to referenced
# actor, and they must be in "to" field and in "tag"
assert sign_and_post.call_count == 1
send_ap_item = sign_and_post.call_args.args[-1]
assert ap_post.call_count == 1
send_ap_item = ap_post.call_args.args[-1]
ap_object = send_ap_item["object"]
assert TEST_AP_ACTOR_ID in ap_object["to"]
expected_mention = {
@ -1336,7 +1347,7 @@ class TestActivityPubGateway:
@ed
async def test_xmpp_repeat_to_ap_announce(self, ap_gateway, monkeypatch):
"""XEP-0272 post repeat is converted to AP Announce activity"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1374,8 +1385,8 @@ class TestActivityPubGateway:
)
item_elt.uri = pubsub.NS_PUBSUB_EVENT
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value.code = 202
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.return_value.code = 202
await ap_gateway.convert_and_post_items(
ap_gateway.client,
TEST_AP_ACCOUNT,
@ -1384,8 +1395,8 @@ class TestActivityPubGateway:
[item_elt],
)
assert sign_and_post.called
url, actor_id, doc = sign_and_post.call_args.args
assert ap_post.called
url, actor_id, doc = ap_post.call_args.args
assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
assert actor_id == ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
assert doc["type"] == "Announce"
@ -1395,7 +1406,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_announce_to_xmpp_repeat(self, ap_gateway, monkeypatch):
"""AP Announce activity is converted to XEP-0272 post repeat"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1423,7 +1434,8 @@ class TestActivityPubGateway:
ap_gateway.host.memory.storage, "cache_pubsub_items"
) as cache_pubsub_items:
await ap_gateway.server.resource.handle_announce_activity(
Request(MagicMock()), announce, None, None, None, "", TEST_AP_ACTOR_ID
TEST_AP_ACTOR_ID, Request(MagicMock()), announce, None, None, None,
"", TEST_AP_ACTOR_ID
)
assert cache_pubsub_items.called
@ -1444,7 +1456,7 @@ class TestActivityPubGateway:
@ed
async def test_xmpp_attachment_noticed_to_ap_like(self, ap_gateway, monkeypatch):
"""Pubsub-attachments ``noticed`` is converted to AP Like activity"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1468,12 +1480,12 @@ class TestActivityPubGateway:
TEST_JID, recipient_jid, attachment_node, [item_elt], {}
)
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value.code = 202
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.return_value.code = 202
await ap_gateway._items_received(ap_gateway.client, items_event)
assert sign_and_post.called
url, actor_id, doc = sign_and_post.call_args.args
assert ap_post.called
url, actor_id, doc = ap_post.call_args.args
assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
assert actor_id == ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
assert doc["type"] == "Like"
@ -1483,7 +1495,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_like_to_xmpp_noticed_attachment(self, ap_gateway, monkeypatch):
"""AP Like activity is converted to ``noticed`` attachment"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1527,7 +1539,7 @@ class TestActivityPubGateway:
@ed
async def test_xmpp_pubsub_reactions_to_ap(self, ap_gateway, monkeypatch):
"""Pubsub-attachments ``reactions`` is converted to AP EmojiReact activity"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1562,12 +1574,12 @@ class TestActivityPubGateway:
TEST_JID, recipient_jid, attachment_node, [item_elt], {}
)
with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
sign_and_post.return_value.code = 202
with patch.object(ap_gateway, "ap_post") as ap_post:
ap_post.return_value.code = 202
await ap_gateway._items_received(ap_gateway.client, items_event)
assert sign_and_post.call_count == 3
for idx, call_args in enumerate(sign_and_post.call_args_list):
assert ap_post.call_count == 3
for idx, call_args in enumerate(ap_post.call_args_list):
url, actor_id, doc = call_args.args
assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
assert actor_id == ap_gateway.build_apurl(
@ -1586,7 +1598,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_reactions_to_xmpp(self, ap_gateway, monkeypatch):
"""AP EmojiReact activity is converted to ``reactions`` attachment"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_treq_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
@ -1725,7 +1737,9 @@ class TestActivityPubGateway:
"url": f"https://test.example/_ap/item/{test_actor}/event_123",
}
event_data = await ap_gateway.ap_events.ap_item_2_event_data(ap_object)
event_data = await ap_gateway.ap_events.ap_item_2_event_data(
TEST_AP_ACTOR_ID, ap_object
)
assert event_data["id"] == ap_object["id"]
assert event_data["name"] == {"": "test event"}