kopia lustrzana https://gitlab.com/jaywink/federation
Add receiving user guid to entity for private Diaspora payloads
Required for example to actually use (legacy) relationship retraction.merge-requests/130/head
rodzic
dd027d4699
commit
d64a2c27a2
|
@ -8,9 +8,10 @@
|
||||||
### Added
|
### Added
|
||||||
* New style Diaspora public payloads are now supported (see [here](https://github.com/diaspora/diaspora_federation/issues/30)). Old style payloads are still supported. Payloads are also still sent out old style.
|
* New style Diaspora public payloads are now supported (see [here](https://github.com/diaspora/diaspora_federation/issues/30)). Old style payloads are still supported. Payloads are also still sent out old style.
|
||||||
* Add new `Follow` base entity and support for the new Diaspora "contact" payload. The simple `Follow` maps to Diaspora contact entity with following/sharing both true or false. Sharing as a separate concept is not currently supported.
|
* Add new `Follow` base entity and support for the new Diaspora "contact" payload. The simple `Follow` maps to Diaspora contact entity with following/sharing both true or false. Sharing as a separate concept is not currently supported.
|
||||||
|
* Added `_receiving_guid` to all entities. This is filled with `user.guid` if `user` is passed to `federation.inbound.handle_receive` and it has a `guid`. Normally in for example Diaspora, this will always be done in private payloads.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Legacy Diaspora retraction of sharing/following is now supported correctly. The end result is a `DiasporaRetraction` for entity type `Profile`.
|
* Legacy Diaspora retraction of sharing/following is now supported correctly. The end result is a `DiasporaRetraction` for entity type `Profile`. Since the payload doesn't contain the receiving user for a sharing/following retraction in legacy Diaspora protocol, we store the guid of the user in the entity as `_receiving_guid`, assuming it was passed in for processing.
|
||||||
|
|
||||||
|
|
||||||
## [0.11.0] - 2017-05-08
|
## [0.11.0] - 2017-05-08
|
||||||
|
|
|
@ -13,6 +13,8 @@ class BaseEntity(object):
|
||||||
_required = []
|
_required = []
|
||||||
_children = []
|
_children = []
|
||||||
_allowed_children = ()
|
_allowed_children = ()
|
||||||
|
# If we have a receiver for a private payload, store receiving user guid here
|
||||||
|
_receiving_guid = ""
|
||||||
_source_protocol = ""
|
_source_protocol = ""
|
||||||
_source_object = None
|
_source_object = None
|
||||||
_sender_key = ""
|
_sender_key = ""
|
||||||
|
|
|
@ -52,7 +52,7 @@ def xml_children_as_dict(node):
|
||||||
return dict((e.tag, e.text) for e in node)
|
return dict((e.tag, e.text) for e in node)
|
||||||
|
|
||||||
|
|
||||||
def element_to_objects(element, sender_key_fetcher=None):
|
def element_to_objects(element, sender_key_fetcher=None, user=None):
|
||||||
"""Transform an Element to a list of entities recursively.
|
"""Transform an Element to a list of entities recursively.
|
||||||
|
|
||||||
Possible child entities are added to each entity `_children` list.
|
Possible child entities are added to each entity `_children` list.
|
||||||
|
@ -60,6 +60,7 @@ def element_to_objects(element, sender_key_fetcher=None):
|
||||||
:param tree: Element
|
:param tree: Element
|
||||||
:param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
|
:param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
|
||||||
over network. The function should take sender handle as the only parameter.
|
over network. The function should take sender handle as the only parameter.
|
||||||
|
:param user: Optional receiving user object. If given, should have a `handle`.
|
||||||
:returns: list of entities
|
:returns: list of entities
|
||||||
"""
|
"""
|
||||||
entities = []
|
entities = []
|
||||||
|
@ -76,6 +77,9 @@ def element_to_objects(element, sender_key_fetcher=None):
|
||||||
entity._source_protocol = "diaspora"
|
entity._source_protocol = "diaspora"
|
||||||
# Save element object to entity for possible later use
|
# Save element object to entity for possible later use
|
||||||
entity._source_object = element
|
entity._source_object = element
|
||||||
|
# Save receiving guid to object
|
||||||
|
if user and hasattr(user, "guid"):
|
||||||
|
entity._receiving_guid = user.guid
|
||||||
# If relayable, fetch sender key for validation
|
# If relayable, fetch sender key for validation
|
||||||
if issubclass(cls, DiasporaRelayableMixin):
|
if issubclass(cls, DiasporaRelayableMixin):
|
||||||
entity._xml_tags = get_element_child_info(element, "tag")
|
entity._xml_tags = get_element_child_info(element, "tag")
|
||||||
|
@ -106,24 +110,25 @@ def element_to_objects(element, sender_key_fetcher=None):
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
|
|
||||||
def message_to_objects(message, sender_key_fetcher=None):
|
def message_to_objects(message, sender_key_fetcher=None, user=None):
|
||||||
"""Takes in a message extracted by a protocol and maps it to entities.
|
"""Takes in a message extracted by a protocol and maps it to entities.
|
||||||
|
|
||||||
:param message: XML payload
|
:param message: XML payload
|
||||||
:type message: str
|
:type message: str
|
||||||
:param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
|
:param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
|
||||||
over network. The function should take sender handle as the only parameter.
|
over network. The function should take sender handle as the only parameter.
|
||||||
|
:param user: Optional receiving user object. If given, should have a `handle`.
|
||||||
:returns: list of entities
|
:returns: list of entities
|
||||||
"""
|
"""
|
||||||
doc = etree.fromstring(message)
|
doc = etree.fromstring(message)
|
||||||
# Future Diaspora protocol version contains the element at top level
|
# Future Diaspora protocol version contains the element at top level
|
||||||
if doc.tag in TAGS:
|
if doc.tag in TAGS:
|
||||||
return element_to_objects(doc, sender_key_fetcher)
|
return element_to_objects(doc, sender_key_fetcher, user)
|
||||||
# Legacy Diaspora protocol wraps the element in <XML><post></post></XML>, so find the right element
|
# Legacy Diaspora protocol wraps the element in <XML><post></post></XML>, so find the right element
|
||||||
for tag in TAGS:
|
for tag in TAGS:
|
||||||
element = doc.find(".//%s" % tag)
|
element = doc.find(".//%s" % tag)
|
||||||
if element is not None:
|
if element is not None:
|
||||||
return element_to_objects(element, sender_key_fetcher)
|
return element_to_objects(element, sender_key_fetcher, user)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ def handle_receive(payload, user=None, sender_key_fetcher=None, skip_author_veri
|
||||||
could actually be a different identity.
|
could actually be a different identity.
|
||||||
|
|
||||||
:arg payload: Payload blob (str)
|
:arg payload: Payload blob (str)
|
||||||
:arg user: User that will be passed to `protocol.receive` (required on private encrypted content)
|
:arg user: User that will be passed to `protocol.receive` (only required on private encrypted content)
|
||||||
|
MUST have a `private_key` and `guid` if given.
|
||||||
:arg sender_key_fetcher: Function that accepts sender handle and returns public key (optional)
|
:arg sender_key_fetcher: Function that accepts sender handle and returns public key (optional)
|
||||||
:arg skip_author_verification: Don't verify sender (test purposes, false default)
|
:arg skip_author_verification: Don't verify sender (test purposes, false default)
|
||||||
:returns: Tuple of sender handle, protocol name and list of entity objects
|
:returns: Tuple of sender handle, protocol name and list of entity objects
|
||||||
|
@ -47,7 +48,7 @@ def handle_receive(payload, user=None, sender_key_fetcher=None, skip_author_veri
|
||||||
raise NoSuitableProtocolFoundError()
|
raise NoSuitableProtocolFoundError()
|
||||||
|
|
||||||
mappers = importlib.import_module("federation.entities.%s.mappers" % found_protocol.PROTOCOL_NAME)
|
mappers = importlib.import_module("federation.entities.%s.mappers" % found_protocol.PROTOCOL_NAME)
|
||||||
entities = mappers.message_to_objects(message, sender_key_fetcher)
|
entities = mappers.message_to_objects(message, sender_key_fetcher, user)
|
||||||
logger.debug("handle_receive: entities %s", entities)
|
logger.debug("handle_receive: entities %s", entities)
|
||||||
|
|
||||||
return sender, found_protocol.PROTOCOL_NAME, entities
|
return sender, found_protocol.PROTOCOL_NAME, entities
|
||||||
|
|
|
@ -156,13 +156,14 @@ class TestDiasporaEntityMappersReceive():
|
||||||
assert entity.entity_type == "Post"
|
assert entity.entity_type == "Post"
|
||||||
|
|
||||||
def test_message_to_objects_retraction_legacy_request(self):
|
def test_message_to_objects_retraction_legacy_request(self):
|
||||||
entities = message_to_objects(DIASPORA_LEGACY_REQUEST_RETRACTION)
|
entities = message_to_objects(DIASPORA_LEGACY_REQUEST_RETRACTION, user=Mock(guid="swfeuihiwehuifhiwheiuf"))
|
||||||
assert len(entities) == 1
|
assert len(entities) == 1
|
||||||
entity = entities[0]
|
entity = entities[0]
|
||||||
assert isinstance(entity, Retraction)
|
assert isinstance(entity, Retraction)
|
||||||
assert entity.handle == "jaywink@iliketoast.net"
|
assert entity.handle == "jaywink@iliketoast.net"
|
||||||
assert entity.target_guid == "7ed1555bc6ae03db"
|
assert entity.target_guid == "7ed1555bc6ae03db"
|
||||||
assert entity.entity_type == "Profile"
|
assert entity.entity_type == "Profile"
|
||||||
|
assert entity._receiving_guid == "swfeuihiwehuifhiwheiuf"
|
||||||
|
|
||||||
def test_message_to_objects_contact(self):
|
def test_message_to_objects_contact(self):
|
||||||
entities = message_to_objects(DIASPORA_CONTACT)
|
entities = message_to_objects(DIASPORA_CONTACT)
|
||||||
|
|
Ładowanie…
Reference in New Issue