comparison tests/unit/test_ap-gateway.py @ 4037:524856bd7b19

massive refactoring to switch from camelCase to snake_case: historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a pre-PEP8 code, to use the same coding style as in Twisted. However, snake_case is more readable and it's better to follow PEP8 best practices, so it has been decided to move on full snake_case. Because Libervia has a huge codebase, this ended with a ugly mix of camelCase and snake_case. To fix that, this patch does a big refactoring by renaming every function and method (including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case. This is a massive change, and may result in some bugs.
author Goffi <goffi@goffi.org>
date Sat, 08 Apr 2023 13:54:42 +0200
parents 69d970f974ff
children 4b842c1fb686
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
346 346
347 async def mock_treq_json(data): 347 async def mock_treq_json(data):
348 return dict(data) 348 return dict(data)
349 349
350 350
351 async def mock_getItems(client, service, node, *args, **kwargs): 351 async def mock_get_items(client, service, node, *args, **kwargs):
352 """Mock getItems 352 """Mock get_items
353 353
354 special kwargs can be used: 354 special kwargs can be used:
355 ret_items (List[Domish.Element]): items to be returned, by default XMPP_ITEMS are 355 ret_items (List[Domish.Element]): items to be returned, by default XMPP_ITEMS are
356 returned 356 returned
357 tested_node (str): node for which items must be returned. If specified and a 357 tested_node (str): node for which items must be returned. If specified and a
365 first=ret_items[0]["id"], last=ret_items[-1]["id"], index=0, count=len(ret_items) 365 first=ret_items[0]["id"], last=ret_items[-1]["id"], index=0, count=len(ret_items)
366 ) 366 )
367 return ret_items, {"rsm": rsm_resp.toDict(), "complete": True} 367 return ret_items, {"rsm": rsm_resp.toDict(), "complete": True}
368 368
369 369
370 async def mock_getPubsubNode(client, service, node, with_subscriptions=False, **kwargs): 370 async def mock_get_pubsub_node(client, service, node, with_subscriptions=False, **kwargs):
371 """Mock storage's getPubsubNode 371 """Mock storage's get_pubsub_node
372 372
373 return an MagicMock with subscription attribute set to empty list 373 return an MagicMock with subscription attribute set to empty list
374 """ 374 """
375 fake_cached_node = MagicMock() 375 fake_cached_node = MagicMock()
376 fake_cached_node.subscriptions = [] 376 fake_cached_node.subscriptions = []
377 return fake_cached_node 377 return fake_cached_node
378 378
379 379
380 def mockClient(jid): 380 def mock_client(jid):
381 client = MagicMock() 381 client = MagicMock()
382 client.jid = jid 382 client.jid = jid
383 client.host = "test.example" 383 client.host = "test.example"
384 client._ap_storage.get = AsyncMock() 384 client._ap_storage.get = AsyncMock()
385 client._ap_storage.aset = AsyncMock() 385 client._ap_storage.aset = AsyncMock()
386 return client 386 return client
387 387
388 388
389 def getVirtualClient(jid): 389 def get_virtual_client(jid):
390 return mockClient(jid) 390 return mock_client(jid)
391 391
392 392
393 class FakeTReqPostResponse: 393 class FakeTReqPostResponse:
394 code = 202 394 code = 202
395 395
396 396
397 @pytest.fixture(scope="session") 397 @pytest.fixture(scope="session")
398 def ap_gateway(host): 398 def ap_gateway(host):
399 gateway = plugin_comp_ap_gateway.APGateway(host) 399 gateway = plugin_comp_ap_gateway.APGateway(host)
400 gateway.initialised = True 400 gateway.initialised = True
401 gateway.isPubsub = AsyncMock() 401 gateway.is_pubsub = AsyncMock()
402 gateway.isPubsub.return_value = False 402 gateway.is_pubsub.return_value = False
403 client = mockClient(jid.JID("ap.test.example")) 403 client = mock_client(jid.JID("ap.test.example"))
404 client.getVirtualClient = getVirtualClient 404 client.get_virtual_client = get_virtual_client
405 gateway.client = client 405 gateway.client = client
406 gateway.local_only = True 406 gateway.local_only = True
407 gateway.public_url = PUBLIC_URL 407 gateway.public_url = PUBLIC_URL
408 gateway.ap_path = "_ap" 408 gateway.ap_path = "_ap"
409 gateway.auto_mentions = True 409 gateway.auto_mentions = True
414 gateway.public_key_pem = None 414 gateway.public_key_pem = None
415 return gateway 415 return gateway
416 416
417 417
418 class TestActivityPubGateway: 418 class TestActivityPubGateway:
419 def getTitleXHTML(self, item_elt: domish.Element) -> domish.Element: 419 def get_title_xhtml(self, item_elt: domish.Element) -> domish.Element:
420 return next( 420 return next(
421 t 421 t
422 for t in item_elt.entry.elements(NS_ATOM, "title") 422 for t in item_elt.entry.elements(NS_ATOM, "title")
423 if t.getAttribute("type") == "xhtml" 423 if t.getAttribute("type") == "xhtml"
424 ) 424 )
425 425
426 @ed 426 @ed
427 async def test_jid_and_node_convert_to_ap_handle(self, ap_gateway): 427 async def test_jid_and_node_convert_to_ap_handle(self, ap_gateway):
428 """JID and pubsub node are converted correctly to an AP actor handle""" 428 """JID and pubsub node are converted correctly to an AP actor handle"""
429 get_account = ap_gateway.getAPAccountFromJidAndNode 429 get_account = ap_gateway.get_ap_account_from_jid_and_node
430 430
431 # local jid 431 # local jid
432 assert ( 432 assert (
433 await get_account(jid_=jid.JID("simple@test.example"), node=None) 433 await get_account(jid_=jid.JID("simple@test.example"), node=None)
434 == "simple@test.example" 434 == "simple@test.example"
445 await get_account(jid_=jid.JID("simple@test.example"), node="some_other_node") 445 await get_account(jid_=jid.JID("simple@test.example"), node="some_other_node")
446 == "some_other_node---simple@test.example" 446 == "some_other_node---simple@test.example"
447 ) 447 )
448 448
449 # local pubsub node 449 # local pubsub node
450 with patch.object(ap_gateway, "isPubsub") as isPubsub: 450 with patch.object(ap_gateway, "is_pubsub") as is_pubsub:
451 isPubsub.return_value = True 451 is_pubsub.return_value = True
452 assert ( 452 assert (
453 await get_account(jid_=jid.JID("pubsub.test.example"), node="some_node") 453 await get_account(jid_=jid.JID("pubsub.test.example"), node="some_node")
454 == "some_node@pubsub.test.example" 454 == "some_node@pubsub.test.example"
455 ) 455 )
456 456
457 # non local pubsub node 457 # non local pubsub node
458 with patch.object(ap_gateway, "isPubsub") as isPubsub: 458 with patch.object(ap_gateway, "is_pubsub") as is_pubsub:
459 isPubsub.return_value = True 459 is_pubsub.return_value = True
460 assert ( 460 assert (
461 await get_account(jid_=jid.JID("pubsub.example.org"), node="some_node") 461 await get_account(jid_=jid.JID("pubsub.example.org"), node="some_node")
462 == "___some_node.40pubsub.2eexample.2eorg@ap.test.example" 462 == "___some_node.40pubsub.2eexample.2eorg@ap.test.example"
463 ) 463 )
464 464
465 @ed 465 @ed
466 async def test_ap_handle_convert_to_jid_and_node(self, ap_gateway, monkeypatch): 466 async def test_ap_handle_convert_to_jid_and_node(self, ap_gateway, monkeypatch):
467 """AP actor handle convert correctly to JID and pubsub node""" 467 """AP actor handle convert correctly to JID and pubsub node"""
468 get_jid_node = ap_gateway.getJIDAndNode 468 get_jid_node = ap_gateway.get_jid_and_node
469 469
470 # for following assertion, host is not a pubsub service 470 # for following assertion, host is not a pubsub service
471 with patch.object(ap_gateway, "isPubsub") as isPubsub: 471 with patch.object(ap_gateway, "is_pubsub") as is_pubsub:
472 isPubsub.return_value = False 472 is_pubsub.return_value = False
473 473
474 # simple local jid 474 # simple local jid
475 assert await get_jid_node("toto@test.example") == ( 475 assert await get_jid_node("toto@test.example") == (
476 jid.JID("toto@test.example"), 476 jid.JID("toto@test.example"),
477 None, 477 None,
496 jid.JID("toto@test.example"), 496 jid.JID("toto@test.example"),
497 "tata", 497 "tata",
498 ) 498 )
499 499
500 # for following assertion, host is a pubsub service 500 # for following assertion, host is a pubsub service
501 with patch.object(ap_gateway, "isPubsub") as isPubsub: 501 with patch.object(ap_gateway, "is_pubsub") as is_pubsub:
502 isPubsub.return_value = True 502 is_pubsub.return_value = True
503 503
504 # simple local node 504 # simple local node
505 assert await get_jid_node("toto@pubsub.test.example") == ( 505 assert await get_jid_node("toto@pubsub.test.example") == (
506 jid.JID("pubsub.test.example"), 506 jid.JID("pubsub.test.example"),
507 "toto", 507 "toto",
515 @ed 515 @ed
516 async def test_ap_to_pubsub_conversion(self, ap_gateway, monkeypatch): 516 async def test_ap_to_pubsub_conversion(self, ap_gateway, monkeypatch):
517 """AP requests are converted to pubsub""" 517 """AP requests are converted to pubsub"""
518 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 518 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
519 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 519 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
520 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 520 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
521 521
522 actor_data = await ap_gateway.getAPActorDataFromAccount(TEST_AP_ACCOUNT) 522 actor_data = await ap_gateway.get_ap_actor_data_from_account(TEST_AP_ACCOUNT)
523 outbox = await ap_gateway.apGetObject(actor_data, "outbox") 523 outbox = await ap_gateway.ap_get_object(actor_data, "outbox")
524 items, rsm_resp = await ap_gateway.getAPItems(outbox, 2) 524 items, rsm_resp = await ap_gateway.get_ap_items(outbox, 2)
525 525
526 assert rsm_resp.count == 4 526 assert rsm_resp.count == 4
527 assert rsm_resp.index == 0 527 assert rsm_resp.index == 0
528 assert rsm_resp.first == "https://example.org/users/test_user/statuses/4" 528 assert rsm_resp.first == "https://example.org/users/test_user/statuses/4"
529 assert rsm_resp.last == "https://example.org/users/test_user/statuses/3" 529 assert rsm_resp.last == "https://example.org/users/test_user/statuses/3"
530 530
531 title_xhtml = self.getTitleXHTML(items[0]) 531 title_xhtml = self.get_title_xhtml(items[0])
532 assert title_xhtml.toXml() == ( 532 assert title_xhtml.toXml() == (
533 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 533 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
534 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 4</p></div>" 534 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 4</p></div>"
535 "</title>" 535 "</title>"
536 ) 536 )
538 [e for e in items[0].entry.author.elements() if e.name == "uri"][0] 538 [e for e in items[0].entry.author.elements() if e.name == "uri"][0]
539 ) 539 )
540 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example" 540 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example"
541 assert str(items[0].entry.published) == "2021-12-16T17:25:03Z" 541 assert str(items[0].entry.published) == "2021-12-16T17:25:03Z"
542 542
543 title_xhtml = self.getTitleXHTML(items[1]) 543 title_xhtml = self.get_title_xhtml(items[1])
544 assert title_xhtml.toXml() == ( 544 assert title_xhtml.toXml() == (
545 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 545 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
546 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 3</p></div>" 546 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 3</p></div>"
547 "</title>" 547 "</title>"
548 ) 548 )
550 [e for e in items[1].entry.author.elements() if e.name == "uri"][0] 550 [e for e in items[1].entry.author.elements() if e.name == "uri"][0]
551 ) 551 )
552 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example" 552 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example"
553 assert str(items[1].entry.published) == "2021-12-16T17:26:03Z" 553 assert str(items[1].entry.published) == "2021-12-16T17:26:03Z"
554 554
555 items, rsm_resp = await ap_gateway.getAPItems( 555 items, rsm_resp = await ap_gateway.get_ap_items(
556 outbox, 556 outbox,
557 max_items=2, 557 max_items=2,
558 after_id="https://example.org/users/test_user/statuses/3", 558 after_id="https://example.org/users/test_user/statuses/3",
559 ) 559 )
560 560
561 assert rsm_resp.count == 4 561 assert rsm_resp.count == 4
562 assert rsm_resp.index == 2 562 assert rsm_resp.index == 2
563 assert rsm_resp.first == "https://example.org/users/test_user/statuses/2" 563 assert rsm_resp.first == "https://example.org/users/test_user/statuses/2"
564 assert rsm_resp.last == "https://example.org/users/test_user/statuses/1" 564 assert rsm_resp.last == "https://example.org/users/test_user/statuses/1"
565 565
566 title_xhtml = self.getTitleXHTML(items[0]) 566 title_xhtml = self.get_title_xhtml(items[0])
567 assert title_xhtml.toXml() == ( 567 assert title_xhtml.toXml() == (
568 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 568 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
569 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 2</p></div>" 569 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 2</p></div>"
570 "</title>" 570 "</title>"
571 ) 571 )
573 [e for e in items[0].entry.author.elements() if e.name == "uri"][0] 573 [e for e in items[0].entry.author.elements() if e.name == "uri"][0]
574 ) 574 )
575 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example" 575 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example"
576 assert str(items[0].entry.published) == "2021-12-16T17:27:03Z" 576 assert str(items[0].entry.published) == "2021-12-16T17:27:03Z"
577 577
578 title_xhtml = self.getTitleXHTML(items[1]) 578 title_xhtml = self.get_title_xhtml(items[1])
579 assert title_xhtml.toXml() == ( 579 assert title_xhtml.toXml() == (
580 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 580 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
581 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 1</p></div>" 581 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 1</p></div>"
582 "</title>" 582 "</title>"
583 ) 583 )
585 [e for e in items[1].entry.author.elements() if e.name == "uri"][0] 585 [e for e in items[1].entry.author.elements() if e.name == "uri"][0]
586 ) 586 )
587 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example" 587 assert author_uri == "xmpp:test_user\\40example.org@ap.test.example"
588 assert str(items[1].entry.published) == "2021-12-16T17:28:03Z" 588 assert str(items[1].entry.published) == "2021-12-16T17:28:03Z"
589 589
590 items, rsm_resp = await ap_gateway.getAPItems(outbox, max_items=1, start_index=2) 590 items, rsm_resp = await ap_gateway.get_ap_items(outbox, max_items=1, start_index=2)
591 591
592 assert rsm_resp.count == 4 592 assert rsm_resp.count == 4
593 assert rsm_resp.index == 2 593 assert rsm_resp.index == 2
594 assert rsm_resp.first == "https://example.org/users/test_user/statuses/2" 594 assert rsm_resp.first == "https://example.org/users/test_user/statuses/2"
595 assert rsm_resp.last == "https://example.org/users/test_user/statuses/2" 595 assert rsm_resp.last == "https://example.org/users/test_user/statuses/2"
596 assert len(items) == 1 596 assert len(items) == 1
597 597
598 title_xhtml = self.getTitleXHTML(items[0]) 598 title_xhtml = self.get_title_xhtml(items[0])
599 assert title_xhtml.toXml() == ( 599 assert title_xhtml.toXml() == (
600 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 600 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
601 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 2</p></div>" 601 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 2</p></div>"
602 "</title>" 602 "</title>"
603 ) 603 )
604 assert str(items[0].entry.published) == "2021-12-16T17:27:03Z" 604 assert str(items[0].entry.published) == "2021-12-16T17:27:03Z"
605 605
606 items, rsm_resp = await ap_gateway.getAPItems( 606 items, rsm_resp = await ap_gateway.get_ap_items(
607 outbox, max_items=3, chronological_pagination=False 607 outbox, max_items=3, chronological_pagination=False
608 ) 608 )
609 assert rsm_resp.count == 4 609 assert rsm_resp.count == 4
610 assert rsm_resp.index == 1 610 assert rsm_resp.index == 1
611 assert rsm_resp.first == "https://example.org/users/test_user/statuses/3" 611 assert rsm_resp.first == "https://example.org/users/test_user/statuses/3"
612 assert rsm_resp.last == "https://example.org/users/test_user/statuses/1" 612 assert rsm_resp.last == "https://example.org/users/test_user/statuses/1"
613 assert len(items) == 3 613 assert len(items) == 3
614 title_xhtml = self.getTitleXHTML(items[0]) 614 title_xhtml = self.get_title_xhtml(items[0])
615 assert title_xhtml.toXml() == ( 615 assert title_xhtml.toXml() == (
616 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 616 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
617 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 3</p></div>" 617 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 3</p></div>"
618 "</title>" 618 "</title>"
619 ) 619 )
620 title_xhtml = self.getTitleXHTML(items[2]) 620 title_xhtml = self.get_title_xhtml(items[2])
621 assert title_xhtml.toXml() == ( 621 assert title_xhtml.toXml() == (
622 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>" 622 "<title xmlns='http://www.w3.org/2005/Atom' type='xhtml'>"
623 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 1</p></div>" 623 "<div xmlns='http://www.w3.org/1999/xhtml'><p>test message 1</p></div>"
624 "</title>" 624 "</title>"
625 ) 625 )
678 return kwargs 678 return kwargs
679 679
680 @ed 680 @ed
681 async def test_pubsub_to_ap_conversion(self, ap_gateway, monkeypatch): 681 async def test_pubsub_to_ap_conversion(self, ap_gateway, monkeypatch):
682 """Pubsub nodes are converted to AP collections""" 682 """Pubsub nodes are converted to AP collections"""
683 monkeypatch.setattr(ap_gateway._p, "getItems", mock_getItems) 683 monkeypatch.setattr(ap_gateway._p, "get_items", mock_get_items)
684 outbox = await ap_gateway.server.resource.APOutboxRequest( 684 outbox = await ap_gateway.server.resource.ap_outbox_request(
685 **self.ap_request_params(ap_gateway, "outbox") 685 **self.ap_request_params(ap_gateway, "outbox")
686 ) 686 )
687 assert outbox["@context"] == ["https://www.w3.org/ns/activitystreams"] 687 assert outbox["@context"] == ["https://www.w3.org/ns/activitystreams"]
688 assert outbox["id"] == "https://test.example/_ap/outbox/some_user@test.example" 688 assert outbox["id"] == "https://test.example/_ap/outbox/some_user@test.example"
689 assert outbox["totalItems"] == len(XMPP_ITEMS) 689 assert outbox["totalItems"] == len(XMPP_ITEMS)
690 assert outbox["type"] == "OrderedCollection" 690 assert outbox["type"] == "OrderedCollection"
691 assert outbox["first"] 691 assert outbox["first"]
692 assert outbox["last"] 692 assert outbox["last"]
693 693
694 first_page = await ap_gateway.server.resource.APOutboxPageRequest( 694 first_page = await ap_gateway.server.resource.ap_outbox_page_request(
695 **self.ap_request_params(ap_gateway, url=outbox["first"]) 695 **self.ap_request_params(ap_gateway, url=outbox["first"])
696 ) 696 )
697 assert first_page["@context"] == ["https://www.w3.org/ns/activitystreams"] 697 assert first_page["@context"] == ["https://www.w3.org/ns/activitystreams"]
698 assert ( 698 assert (
699 first_page["id"] 699 first_page["id"]
723 @ed 723 @ed
724 async def test_following_to_pps(self, ap_gateway, monkeypatch): 724 async def test_following_to_pps(self, ap_gateway, monkeypatch):
725 """AP following items are converted to Public Pubsub Subscription subscriptions""" 725 """AP following items are converted to Public Pubsub Subscription subscriptions"""
726 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 726 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
727 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 727 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
728 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 728 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
729 729
730 items, __ = await ap_gateway.pubsub_service.items( 730 items, __ = await ap_gateway.pubsub_service.items(
731 jid.JID("toto@example.org"), 731 jid.JID("toto@example.org"),
732 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT), 732 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT),
733 ap_gateway._pps.subscriptions_node, 733 ap_gateway._pps.subscriptions_node,
734 None, 734 None,
735 None, 735 None,
736 None, 736 None,
737 ) 737 )
747 @ed 747 @ed
748 async def test_followers_to_pps(self, ap_gateway, monkeypatch): 748 async def test_followers_to_pps(self, ap_gateway, monkeypatch):
749 """AP followers items are converted to Public Pubsub Subscription subscribers""" 749 """AP followers items are converted to Public Pubsub Subscription subscribers"""
750 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 750 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
751 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 751 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
752 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 752 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
753 753
754 items, __ = await ap_gateway.pubsub_service.items( 754 items, __ = await ap_gateway.pubsub_service.items(
755 jid.JID("toto@example.org"), 755 jid.JID("toto@example.org"),
756 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT), 756 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT),
757 ap_gateway._pps.getPublicSubscribersNode(ap_gateway._m.namespace), 757 ap_gateway._pps.get_public_subscribers_node(ap_gateway._m.namespace),
758 None, 758 None,
759 None, 759 None,
760 None, 760 None,
761 ) 761 )
762 assert len(items) == 2 762 assert len(items) == 2
771 async def test_pps_to_following(self, ap_gateway, monkeypatch): 771 async def test_pps_to_following(self, ap_gateway, monkeypatch):
772 """Public Pubsub Subscription subscriptions are converted to AP following items""" 772 """Public Pubsub Subscription subscriptions are converted to AP following items"""
773 subscriptions = [ 773 subscriptions = [
774 pubsub.Item( 774 pubsub.Item(
775 id="subscription_1", 775 id="subscription_1",
776 payload=ap_gateway._pps.buildSubscriptionElt( 776 payload=ap_gateway._pps.build_subscription_elt(
777 ap_gateway._m.namespace, jid.JID("local_user@test.example") 777 ap_gateway._m.namespace, jid.JID("local_user@test.example")
778 ), 778 ),
779 ), 779 ),
780 pubsub.Item( 780 pubsub.Item(
781 id="subscription_2", 781 id="subscription_2",
782 payload=ap_gateway._pps.buildSubscriptionElt( 782 payload=ap_gateway._pps.build_subscription_elt(
783 ap_gateway._m.namespace, 783 ap_gateway._m.namespace,
784 jid.JID("ext_user\\40example.org@ap.test.example"), 784 jid.JID("ext_user\\40example.org@ap.test.example"),
785 ), 785 ),
786 ), 786 ),
787 ] 787 ]
788 monkeypatch.setattr( 788 monkeypatch.setattr(
789 ap_gateway._p, "getItems", partial(mock_getItems, ret_items=subscriptions) 789 ap_gateway._p, "get_items", partial(mock_get_items, ret_items=subscriptions)
790 ) 790 )
791 following = await ap_gateway.server.resource.APFollowingRequest( 791 following = await ap_gateway.server.resource.ap_following_request(
792 **self.ap_request_params(ap_gateway, "following") 792 **self.ap_request_params(ap_gateway, "following")
793 ) 793 )
794 assert following["@context"] == ["https://www.w3.org/ns/activitystreams"] 794 assert following["@context"] == ["https://www.w3.org/ns/activitystreams"]
795 assert ( 795 assert (
796 following["id"] 796 following["id"]
810 async def test_pps_to_followers(self, ap_gateway, monkeypatch): 810 async def test_pps_to_followers(self, ap_gateway, monkeypatch):
811 """Public Pubsub Subscription subscribers are converted to AP followers""" 811 """Public Pubsub Subscription subscribers are converted to AP followers"""
812 subscribers = [ 812 subscribers = [
813 pubsub.Item( 813 pubsub.Item(
814 id="subscriber_1", 814 id="subscriber_1",
815 payload=ap_gateway._pps.buildSubscriberElt( 815 payload=ap_gateway._pps.build_subscriber_elt(
816 jid.JID("local_user@test.example") 816 jid.JID("local_user@test.example")
817 ), 817 ),
818 ), 818 ),
819 pubsub.Item( 819 pubsub.Item(
820 id="subscriber_2", 820 id="subscriber_2",
821 payload=ap_gateway._pps.buildSubscriberElt( 821 payload=ap_gateway._pps.build_subscriber_elt(
822 jid.JID("ext_user\\40example.org@ap.test.example") 822 jid.JID("ext_user\\40example.org@ap.test.example")
823 ), 823 ),
824 ), 824 ),
825 ] 825 ]
826 monkeypatch.setattr( 826 monkeypatch.setattr(
827 ap_gateway._p, "getItems", partial(mock_getItems, ret_items=subscribers) 827 ap_gateway._p, "get_items", partial(mock_get_items, ret_items=subscribers)
828 ) 828 )
829 followers = await ap_gateway.server.resource.APFollowersRequest( 829 followers = await ap_gateway.server.resource.ap_followers_request(
830 **self.ap_request_params(ap_gateway, "followers") 830 **self.ap_request_params(ap_gateway, "followers")
831 ) 831 )
832 assert followers["@context"] == ["https://www.w3.org/ns/activitystreams"] 832 assert followers["@context"] == ["https://www.w3.org/ns/activitystreams"]
833 assert ( 833 assert (
834 followers["id"] 834 followers["id"]
847 @ed 847 @ed
848 async def test_xmpp_message_to_ap_direct_message(self, ap_gateway, monkeypatch): 848 async def test_xmpp_message_to_ap_direct_message(self, ap_gateway, monkeypatch):
849 """XMPP message are sent as AP direct message""" 849 """XMPP message are sent as AP direct message"""
850 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 850 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
851 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 851 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
852 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 852 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
853 mess_data = { 853 mess_data = {
854 "from": TEST_JID, 854 "from": TEST_JID,
855 "to": ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT), 855 "to": ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT),
856 "type": "chat", 856 "type": "chat",
857 "message": {"": "This is a test message."}, 857 "message": {"": "This is a test message."},
858 "extra": {"origin-id": "123"}, 858 "extra": {"origin-id": "123"},
859 } 859 }
860 with patch.object(ap_gateway, "signAndPost") as signAndPost: 860 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
861 await ap_gateway.onMessage(ap_gateway.client, mess_data) 861 await ap_gateway.onMessage(ap_gateway.client, mess_data)
862 url, actor_id, doc = signAndPost.call_args[0] 862 url, actor_id, doc = sign_and_post.call_args[0]
863 assert url == "https://example.org/users/test_user/inbox" 863 assert url == "https://example.org/users/test_user/inbox"
864 assert actor_id == "https://test.example/_ap/actor/some_user@test.example" 864 assert actor_id == "https://test.example/_ap/actor/some_user@test.example"
865 obj = doc["object"] 865 obj = doc["object"]
866 assert doc["@context"] == ["https://www.w3.org/ns/activitystreams"] 866 assert doc["@context"] == ["https://www.w3.org/ns/activitystreams"]
867 assert doc["actor"] == "https://test.example/_ap/actor/some_user@test.example" 867 assert doc["actor"] == "https://test.example/_ap/actor/some_user@test.example"
881 @ed 881 @ed
882 async def test_ap_direct_message_to_xmpp_message(self, ap_gateway, monkeypatch): 882 async def test_ap_direct_message_to_xmpp_message(self, ap_gateway, monkeypatch):
883 """AP direct message are sent as XMPP message (not Pubsub)""" 883 """AP direct message are sent as XMPP message (not Pubsub)"""
884 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 884 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
885 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 885 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
886 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 886 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
887 # we have to patch DeferredList to not wait forever 887 # we have to patch DeferredList to not wait forever
888 monkeypatch.setattr(defer, "DeferredList", AsyncMock()) 888 monkeypatch.setattr(defer, "DeferredList", AsyncMock())
889 889
890 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 890 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
891 direct_ap_message = { 891 direct_ap_message = {
892 "attributedTo": TEST_AP_ACTOR_ID, 892 "attributedTo": TEST_AP_ACTOR_ID,
893 "cc": [], 893 "cc": [],
894 "content": "<p>test direct message</p>", 894 "content": "<p>test direct message</p>",
895 "contentMap": {"en": "<p>test direct message</p>"}, 895 "contentMap": {"en": "<p>test direct message</p>"},
896 "id": f"{TEST_AP_ACTOR_ID}/statuses/123", 896 "id": f"{TEST_AP_ACTOR_ID}/statuses/123",
897 "published": "2022-05-20T08:14:39Z", 897 "published": "2022-05-20T08:14:39Z",
898 "to": [xmpp_actor_id], 898 "to": [xmpp_actor_id],
899 "type": "Note", 899 "type": "Note",
900 } 900 }
901 client = ap_gateway.client.getVirtualClient( 901 client = ap_gateway.client.get_virtual_client(
902 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 902 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
903 ) 903 )
904 with patch.object(client, "sendMessage") as sendMessage: 904 with patch.object(client, "sendMessage") as sendMessage:
905 await ap_gateway.newAPItem( 905 await ap_gateway.new_ap_item(
906 client, None, ap_gateway._m.namespace, direct_ap_message 906 client, None, ap_gateway._m.namespace, direct_ap_message
907 ) 907 )
908 908
909 # sendMessage must be called for <message> stanza, and the "message" argument must 909 # sendMessage must be called for <message> stanza, and the "message" argument must
910 # be set to the content of the original AP message 910 # be set to the content of the original AP message
915 @ed 915 @ed
916 async def test_pubsub_retract_to_ap_delete(self, ap_gateway, monkeypatch): 916 async def test_pubsub_retract_to_ap_delete(self, ap_gateway, monkeypatch):
917 """Pubsub retract requests are converted to AP delete activity""" 917 """Pubsub retract requests are converted to AP delete activity"""
918 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 918 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
919 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 919 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
920 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 920 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
921 retract_id = "retract_123" 921 retract_id = "retract_123"
922 retract_elt = domish.Element((pubsub.NS_PUBSUB_EVENT, "retract")) 922 retract_elt = domish.Element((pubsub.NS_PUBSUB_EVENT, "retract"))
923 retract_elt["id"] = retract_id 923 retract_elt["id"] = retract_id
924 items_event = pubsub.ItemsEvent( 924 items_event = pubsub.ItemsEvent(
925 sender=TEST_JID, 925 sender=TEST_JID,
926 recipient=ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT), 926 recipient=ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT),
927 nodeIdentifier=ap_gateway._m.namespace, 927 nodeIdentifier=ap_gateway._m.namespace,
928 items=[retract_elt], 928 items=[retract_elt],
929 headers={}, 929 headers={},
930 ) 930 )
931 with patch.object(ap_gateway, "signAndPost") as signAndPost: 931 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
932 signAndPost.return_value = FakeTReqPostResponse() 932 sign_and_post.return_value = FakeTReqPostResponse()
933 # we simulate the reception of a retract event 933 # we simulate the reception of a retract event
934 await ap_gateway._itemsReceived(ap_gateway.client, items_event) 934 await ap_gateway._items_received(ap_gateway.client, items_event)
935 url, actor_id, doc = signAndPost.call_args[0] 935 url, actor_id, doc = sign_and_post.call_args[0]
936 jid_account = await ap_gateway.getAPAccountFromJidAndNode(TEST_JID, None) 936 jid_account = await ap_gateway.get_ap_account_from_jid_and_node(TEST_JID, None)
937 jid_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, jid_account) 937 jid_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, jid_account)
938 assert url == f"{TEST_BASE_URL}/inbox" 938 assert url == f"{TEST_BASE_URL}/inbox"
939 assert actor_id == jid_actor_id 939 assert actor_id == jid_actor_id
940 assert doc["type"] == "Delete" 940 assert doc["type"] == "Delete"
941 assert doc["actor"] == jid_actor_id 941 assert doc["actor"] == jid_actor_id
942 obj = doc["object"] 942 obj = doc["object"]
943 assert obj["type"] == ap_const.TYPE_TOMBSTONE 943 assert obj["type"] == ap_const.TYPE_TOMBSTONE
944 url_item_id = ap_gateway.buildAPURL(ap_const.TYPE_ITEM, jid_account, retract_id) 944 url_item_id = ap_gateway.build_apurl(ap_const.TYPE_ITEM, jid_account, retract_id)
945 assert obj["id"] == url_item_id 945 assert obj["id"] == url_item_id
946 946
947 @ed 947 @ed
948 async def test_ap_delete_to_pubsub_retract(self, ap_gateway): 948 async def test_ap_delete_to_pubsub_retract(self, ap_gateway):
949 """AP delete activity is converted to pubsub retract""" 949 """AP delete activity is converted to pubsub retract"""
950 client = ap_gateway.client.getVirtualClient( 950 client = ap_gateway.client.get_virtual_client(
951 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 951 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
952 ) 952 )
953 953
954 ap_item = { 954 ap_item = {
955 "@context": "https://www.w3.org/ns/activitystreams", 955 "@context": "https://www.w3.org/ns/activitystreams",
956 "actor": TEST_AP_ACTOR_ID, 956 "actor": TEST_AP_ACTOR_ID,
960 "to": ["https://www.w3.org/ns/activitystreams#Public"], 960 "to": ["https://www.w3.org/ns/activitystreams#Public"],
961 } 961 }
962 with patch.multiple( 962 with patch.multiple(
963 ap_gateway.host.memory.storage, 963 ap_gateway.host.memory.storage,
964 get=DEFAULT, 964 get=DEFAULT,
965 getPubsubNode=DEFAULT, 965 get_pubsub_node=DEFAULT,
966 deletePubsubItems=DEFAULT, 966 delete_pubsub_items=DEFAULT,
967 ) as mock_objs: 967 ) as mock_objs:
968 mock_objs["get"].return_value = None 968 mock_objs["get"].return_value = None
969 cached_node = MagicMock() 969 cached_node = MagicMock()
970 mock_objs["getPubsubNode"].return_value = cached_node 970 mock_objs["get_pubsub_node"].return_value = cached_node
971 subscription = MagicMock() 971 subscription = MagicMock()
972 subscription.state = SubscriptionState.SUBSCRIBED 972 subscription.state = SubscriptionState.SUBSCRIBED
973 subscription.subscriber = TEST_JID 973 subscription.subscriber = TEST_JID
974 cached_node.subscriptions = [subscription] 974 cached_node.subscriptions = [subscription]
975 with patch.object( 975 with patch.object(
976 ap_gateway.pubsub_service, "notifyRetract" 976 ap_gateway.pubsub_service, "notifyRetract"
977 ) as notifyRetract: 977 ) as notifyRetract:
978 # we simulate a received Delete activity 978 # we simulate a received Delete activity
979 await ap_gateway.newAPDeleteItem( 979 await ap_gateway.new_ap_delete_item(
980 client=client, 980 client=client,
981 destinee=None, 981 destinee=None,
982 node=ap_gateway._m.namespace, 982 node=ap_gateway._m.namespace,
983 item=ap_item, 983 item=ap_item,
984 ) 984 )
985 985
986 # item is deleted from database 986 # item is deleted from database
987 deletePubsubItems = mock_objs["deletePubsubItems"] 987 delete_pubsub_items = mock_objs["delete_pubsub_items"]
988 assert deletePubsubItems.call_count == 1 988 assert delete_pubsub_items.call_count == 1
989 assert deletePubsubItems.call_args.args[1] == [ap_item["id"]] 989 assert delete_pubsub_items.call_args.args[1] == [ap_item["id"]]
990 990
991 # retraction notification is sent to subscribers 991 # retraction notification is sent to subscribers
992 assert notifyRetract.call_count == 1 992 assert notifyRetract.call_count == 1
993 assert notifyRetract.call_args.args[0] == client.jid 993 assert notifyRetract.call_args.args[0] == client.jid
994 assert notifyRetract.call_args.args[1] == ap_gateway._m.namespace 994 assert notifyRetract.call_args.args[1] == ap_gateway._m.namespace
1005 @ed 1005 @ed
1006 async def test_message_retract_to_ap_delete(self, ap_gateway, monkeypatch): 1006 async def test_message_retract_to_ap_delete(self, ap_gateway, monkeypatch):
1007 """Message retract requests are converted to AP delete activity""" 1007 """Message retract requests are converted to AP delete activity"""
1008 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1008 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1009 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1009 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1010 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1010 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1011 # origin ID is the ID of the message to retract 1011 # origin ID is the ID of the message to retract
1012 origin_id = "mess_retract_123" 1012 origin_id = "mess_retract_123"
1013 1013
1014 # we call retractByOriginId to get the message element of a retraction request 1014 # we call retract_by_origin_id to get the message element of a retraction request
1015 fake_client = MagicMock() 1015 fake_client = MagicMock()
1016 fake_client.jid = TEST_JID 1016 fake_client.jid = TEST_JID
1017 dest_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1017 dest_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1018 ap_gateway._r.retractByOriginId(fake_client, dest_jid, origin_id) 1018 ap_gateway._r.retract_by_origin_id(fake_client, dest_jid, origin_id)
1019 # message_retract_elt is the message which would be sent for a retraction 1019 # message_retract_elt is the message which would be sent for a retraction
1020 message_retract_elt = fake_client.send.call_args.args[0] 1020 message_retract_elt = fake_client.send.call_args.args[0]
1021 apply_to_elt = next(message_retract_elt.elements(NS_FASTEN, "apply-to")) 1021 apply_to_elt = next(message_retract_elt.elements(NS_FASTEN, "apply-to"))
1022 retract_elt = apply_to_elt.retract 1022 retract_elt = apply_to_elt.retract
1023 1023
1024 with patch.object(ap_gateway, "signAndPost") as signAndPost: 1024 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
1025 signAndPost.return_value = FakeTReqPostResponse() 1025 sign_and_post.return_value = FakeTReqPostResponse()
1026 fake_fastened_elts = MagicMock() 1026 fake_fastened_elts = MagicMock()
1027 fake_fastened_elts.id = origin_id 1027 fake_fastened_elts.id = origin_id
1028 # we simulate the reception of a retract event using the message element that 1028 # we simulate the reception of a retract event using the message element that
1029 # we generated above 1029 # we generated above
1030 await ap_gateway._onMessageRetract( 1030 await ap_gateway._on_message_retract(
1031 ap_gateway.client, message_retract_elt, retract_elt, fake_fastened_elts 1031 ap_gateway.client, message_retract_elt, retract_elt, fake_fastened_elts
1032 ) 1032 )
1033 url, actor_id, doc = signAndPost.call_args[0] 1033 url, actor_id, doc = sign_and_post.call_args[0]
1034 1034
1035 # the AP delete activity must have been sent through signAndPost 1035 # the AP delete activity must have been sent through sign_and_post
1036 # we check its values 1036 # we check its values
1037 jid_account = await ap_gateway.getAPAccountFromJidAndNode(TEST_JID, None) 1037 jid_account = await ap_gateway.get_ap_account_from_jid_and_node(TEST_JID, None)
1038 jid_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, jid_account) 1038 jid_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, jid_account)
1039 assert url == f"{TEST_BASE_URL}/users/{TEST_USER}/inbox" 1039 assert url == f"{TEST_BASE_URL}/users/{TEST_USER}/inbox"
1040 assert actor_id == jid_actor_id 1040 assert actor_id == jid_actor_id
1041 assert doc["type"] == "Delete" 1041 assert doc["type"] == "Delete"
1042 assert doc["actor"] == jid_actor_id 1042 assert doc["actor"] == jid_actor_id
1043 obj = doc["object"] 1043 obj = doc["object"]
1044 assert obj["type"] == ap_const.TYPE_TOMBSTONE 1044 assert obj["type"] == ap_const.TYPE_TOMBSTONE
1045 url_item_id = ap_gateway.buildAPURL(ap_const.TYPE_ITEM, jid_account, origin_id) 1045 url_item_id = ap_gateway.build_apurl(ap_const.TYPE_ITEM, jid_account, origin_id)
1046 assert obj["id"] == url_item_id 1046 assert obj["id"] == url_item_id
1047 1047
1048 @ed 1048 @ed
1049 async def test_ap_delete_to_message_retract(self, ap_gateway, monkeypatch): 1049 async def test_ap_delete_to_message_retract(self, ap_gateway, monkeypatch):
1050 """AP delete activity is converted to message retract""" 1050 """AP delete activity is converted to message retract"""
1051 # note: a message retract is used when suitable message is found in history, 1051 # note: a message retract is used when suitable message is found in history,
1052 # otherwise it should be in pubsub cache and it's a pubsub retract (tested above 1052 # otherwise it should be in pubsub cache and it's a pubsub retract (tested above
1053 # by ``test_ap_delete_to_pubsub_retract``) 1053 # by ``test_ap_delete_to_pubsub_retract``)
1054 1054
1055 # we don't want actual queries in database 1055 # we don't want actual queries in database
1056 retractDBHistory = AsyncMock() 1056 retract_db_history = AsyncMock()
1057 monkeypatch.setattr(ap_gateway._r, "retractDBHistory", retractDBHistory) 1057 monkeypatch.setattr(ap_gateway._r, "retract_db_history", retract_db_history)
1058 1058
1059 client = ap_gateway.client.getVirtualClient( 1059 client = ap_gateway.client.get_virtual_client(
1060 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1060 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1061 ) 1061 )
1062 fake_send = MagicMock() 1062 fake_send = MagicMock()
1063 monkeypatch.setattr(client, "send", fake_send) 1063 monkeypatch.setattr(client, "send", fake_send)
1064 1064
1065 ap_item = { 1065 ap_item = {
1075 fake_history.source_jid = client.jid 1075 fake_history.source_jid = client.jid
1076 fake_history.dest_jid = TEST_JID 1076 fake_history.dest_jid = TEST_JID
1077 fake_history.origin_id = ap_item["id"] 1077 fake_history.origin_id = ap_item["id"]
1078 storage_get.return_value = fake_history 1078 storage_get.return_value = fake_history
1079 # we simulate a received Delete activity 1079 # we simulate a received Delete activity
1080 await ap_gateway.newAPDeleteItem( 1080 await ap_gateway.new_ap_delete_item(
1081 client=client, destinee=None, node=ap_gateway._m.namespace, item=ap_item 1081 client=client, destinee=None, node=ap_gateway._m.namespace, item=ap_item
1082 ) 1082 )
1083 1083
1084 # item is deleted from database 1084 # item is deleted from database
1085 assert retractDBHistory.call_count == 1 1085 assert retract_db_history.call_count == 1
1086 assert retractDBHistory.call_args.args[0] == client 1086 assert retract_db_history.call_args.args[0] == client
1087 assert retractDBHistory.call_args.args[1] == fake_history 1087 assert retract_db_history.call_args.args[1] == fake_history
1088 1088
1089 # retraction notification is sent to destinee 1089 # retraction notification is sent to destinee
1090 assert fake_send.call_count == 1 1090 assert fake_send.call_count == 1
1091 sent_elt = fake_send.call_args.args[0] 1091 sent_elt = fake_send.call_args.args[0]
1092 assert sent_elt.name == "message" 1092 assert sent_elt.name == "message"
1101 @ed 1101 @ed
1102 async def test_ap_actor_metadata_to_vcard(self, ap_gateway, monkeypatch): 1102 async def test_ap_actor_metadata_to_vcard(self, ap_gateway, monkeypatch):
1103 """AP actor metadata are converted to XMPP/vCard4""" 1103 """AP actor metadata are converted to XMPP/vCard4"""
1104 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1104 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1105 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1105 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1106 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1106 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1107 1107
1108 items, __ = await ap_gateway.pubsub_service.items( 1108 items, __ = await ap_gateway.pubsub_service.items(
1109 jid.JID("toto@example.org"), 1109 jid.JID("toto@example.org"),
1110 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT), 1110 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT),
1111 # VCard4 node 1111 # VCard4 node
1112 ap_gateway._v.node, 1112 ap_gateway._v.node,
1113 None, 1113 None,
1114 None, 1114 None,
1115 None, 1115 None,
1116 ) 1116 )
1117 assert len(items) == 1 1117 assert len(items) == 1
1118 vcard_elt = next(items[0].elements(ap_gateway._v.namespace, "vcard")) 1118 vcard_elt = next(items[0].elements(ap_gateway._v.namespace, "vcard"))
1119 vcard = ap_gateway._v.vcard2Dict(vcard_elt) 1119 vcard = ap_gateway._v.vcard_2_dict(vcard_elt)
1120 assert "test_user nickname" in vcard["nicknames"] 1120 assert "test_user nickname" in vcard["nicknames"]
1121 assert vcard["description"] == "test account" 1121 assert vcard["description"] == "test account"
1122 1122
1123 @ed 1123 @ed
1124 async def test_identity_data_to_ap_actor_metadata(self, ap_gateway): 1124 async def test_identity_data_to_ap_actor_metadata(self, ap_gateway):
1125 """XMPP identity is converted to AP actor metadata""" 1125 """XMPP identity is converted to AP actor metadata"""
1126 # XXX: XMPP identity is normally an amalgam of metadata from several 1126 # XXX: XMPP identity is normally an amalgam of metadata from several
1127 # XEPs/locations (vCard4, vcard-tmp, etc) 1127 # XEPs/locations (vCard4, vcard-tmp, etc)
1128 with patch.object(ap_gateway._i, "getIdentity") as getIdentity: 1128 with patch.object(ap_gateway._i, "get_identity") as get_identity:
1129 getIdentity.return_value = { 1129 get_identity.return_value = {
1130 "nicknames": ["nick1", "nick2"], 1130 "nicknames": ["nick1", "nick2"],
1131 "description": "test description", 1131 "description": "test description",
1132 } 1132 }
1133 actor_data = await ap_gateway.server.resource.APActorRequest( 1133 actor_data = await ap_gateway.server.resource.ap_actor_request(
1134 **self.ap_request_params(ap_gateway, ap_const.TYPE_ACTOR) 1134 **self.ap_request_params(ap_gateway, ap_const.TYPE_ACTOR)
1135 ) 1135 )
1136 1136
1137 # only the first nickname should be used 1137 # only the first nickname should be used
1138 assert actor_data["name"] == "nick1" 1138 assert actor_data["name"] == "nick1"
1141 @ed 1141 @ed
1142 async def test_direct_addressing_mention_to_reference(self, ap_gateway, monkeypatch): 1142 async def test_direct_addressing_mention_to_reference(self, ap_gateway, monkeypatch):
1143 """AP mentions by direct addressing are converted to XEP-0372 references""" 1143 """AP mentions by direct addressing are converted to XEP-0372 references"""
1144 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1144 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1145 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1145 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1146 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1146 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1147 1147
1148 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1148 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1149 1149
1150 direct_addr_mention = { 1150 direct_addr_mention = {
1151 "attributedTo": TEST_AP_ACTOR_ID, 1151 "attributedTo": TEST_AP_ACTOR_ID,
1152 "cc": [], 1152 "cc": [],
1153 "content": "<p>test mention by direct addressing</p>", 1153 "content": "<p>test mention by direct addressing</p>",
1154 "id": f"{TEST_AP_ACTOR_ID}/statuses/direct_addr_123", 1154 "id": f"{TEST_AP_ACTOR_ID}/statuses/direct_addr_123",
1155 "published": "2022-05-20T08:14:39Z", 1155 "published": "2022-05-20T08:14:39Z",
1156 "to": [ap_const.NS_AP_PUBLIC, xmpp_actor_id], 1156 "to": [ap_const.NS_AP_PUBLIC, xmpp_actor_id],
1157 "type": "Note", 1157 "type": "Note",
1158 } 1158 }
1159 client = ap_gateway.client.getVirtualClient( 1159 client = ap_gateway.client.get_virtual_client(
1160 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1160 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1161 ) 1161 )
1162 monkeypatch.setattr(client, "sendMessage", MagicMock()) 1162 monkeypatch.setattr(client, "sendMessage", MagicMock())
1163 1163
1164 with patch.object(ap_gateway._refs, "sendReference") as sendReference: 1164 with patch.object(ap_gateway._refs, "send_reference") as send_reference:
1165 await ap_gateway.newAPItem( 1165 await ap_gateway.new_ap_item(
1166 client, None, ap_gateway._m.namespace, direct_addr_mention 1166 client, None, ap_gateway._m.namespace, direct_addr_mention
1167 ) 1167 )
1168 1168
1169 assert sendReference.call_count == 1 1169 assert send_reference.call_count == 1
1170 assert sendReference.call_args.kwargs["to_jid"] == TEST_JID 1170 assert send_reference.call_args.kwargs["to_jid"] == TEST_JID
1171 1171
1172 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1172 local_actor_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1173 expected_anchor = xmpp_uri.buildXMPPUri( 1173 expected_anchor = xmpp_uri.build_xmpp_uri(
1174 "pubsub", 1174 "pubsub",
1175 path=local_actor_jid.full(), 1175 path=local_actor_jid.full(),
1176 node=ap_gateway._m.namespace, 1176 node=ap_gateway._m.namespace,
1177 item=direct_addr_mention["id"], 1177 item=direct_addr_mention["id"],
1178 ) 1178 )
1179 1179
1180 assert sendReference.call_args.kwargs["anchor"] == expected_anchor 1180 assert send_reference.call_args.kwargs["anchor"] == expected_anchor
1181 1181
1182 @ed 1182 @ed
1183 async def test_tag_mention_to_reference(self, ap_gateway, monkeypatch): 1183 async def test_tag_mention_to_reference(self, ap_gateway, monkeypatch):
1184 """AP mentions in "tag" field are converted to XEP-0372 references""" 1184 """AP mentions in "tag" field are converted to XEP-0372 references"""
1185 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1185 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1186 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1186 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1187 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1187 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1188 1188
1189 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1189 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1190 1190
1191 direct_addr_mention = { 1191 direct_addr_mention = {
1192 "attributedTo": TEST_AP_ACTOR_ID, 1192 "attributedTo": TEST_AP_ACTOR_ID,
1193 "cc": [], 1193 "cc": [],
1194 "content": "<p>test mention by tag</p>", 1194 "content": "<p>test mention by tag</p>",
1196 "published": "2022-05-20T08:14:39Z", 1196 "published": "2022-05-20T08:14:39Z",
1197 "to": [ap_const.NS_AP_PUBLIC], 1197 "to": [ap_const.NS_AP_PUBLIC],
1198 "tag": [{"type": "Mention", "href": xmpp_actor_id, "name": f"@{TEST_JID}'"}], 1198 "tag": [{"type": "Mention", "href": xmpp_actor_id, "name": f"@{TEST_JID}'"}],
1199 "type": "Note", 1199 "type": "Note",
1200 } 1200 }
1201 client = ap_gateway.client.getVirtualClient( 1201 client = ap_gateway.client.get_virtual_client(
1202 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1202 ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1203 ) 1203 )
1204 monkeypatch.setattr(client, "sendMessage", MagicMock()) 1204 monkeypatch.setattr(client, "sendMessage", MagicMock())
1205 1205
1206 with patch.object(ap_gateway._refs, "sendReference") as sendReference: 1206 with patch.object(ap_gateway._refs, "send_reference") as send_reference:
1207 await ap_gateway.newAPItem( 1207 await ap_gateway.new_ap_item(
1208 client, None, ap_gateway._m.namespace, direct_addr_mention 1208 client, None, ap_gateway._m.namespace, direct_addr_mention
1209 ) 1209 )
1210 1210
1211 assert sendReference.call_count == 1 1211 assert send_reference.call_count == 1
1212 assert sendReference.call_args.kwargs["to_jid"] == TEST_JID 1212 assert send_reference.call_args.kwargs["to_jid"] == TEST_JID
1213 1213
1214 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1214 local_actor_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1215 expected_anchor = xmpp_uri.buildXMPPUri( 1215 expected_anchor = xmpp_uri.build_xmpp_uri(
1216 "pubsub", 1216 "pubsub",
1217 path=local_actor_jid.full(), 1217 path=local_actor_jid.full(),
1218 node=ap_gateway._m.namespace, 1218 node=ap_gateway._m.namespace,
1219 item=direct_addr_mention["id"], 1219 item=direct_addr_mention["id"],
1220 ) 1220 )
1221 1221
1222 assert sendReference.call_args.kwargs["anchor"] == expected_anchor 1222 assert send_reference.call_args.kwargs["anchor"] == expected_anchor
1223 1223
1224 @ed 1224 @ed
1225 async def test_auto_mentions(self, ap_gateway, monkeypatch): 1225 async def test_auto_mentions(self, ap_gateway, monkeypatch):
1226 """Check that mentions in body are converted to AP mentions""" 1226 """Check that mentions in body are converted to AP mentions"""
1227 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1227 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1228 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1228 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1229 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1229 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1230 1230
1231 mb_data = { 1231 mb_data = {
1232 "author_jid": TEST_JID.full(), 1232 "author_jid": TEST_JID.full(),
1233 "content": f"mention of @{TEST_AP_ACCOUNT}", 1233 "content": f"mention of @{TEST_AP_ACCOUNT}",
1234 "service": TEST_JID.full(), 1234 "service": TEST_JID.full(),
1252 """Check that no mention is send when the message is not public""" 1252 """Check that no mention is send when the message is not public"""
1253 # this is the same test as test_auto_mentions above, except that public is not set 1253 # this is the same test as test_auto_mentions above, except that public is not set
1254 # in mb_data_2_ap_item 1254 # in mb_data_2_ap_item
1255 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1255 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1256 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1256 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1257 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1257 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1258 1258
1259 mb_data = { 1259 mb_data = {
1260 "author_jid": TEST_JID.full(), 1260 "author_jid": TEST_JID.full(),
1261 "content": f"mention of @{TEST_AP_ACCOUNT}", 1261 "content": f"mention of @{TEST_AP_ACCOUNT}",
1262 "service": TEST_JID.full(), 1262 "service": TEST_JID.full(),
1273 @ed 1273 @ed
1274 async def test_xmpp_reference_to_ap_mention(self, ap_gateway, monkeypatch): 1274 async def test_xmpp_reference_to_ap_mention(self, ap_gateway, monkeypatch):
1275 """Check that XEP-0372 references are converted to AP mention""" 1275 """Check that XEP-0372 references are converted to AP mention"""
1276 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1276 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1277 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1277 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1278 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1278 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1279 1279
1280 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1280 local_actor_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1281 item_elt = XMPP_ITEMS[0] 1281 item_elt = XMPP_ITEMS[0]
1282 anchor = xmpp_uri.buildXMPPUri( 1282 anchor = xmpp_uri.build_xmpp_uri(
1283 "pubsub", 1283 "pubsub",
1284 path=TEST_JID.full(), 1284 path=TEST_JID.full(),
1285 node=ap_gateway._m.namespace, 1285 node=ap_gateway._m.namespace,
1286 item=item_elt["id"], 1286 item=item_elt["id"],
1287 ) 1287 )
1288 1288
1289 ref_data: Dict[str, Union[str, int, dict]] = { 1289 ref_data: Dict[str, Union[str, int, dict]] = {
1290 "uri": xmpp_uri.buildXMPPUri(None, path=local_actor_jid.full()), 1290 "uri": xmpp_uri.build_xmpp_uri(None, path=local_actor_jid.full()),
1291 "type_": "mention", 1291 "type_": "mention",
1292 "anchor": anchor, 1292 "anchor": anchor,
1293 } 1293 }
1294 reference_elt = ap_gateway._refs.buildRefElement(**ref_data) 1294 reference_elt = ap_gateway._refs.build_ref_element(**ref_data)
1295 1295
1296 # we now update ref_data to look like what is received in the trigger 1296 # we now update ref_data to look like what is received in the trigger
1297 1297
1298 ref_data["parsed_uri"] = xmpp_uri.parseXMPPUri(ref_data["uri"]) 1298 ref_data["parsed_uri"] = xmpp_uri.parse_xmpp_uri(ref_data["uri"])
1299 ref_data["parsed_anchor"] = xmpp_uri.parseXMPPUri(ref_data["anchor"]) 1299 ref_data["parsed_anchor"] = xmpp_uri.parse_xmpp_uri(ref_data["anchor"])
1300 1300
1301 # "type" is a builtin function, thus "type_" is used in buildRefElement, but in 1301 # "type" is a builtin function, thus "type_" is used in build_ref_element, but in
1302 # ref_data is "type" without underscore 1302 # ref_data is "type" without underscore
1303 ref_data["type"] = ref_data["type_"] 1303 ref_data["type"] = ref_data["type_"]
1304 del ref_data["type_"] 1304 del ref_data["type_"]
1305 1305
1306 message_elt = domish.Element((None, "message")) 1306 message_elt = domish.Element((None, "message"))
1307 message_elt.addChild(reference_elt) 1307 message_elt.addChild(reference_elt)
1308 1308
1309 with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems: 1309 with patch.object(ap_gateway.host.memory.storage, "get_items") as get_items:
1310 # getItems returns a sqla_mapping.PubsubItem, thus we need to fake it and set 1310 # get_items returns a sqla_mapping.PubsubItem, thus we need to fake it and set
1311 # the item_elt we want to use in its "data" attribute 1311 # the item_elt we want to use in its "data" attribute
1312 mock_pubsub_item = MagicMock 1312 mock_pubsub_item = MagicMock
1313 mock_pubsub_item.data = item_elt 1313 mock_pubsub_item.data = item_elt
1314 getItems.return_value = ([mock_pubsub_item], {}) 1314 get_items.return_value = ([mock_pubsub_item], {})
1315 with patch.object(ap_gateway, "signAndPost") as signAndPost: 1315 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
1316 signAndPost.return_value.code = 202 1316 sign_and_post.return_value.code = 202
1317 await ap_gateway._onReferenceReceived( 1317 await ap_gateway._on_reference_received(
1318 ap_gateway.client, message_elt, ref_data 1318 ap_gateway.client, message_elt, ref_data
1319 ) 1319 )
1320 1320
1321 # when reference is received, the referencing item must be sent to referenced 1321 # when reference is received, the referencing item must be sent to referenced
1322 # actor, and they must be in "to" field and in "tag" 1322 # actor, and they must be in "to" field and in "tag"
1323 assert signAndPost.call_count == 1 1323 assert sign_and_post.call_count == 1
1324 send_ap_item = signAndPost.call_args.args[-1] 1324 send_ap_item = sign_and_post.call_args.args[-1]
1325 ap_object = send_ap_item["object"] 1325 ap_object = send_ap_item["object"]
1326 assert TEST_AP_ACTOR_ID in ap_object["to"] 1326 assert TEST_AP_ACTOR_ID in ap_object["to"]
1327 expected_mention = { 1327 expected_mention = {
1328 "type": ap_const.TYPE_MENTION, 1328 "type": ap_const.TYPE_MENTION,
1329 "href": TEST_AP_ACTOR_ID, 1329 "href": TEST_AP_ACTOR_ID,
1336 @ed 1336 @ed
1337 async def test_xmpp_repeat_to_ap_announce(self, ap_gateway, monkeypatch): 1337 async def test_xmpp_repeat_to_ap_announce(self, ap_gateway, monkeypatch):
1338 """XEP-0272 post repeat is converted to AP Announce activity""" 1338 """XEP-0272 post repeat is converted to AP Announce activity"""
1339 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1339 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1340 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1340 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1341 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1341 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1342 1342
1343 # JID repeated AP actor (also the recipient of the message) 1343 # JID repeated AP actor (also the recipient of the message)
1344 recipient_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1344 recipient_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1345 # repeated item 1345 # repeated item
1346 ap_item = TEST_AP_ITEMS[0] 1346 ap_item = TEST_AP_ITEMS[0]
1347 ap_item_url = xmpp_uri.buildXMPPUri( 1347 ap_item_url = xmpp_uri.build_xmpp_uri(
1348 "pubsub", 1348 "pubsub",
1349 path=recipient_jid.full(), 1349 path=recipient_jid.full(),
1350 node=ap_gateway._m.namespace, 1350 node=ap_gateway._m.namespace,
1351 item=ap_item["id"], 1351 item=ap_item["id"],
1352 ) 1352 )
1372 </item> 1372 </item>
1373 """ 1373 """
1374 ) 1374 )
1375 item_elt.uri = pubsub.NS_PUBSUB_EVENT 1375 item_elt.uri = pubsub.NS_PUBSUB_EVENT
1376 1376
1377 with patch.object(ap_gateway, "signAndPost") as signAndPost: 1377 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
1378 signAndPost.return_value.code = 202 1378 sign_and_post.return_value.code = 202
1379 await ap_gateway.convertAndPostItems( 1379 await ap_gateway.convert_and_post_items(
1380 ap_gateway.client, 1380 ap_gateway.client,
1381 TEST_AP_ACCOUNT, 1381 TEST_AP_ACCOUNT,
1382 TEST_JID, 1382 TEST_JID,
1383 ap_gateway._m.namespace, 1383 ap_gateway._m.namespace,
1384 [item_elt], 1384 [item_elt],
1385 ) 1385 )
1386 1386
1387 assert signAndPost.called 1387 assert sign_and_post.called
1388 url, actor_id, doc = signAndPost.call_args.args 1388 url, actor_id, doc = sign_and_post.call_args.args
1389 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"] 1389 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
1390 assert actor_id == ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1390 assert actor_id == ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1391 assert doc["type"] == "Announce" 1391 assert doc["type"] == "Announce"
1392 assert ap_const.NS_AP_PUBLIC in doc["to"] 1392 assert ap_const.NS_AP_PUBLIC in doc["to"]
1393 assert doc["object"] == ap_item["id"] 1393 assert doc["object"] == ap_item["id"]
1394 1394
1395 @ed 1395 @ed
1396 async def test_ap_announce_to_xmpp_repeat(self, ap_gateway, monkeypatch): 1396 async def test_ap_announce_to_xmpp_repeat(self, ap_gateway, monkeypatch):
1397 """AP Announce activity is converted to XEP-0272 post repeat""" 1397 """AP Announce activity is converted to XEP-0272 post repeat"""
1398 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1398 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1399 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1399 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1400 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1400 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1401 1401
1402 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1402 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1403 # announced item 1403 # announced item
1404 xmpp_item = XMPP_ITEMS[0] 1404 xmpp_item = XMPP_ITEMS[0]
1405 xmpp_item_url = ap_gateway.buildAPURL( 1405 xmpp_item_url = ap_gateway.build_apurl(
1406 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"] 1406 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"]
1407 ) 1407 )
1408 announce = { 1408 announce = {
1409 "@context": "https://www.w3.org/ns/activitystreams", 1409 "@context": "https://www.w3.org/ns/activitystreams",
1410 "type": "Announce", 1410 "type": "Announce",
1413 "id": "https://example.org/announce/123", 1413 "id": "https://example.org/announce/123",
1414 "object": xmpp_item_url, 1414 "object": xmpp_item_url,
1415 "published": "2022-07-22T09:24:12Z", 1415 "published": "2022-07-22T09:24:12Z",
1416 "to": [ap_const.NS_AP_PUBLIC], 1416 "to": [ap_const.NS_AP_PUBLIC],
1417 } 1417 }
1418 with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems: 1418 with patch.object(ap_gateway.host.memory.storage, "get_items") as get_items:
1419 mock_pubsub_item = MagicMock 1419 mock_pubsub_item = MagicMock
1420 mock_pubsub_item.data = xmpp_item 1420 mock_pubsub_item.data = xmpp_item
1421 getItems.return_value = ([mock_pubsub_item], {}) 1421 get_items.return_value = ([mock_pubsub_item], {})
1422 with patch.object( 1422 with patch.object(
1423 ap_gateway.host.memory.storage, "cachePubsubItems" 1423 ap_gateway.host.memory.storage, "cache_pubsub_items"
1424 ) as cachePubsubItems: 1424 ) as cache_pubsub_items:
1425 await ap_gateway.server.resource.handleAnnounceActivity( 1425 await ap_gateway.server.resource.handle_announce_activity(
1426 Request(MagicMock()), announce, None, None, None, "", TEST_AP_ACTOR_ID 1426 Request(MagicMock()), announce, None, None, None, "", TEST_AP_ACTOR_ID
1427 ) 1427 )
1428 1428
1429 assert cachePubsubItems.called 1429 assert cache_pubsub_items.called
1430 # the microblog data put in cache correspond to the item sent to subscribers 1430 # the microblog data put in cache correspond to the item sent to subscribers
1431 __, __, __, [mb_data] = cachePubsubItems.call_args.args 1431 __, __, __, [mb_data] = cache_pubsub_items.call_args.args
1432 extra = mb_data["extra"] 1432 extra = mb_data["extra"]
1433 assert "repeated" in extra 1433 assert "repeated" in extra
1434 repeated = extra["repeated"] 1434 repeated = extra["repeated"]
1435 assert repeated["by"] == ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT).full() 1435 assert repeated["by"] == ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT).full()
1436 xmpp_item_xmpp_url = xmpp_uri.buildXMPPUri( 1436 xmpp_item_xmpp_url = xmpp_uri.build_xmpp_uri(
1437 "pubsub", 1437 "pubsub",
1438 path=TEST_JID.full(), 1438 path=TEST_JID.full(),
1439 node=ap_gateway._m.namespace, 1439 node=ap_gateway._m.namespace,
1440 item=xmpp_item["id"], 1440 item=xmpp_item["id"],
1441 ) 1441 )
1444 @ed 1444 @ed
1445 async def test_xmpp_attachment_noticed_to_ap_like(self, ap_gateway, monkeypatch): 1445 async def test_xmpp_attachment_noticed_to_ap_like(self, ap_gateway, monkeypatch):
1446 """Pubsub-attachments ``noticed`` is converted to AP Like activity""" 1446 """Pubsub-attachments ``noticed`` is converted to AP Like activity"""
1447 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1447 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1448 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1448 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1449 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1449 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1450 1450
1451 recipient_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1451 recipient_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1452 # noticed item 1452 # noticed item
1453 ap_item = TEST_AP_ITEMS[0] 1453 ap_item = TEST_AP_ITEMS[0]
1454 attachment_node = ap_gateway._pa.getAttachmentNodeName( 1454 attachment_node = ap_gateway._pa.get_attachment_node_name(
1455 recipient_jid, ap_gateway._m.namespace, ap_item["id"] 1455 recipient_jid, ap_gateway._m.namespace, ap_item["id"]
1456 ) 1456 )
1457 item_elt = xml_tools.parse( 1457 item_elt = xml_tools.parse(
1458 f""" 1458 f"""
1459 <item id="{TEST_JID.userhost()}" published="{TEST_JID.userhostJID()}"> 1459 <item id="{TEST_JID.userhost()}" published="{TEST_JID.userhostJID()}">
1466 item_elt.uri = pubsub.NS_PUBSUB_EVENT 1466 item_elt.uri = pubsub.NS_PUBSUB_EVENT
1467 items_event = pubsub.ItemsEvent( 1467 items_event = pubsub.ItemsEvent(
1468 TEST_JID, recipient_jid, attachment_node, [item_elt], {} 1468 TEST_JID, recipient_jid, attachment_node, [item_elt], {}
1469 ) 1469 )
1470 1470
1471 with patch.object(ap_gateway, "signAndPost") as signAndPost: 1471 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
1472 signAndPost.return_value.code = 202 1472 sign_and_post.return_value.code = 202
1473 await ap_gateway._itemsReceived(ap_gateway.client, items_event) 1473 await ap_gateway._items_received(ap_gateway.client, items_event)
1474 1474
1475 assert signAndPost.called 1475 assert sign_and_post.called
1476 url, actor_id, doc = signAndPost.call_args.args 1476 url, actor_id, doc = sign_and_post.call_args.args
1477 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"] 1477 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
1478 assert actor_id == ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1478 assert actor_id == ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1479 assert doc["type"] == "Like" 1479 assert doc["type"] == "Like"
1480 assert ap_const.NS_AP_PUBLIC in doc["cc"] 1480 assert ap_const.NS_AP_PUBLIC in doc["cc"]
1481 assert doc["object"] == ap_item["id"] 1481 assert doc["object"] == ap_item["id"]
1482 1482
1483 @ed 1483 @ed
1484 async def test_ap_like_to_xmpp_noticed_attachment(self, ap_gateway, monkeypatch): 1484 async def test_ap_like_to_xmpp_noticed_attachment(self, ap_gateway, monkeypatch):
1485 """AP Like activity is converted to ``noticed`` attachment""" 1485 """AP Like activity is converted to ``noticed`` attachment"""
1486 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1486 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1487 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1487 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1488 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1488 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1489 1489
1490 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1490 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1491 # liked item 1491 # liked item
1492 xmpp_item = XMPP_ITEMS[0] 1492 xmpp_item = XMPP_ITEMS[0]
1493 xmpp_item_url = ap_gateway.buildAPURL( 1493 xmpp_item_url = ap_gateway.build_apurl(
1494 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"] 1494 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"]
1495 ) 1495 )
1496 like = { 1496 like = {
1497 "@context": "https://www.w3.org/ns/activitystreams", 1497 "@context": "https://www.w3.org/ns/activitystreams",
1498 "type": "Like", 1498 "type": "Like",
1501 "id": "https://example.org/like/123", 1501 "id": "https://example.org/like/123",
1502 "object": xmpp_item_url, 1502 "object": xmpp_item_url,
1503 "published": "2022-07-22T09:24:12Z", 1503 "published": "2022-07-22T09:24:12Z",
1504 "to": [ap_const.NS_AP_PUBLIC], 1504 "to": [ap_const.NS_AP_PUBLIC],
1505 } 1505 }
1506 with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems: 1506 with patch.object(ap_gateway.host.memory.storage, "get_items") as get_items:
1507 getItems.return_value = ([], {}) 1507 get_items.return_value = ([], {})
1508 with patch.object(ap_gateway._p, "sendItems") as sendItems: 1508 with patch.object(ap_gateway._p, "send_items") as send_items:
1509 await ap_gateway.server.resource.APInboxRequest( 1509 await ap_gateway.server.resource.ap_inbox_request(
1510 **self.ap_request_params( 1510 **self.ap_request_params(
1511 ap_gateway, "inbox", data=like, signing_actor=TEST_AP_ACTOR_ID 1511 ap_gateway, "inbox", data=like, signing_actor=TEST_AP_ACTOR_ID
1512 ) 1512 )
1513 ) 1513 )
1514 1514
1515 assert sendItems.called 1515 assert send_items.called
1516 si_client, si_service, si_node, [si_item] = sendItems.call_args.args 1516 si_client, si_service, si_node, [si_item] = send_items.call_args.args
1517 assert si_client.jid == ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1517 assert si_client.jid == ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1518 assert si_service == TEST_JID 1518 assert si_service == TEST_JID
1519 assert si_node == ap_gateway._pa.getAttachmentNodeName( 1519 assert si_node == ap_gateway._pa.get_attachment_node_name(
1520 TEST_JID, ap_gateway._m.namespace, xmpp_item["id"] 1520 TEST_JID, ap_gateway._m.namespace, xmpp_item["id"]
1521 ) 1521 )
1522 [parsed_item] = ap_gateway._pa.items2attachmentData(si_client, [si_item]) 1522 [parsed_item] = ap_gateway._pa.items_2_attachment_data(si_client, [si_item])
1523 assert parsed_item["from"] == si_client.jid.full() 1523 assert parsed_item["from"] == si_client.jid.full()
1524 assert "noticed" in parsed_item 1524 assert "noticed" in parsed_item
1525 assert parsed_item["noticed"]["noticed"] == True 1525 assert parsed_item["noticed"]["noticed"] == True
1526 1526
1527 @ed 1527 @ed
1528 async def test_xmpp_pubsub_reactions_to_ap(self, ap_gateway, monkeypatch): 1528 async def test_xmpp_pubsub_reactions_to_ap(self, ap_gateway, monkeypatch):
1529 """Pubsub-attachments ``reactions`` is converted to AP EmojiReact activity""" 1529 """Pubsub-attachments ``reactions`` is converted to AP EmojiReact activity"""
1530 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1530 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1531 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1531 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1532 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1532 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1533 1533
1534 recipient_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1534 recipient_jid = ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1535 # noticed item 1535 # noticed item
1536 ap_item = TEST_AP_ITEMS[0] 1536 ap_item = TEST_AP_ITEMS[0]
1537 ap_item_url = xmpp_uri.buildXMPPUri( 1537 ap_item_url = xmpp_uri.build_xmpp_uri(
1538 "pubsub", 1538 "pubsub",
1539 path=recipient_jid.full(), 1539 path=recipient_jid.full(),
1540 node=ap_gateway._m.namespace, 1540 node=ap_gateway._m.namespace,
1541 item=ap_item["id"], 1541 item=ap_item["id"],
1542 ) 1542 )
1543 attachment_node = ap_gateway._pa.getAttachmentNodeName( 1543 attachment_node = ap_gateway._pa.get_attachment_node_name(
1544 recipient_jid, ap_gateway._m.namespace, ap_item["id"] 1544 recipient_jid, ap_gateway._m.namespace, ap_item["id"]
1545 ) 1545 )
1546 reactions = ["🦁", "🥜", "🎻"] 1546 reactions = ["🦁", "🥜", "🎻"]
1547 item_elt = xml_tools.parse( 1547 item_elt = xml_tools.parse(
1548 f""" 1548 f"""
1560 item_elt.uri = pubsub.NS_PUBSUB_EVENT 1560 item_elt.uri = pubsub.NS_PUBSUB_EVENT
1561 items_event = pubsub.ItemsEvent( 1561 items_event = pubsub.ItemsEvent(
1562 TEST_JID, recipient_jid, attachment_node, [item_elt], {} 1562 TEST_JID, recipient_jid, attachment_node, [item_elt], {}
1563 ) 1563 )
1564 1564
1565 with patch.object(ap_gateway, "signAndPost") as signAndPost: 1565 with patch.object(ap_gateway, "sign_and_post") as sign_and_post:
1566 signAndPost.return_value.code = 202 1566 sign_and_post.return_value.code = 202
1567 await ap_gateway._itemsReceived(ap_gateway.client, items_event) 1567 await ap_gateway._items_received(ap_gateway.client, items_event)
1568 1568
1569 assert signAndPost.call_count == 3 1569 assert sign_and_post.call_count == 3
1570 for idx, call_args in enumerate(signAndPost.call_args_list): 1570 for idx, call_args in enumerate(sign_and_post.call_args_list):
1571 url, actor_id, doc = call_args.args 1571 url, actor_id, doc = call_args.args
1572 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"] 1572 assert url == TEST_USER_DATA["endpoints"]["sharedInbox"]
1573 assert actor_id == ap_gateway.buildAPURL( 1573 assert actor_id == ap_gateway.build_apurl(
1574 ap_const.TYPE_ACTOR, TEST_JID.userhost() 1574 ap_const.TYPE_ACTOR, TEST_JID.userhost()
1575 ) 1575 )
1576 assert doc["type"] == "EmojiReact" 1576 assert doc["type"] == "EmojiReact"
1577 assert ap_const.NS_AP_PUBLIC in doc["cc"] 1577 assert ap_const.NS_AP_PUBLIC in doc["cc"]
1578 assert doc["object"] == ap_item["id"] 1578 assert doc["object"] == ap_item["id"]
1586 @ed 1586 @ed
1587 async def test_ap_reactions_to_xmpp(self, ap_gateway, monkeypatch): 1587 async def test_ap_reactions_to_xmpp(self, ap_gateway, monkeypatch):
1588 """AP EmojiReact activity is converted to ``reactions`` attachment""" 1588 """AP EmojiReact activity is converted to ``reactions`` attachment"""
1589 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) 1589 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
1590 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) 1590 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
1591 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) 1591 monkeypatch.setattr(ap_gateway, "ap_get", mock_ap_get)
1592 1592
1593 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) 1593 xmpp_actor_id = ap_gateway.build_apurl(ap_const.TYPE_ACTOR, TEST_JID.userhost())
1594 # item on which reaction is attached 1594 # item on which reaction is attached
1595 xmpp_item = XMPP_ITEMS[0] 1595 xmpp_item = XMPP_ITEMS[0]
1596 xmpp_item_url = ap_gateway.buildAPURL( 1596 xmpp_item_url = ap_gateway.build_apurl(
1597 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"] 1597 ap_const.TYPE_ITEM, TEST_JID.userhost(), xmpp_item["id"]
1598 ) 1598 )
1599 like = { 1599 like = {
1600 "@context": "https://www.w3.org/ns/activitystreams", 1600 "@context": "https://www.w3.org/ns/activitystreams",
1601 "type": "EmojiReact", 1601 "type": "EmojiReact",
1605 "object": xmpp_item_url, 1605 "object": xmpp_item_url,
1606 "content": "🐅", 1606 "content": "🐅",
1607 "published": "2022-07-22T09:24:12Z", 1607 "published": "2022-07-22T09:24:12Z",
1608 "to": [ap_const.NS_AP_PUBLIC], 1608 "to": [ap_const.NS_AP_PUBLIC],
1609 } 1609 }
1610 with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems: 1610 with patch.object(ap_gateway.host.memory.storage, "get_items") as get_items:
1611 getItems.return_value = ([], {}) 1611 get_items.return_value = ([], {})
1612 with patch.object(ap_gateway._p, "sendItems") as sendItems: 1612 with patch.object(ap_gateway._p, "send_items") as send_items:
1613 await ap_gateway.server.resource.APInboxRequest( 1613 await ap_gateway.server.resource.ap_inbox_request(
1614 **self.ap_request_params( 1614 **self.ap_request_params(
1615 ap_gateway, "inbox", data=like, signing_actor=TEST_AP_ACTOR_ID 1615 ap_gateway, "inbox", data=like, signing_actor=TEST_AP_ACTOR_ID
1616 ) 1616 )
1617 ) 1617 )
1618 1618
1619 assert sendItems.called 1619 assert send_items.called
1620 si_client, si_service, si_node, [si_item] = sendItems.call_args.args 1620 si_client, si_service, si_node, [si_item] = send_items.call_args.args
1621 assert si_client.jid == ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) 1621 assert si_client.jid == ap_gateway.get_local_jid_from_account(TEST_AP_ACCOUNT)
1622 assert si_service == TEST_JID 1622 assert si_service == TEST_JID
1623 assert si_node == ap_gateway._pa.getAttachmentNodeName( 1623 assert si_node == ap_gateway._pa.get_attachment_node_name(
1624 TEST_JID, ap_gateway._m.namespace, xmpp_item["id"] 1624 TEST_JID, ap_gateway._m.namespace, xmpp_item["id"]
1625 ) 1625 )
1626 [parsed_item] = ap_gateway._pa.items2attachmentData(si_client, [si_item]) 1626 [parsed_item] = ap_gateway._pa.items_2_attachment_data(si_client, [si_item])
1627 assert parsed_item["from"] == si_client.jid.full() 1627 assert parsed_item["from"] == si_client.jid.full()
1628 assert "reactions" in parsed_item 1628 assert "reactions" in parsed_item
1629 assert parsed_item["reactions"]["reactions"] == ["🐅"] 1629 assert parsed_item["reactions"]["reactions"] == ["🐅"]
1630 1630
1631 @ed 1631 @ed