From e049b7be975df810d91a8536a912708698379740 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Sun, 19 Aug 2018 22:51:11 +0300 Subject: [PATCH] Add optional handle and guid to UserType Handle is required if delivering to Diaspora platforms. --- federation/protocols/diaspora/protocol.py | 5 ++--- .../tests/protocols/diaspora/test_protocol.py | 6 +++++- federation/tests/test_outbound.py | 20 ++++++++++++++----- federation/types.py | 13 ++++++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/federation/protocols/diaspora/protocol.py b/federation/protocols/diaspora/protocol.py index dfa9341..5e2230e 100644 --- a/federation/protocols/diaspora/protocol.py +++ b/federation/protocols/diaspora/protocol.py @@ -12,7 +12,7 @@ from federation.exceptions import EncryptedMessageError, NoSenderKeyFoundError from federation.protocols.diaspora.encrypted import EncryptedPayload from federation.protocols.diaspora.magic_envelope import MagicEnvelope from federation.types import UserType -from federation.utils.diaspora import fetch_public_key, parse_profile_diaspora_id, generate_diaspora_profile_id +from federation.utils.diaspora import fetch_public_key, generate_diaspora_profile_id from federation.utils.text import decode_if_bytes, encode_if_text logger = logging.getLogger("federation") @@ -136,8 +136,7 @@ class Protocol: xml = entity.outbound_doc else: xml = entity.to_xml() - handle, _guid = parse_profile_diaspora_id(from_user.id) - me = MagicEnvelope(etree.tostring(xml), private_key=from_user.private_key, author_handle=handle) + me = MagicEnvelope(etree.tostring(xml), private_key=from_user.private_key, author_handle=from_user.handle) rendered = me.render() if to_user_key: return EncryptedPayload.encrypt(rendered, to_user_key) diff --git a/federation/tests/protocols/diaspora/test_protocol.py b/federation/tests/protocols/diaspora/test_protocol.py index 6d5fec1..d907d32 100644 --- a/federation/tests/protocols/diaspora/test_protocol.py +++ b/federation/tests/protocols/diaspora/test_protocol.py @@ -110,6 +110,7 @@ class TestDiasporaProtocol(DiasporaTestBase): outbound_entity = get_outbound_entity(entity, private_key) data = protocol.build_send(outbound_entity, from_user=Mock( private_key=private_key, id="diaspora://johnny@localhost/profile/", + handle="johnny@localhost", )) mock_me.assert_called_once_with( etree.tostring(entity.to_xml()), private_key=private_key, author_handle="johnny@localhost", @@ -129,6 +130,7 @@ class TestDiasporaProtocol(DiasporaTestBase): outbound_entity = get_outbound_entity(entity, private_key) data = protocol.build_send(outbound_entity, to_user_key="public key", from_user=Mock( private_key=private_key, id="diaspora://johnny@localhost/profile/", + handle="johnny@localhost", )) mock_me.assert_called_once_with( etree.tostring(entity.to_xml()), private_key=private_key, author_handle="johnny@localhost", @@ -144,7 +146,9 @@ class TestDiasporaProtocol(DiasporaTestBase): protocol = self.init_protocol() outbound_doc = etree.fromstring("foo") entity = Mock(outbound_doc=outbound_doc) - from_user = Mock(id="diaspora://foobar/profile/", private_key="barfoo") + from_user = Mock( + id="diaspora://foobar/profile/", private_key="barfoo", handle="foobar", + ) protocol.build_send(entity, from_user) mock_me.assert_called_once_with(b"foo", private_key=from_user.private_key, author_handle="foobar") diff --git a/federation/tests/test_outbound.py b/federation/tests/test_outbound.py index 049c5a5..d9c33ac 100644 --- a/federation/tests/test_outbound.py +++ b/federation/tests/test_outbound.py @@ -20,7 +20,9 @@ class TestHandleCreatePayloadBuildsAPayload: @patch("federation.outbound.get_outbound_entity") def test_handle_create_payload_calls_get_outbound_entity(self, mock_get_outbound_entity): mock_get_outbound_entity.return_value = DiasporaPost() - author_user = Mock(private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/") + author_user = Mock( + private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/", handle="foobar@domain.tld", + ) entity = DiasporaPost() handle_create_payload(entity, author_user) mock_get_outbound_entity.assert_called_once_with(entity, author_user.private_key) @@ -28,7 +30,9 @@ class TestHandleCreatePayloadBuildsAPayload: @patch("federation.outbound.get_outbound_entity") def test_handle_create_payload_calls_get_outbound_entity_with_author_user(self, mock_get_outbound_entity): mock_get_outbound_entity.return_value = DiasporaPost() - author_user = Mock(private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/") + author_user = Mock( + private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/", handle="foobar@domain.tld", + ) entity = DiasporaPost() handle_create_payload(entity, author_user) mock_get_outbound_entity.assert_called_once_with(entity, author_user.private_key) @@ -37,8 +41,12 @@ class TestHandleCreatePayloadBuildsAPayload: def test_handle_create_payload_calls_sign_with_parent(self, mock_get_outbound_entity): comment = DiasporaComment() mock_get_outbound_entity.return_value = comment - author_user = Mock(private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/") - parent_user = Mock(private_key=RSA.generate(2048), id="diaspora://parent@domain.tld/profile/") + author_user = Mock( + private_key=RSA.generate(2048), id="diaspora://foobar@domain.tld/profile/", handle="foobar@domain.tld", + ) + parent_user = Mock( + private_key=RSA.generate(2048), id="diaspora://parent@domain.tld/profile/", handle="parent@domain.tld", + ) entity = DiasporaComment() with patch.object(comment, "sign_with_parent") as mock_sign: handle_create_payload(entity, author_user, parent_user=parent_user) @@ -56,7 +64,9 @@ class TestHandleSend: "diaspora://qwer@example.net/profile/qwerty", # Same host twice to ensure one delivery only per host # for public payloads ] - mock_author = Mock(private_key=key, id="diaspora://foo@example.com/profile/") + mock_author = Mock( + private_key=key, id="diaspora://foo@example.com/profile/", handle="foo@example.com", + ) handle_send(diasporapost, mock_author, recipients) # Ensure first call is a private payload diff --git a/federation/types.py b/federation/types.py index 5cca63c..bde699e 100644 --- a/federation/types.py +++ b/federation/types.py @@ -7,3 +7,16 @@ import attr class UserType: id: str = attr.ib() private_key: Optional[str] = attr.ib(default=None) + + # Required only if sending to Diaspora protocol platforms + handle: Optional[str] = attr.ib(default=None) + guid: Optional[str] = attr.ib(default=None) + + @property + def diaspora_id(self): + from federation.utils.diaspora import generate_diaspora_profile_id # Circulars + + if not self.handle: + raise ValueError("Cannot generate UserType.diaspora_id without a handle") + + return generate_diaspora_profile_id(self.handle, guid=self.guid)