Esempio n. 1
0
 def fill_extra_attributes(attributes):
     """Diaspora Profile XML message contains no GUID. We need the guid. Fetch it."""
     if not attributes.get("handle"):
         raise ValueError("Can't fill GUID for profile creation since there is no handle! Attrs: %s" % attributes)
     profile = retrieve_and_parse_profile(attributes.get("handle"))
     attributes["guid"] = profile.guid
     return attributes
Esempio n. 2
0
 def fill_extra_attributes(attributes):
     """Diaspora Profile XML message contains no GUID. We need the guid. Fetch it."""
     if not attributes.get("handle"):
         raise ValueError("Can't fill GUID for profile creation since there is no handle! Attrs: %s" % attributes)
     profile = retrieve_and_parse_profile(attributes.get("handle"))
     attributes["guid"] = profile.guid
     return attributes
Esempio n. 3
0
 def test_parse_profile_from_hcard_called(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     retrieve_and_parse_profile("foo@bar")
     mock_parse.assert_called_with(hcard, "foo@bar")
Esempio n. 4
0
 def test_parse_profile_from_hcard_called(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     retrieve_and_parse_profile("foo@bar")
     mock_parse.assert_called_with(hcard, "foo@bar")
Esempio n. 5
0
 def test_profile_validate_is_called(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     mock_profile = Mock()
     mock_parse.return_value = mock_profile
     retrieve_and_parse_profile("foo@bar")
     assert mock_profile.validate.called
Esempio n. 6
0
 def test_profile_validate_is_called(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     mock_profile = Mock()
     mock_parse.return_value = mock_profile
     retrieve_and_parse_profile("foo@bar")
     assert mock_profile.validate.called
Esempio n. 7
0
 def test_profile_that_doesnt_validate_returns_none(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     mock_parse.return_value = Profile(guid="123")
     profile = retrieve_and_parse_profile("foo@bar")
     assert profile == None
Esempio n. 8
0
 def test_profile_that_doesnt_validate_returns_none(self, mock_retrieve, mock_parse):
     hcard = generate_hcard(
         "diaspora",
         hostname="https://hostname",
         fullname="fullname",
         firstname="firstname",
         lastname="lastname",
         photo300="photo300",
         photo100="photo100",
         photo50="photo50",
         searchable="true",
         guid="guid",
         public_key="public_key",
         username="******",
     )
     mock_retrieve.return_value = hcard
     mock_parse.return_value = Profile(guid="123")
     profile = retrieve_and_parse_profile("foo@bar")
     assert profile == None
Esempio n. 9
0
def element_to_objects(
        element: etree.ElementTree, sender: str, sender_key_fetcher: Callable[[str], str] = None, user: UserType = None,
) -> List:
    """Transform an Element to a list of entities recursively.

    Possible child entities are added to each entity ``_children`` list.

    Optional parameter ``sender_key_fetcher`` can be a function to fetch sender public key.
    If not given, key will always be fetched over the network. The function should take sender as the only parameter.
    """
    entities = []
    cls = MAPPINGS.get(element.tag)
    if not cls:
        return []

    attrs = xml_children_as_dict(element)
    transformed = transform_attributes(attrs, cls)
    if hasattr(cls, "fill_extra_attributes"):
        transformed = cls.fill_extra_attributes(transformed)
    entity = cls(**transformed)
    # Add protocol name
    entity._source_protocol = "diaspora"
    # Save element object to entity for possible later use
    entity._source_object = etree.tostring(element)

    # Save receivers on the entity
    if user:
        # Single receiver
        entity._receivers = [UserType(id=user.id, receiver_variant=ReceiverVariant.ACTOR)]
    else:
        # Followers
        entity._receivers = [UserType(id=sender, receiver_variant=ReceiverVariant.FOLLOWERS)]

    if issubclass(cls, DiasporaRelayableMixin):
        # If relayable, fetch sender key for validation
        entity._xml_tags = get_element_child_info(element, "tag")
        if sender_key_fetcher:
            entity._sender_key = sender_key_fetcher(entity.actor_id)
        else:
            profile = retrieve_and_parse_profile(entity.handle)
            if profile:
                entity._sender_key = profile.public_key
    else:
        # If not relayable, ensure handles match
        if not check_sender_and_entity_handle_match(sender, entity.handle):
            return []
    try:
        entity.validate()
    except ValueError as ex:
        logger.error("Failed to validate entity %s: %s", entity, ex, extra={
            "attrs": attrs,
            "transformed": transformed,
        })
        return []

    # Extract mentions
    if hasattr(entity, "extract_mentions"):
        entity.extract_mentions()

    # Do child elements
    for child in element:
        # noinspection PyProtectedMember
        entity._children.extend(element_to_objects(child, sender, user=user))
    # Add to entities list
    entities.append(entity)
    return entities
Esempio n. 10
0
def transform_attributes(attrs, cls):
    """Transform some attribute keys.

    :param attrs: Properties from the XML
    :type attrs: dict
    :param cls: Class of the entity
    :type cls: class
    """
    transformed = {}
    for key, value in attrs.items():
        if value is None:
            value = ""
        if key == "text":
            transformed["raw_content"] = value
        elif key == "activitypub_id":
            transformed["id"] = value
        elif key == "author":
            if cls == DiasporaProfile:
                # Diaspora Profile XML message contains no GUID. We need the guid. Fetch it.
                profile = retrieve_and_parse_profile(value)
                transformed['id'] = value
                transformed["guid"] = profile.guid
            else:
                transformed["actor_id"] = value
            transformed["handle"] = value
        elif key == 'guid':
            if cls != DiasporaProfile:
                transformed["id"] = value
                transformed["guid"] = value
        elif key in ("root_author", "recipient"):
            transformed["target_id"] = value
            transformed["target_handle"] = value
        elif key in ("target_guid", "root_guid", "parent_guid"):
            transformed["target_id"] = value
            transformed["target_guid"] = value
        elif key == "thread_parent_guid":
            transformed["root_target_id"] = value
            transformed["root_target_guid"] = value
        elif key in ("first_name", "last_name"):
            values = [attrs.get('first_name'), attrs.get('last_name')]
            values = [v for v in values if v]
            transformed["name"] = " ".join(values)
        elif key == "image_url":
            if "image_urls" not in transformed:
                transformed["image_urls"] = {}
            transformed["image_urls"]["large"] = value
        elif key == "image_url_small":
            if "image_urls" not in transformed:
                transformed["image_urls"] = {}
            transformed["image_urls"]["small"] = value
        elif key == "image_url_medium":
            if "image_urls" not in transformed:
                transformed["image_urls"] = {}
            transformed["image_urls"]["medium"] = value
        elif key == "tag_string":
            if value:
                transformed["tag_list"] = value.replace("#", "").split(" ")
        elif key == "bio":
            transformed["raw_content"] = value
        elif key == "searchable":
            transformed["public"] = True if value == "true" else False
        elif key in ["target_type"] and cls == DiasporaRetraction:
            transformed["entity_type"] = DiasporaRetraction.entity_type_from_remote(value)
        elif key == "remote_photo_path":
            transformed["url"] = f"{value}{attrs.get('remote_photo_name')}"
        elif key == "author_signature":
            transformed["signature"] = value
        elif key in BOOLEAN_KEYS:
            transformed[key] = True if value == "true" else False
        elif key in DATETIME_KEYS:
            transformed[key] = datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
        elif key in INTEGER_KEYS:
            transformed[key] = int(value)
        else:
            transformed[key] = value
    return transformed
Esempio n. 11
0
def element_to_objects(element, sender, sender_key_fetcher=None, user=None):
    """Transform an Element to a list of entities recursively.

    Possible child entities are added to each entity `_children` list.

    :param tree: Element
    :param sender: Payload sender handle
    :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.
    :param user: Optional receiving user object. If given, should have a `handle`.
    :returns: list of entities
    """
    entities = []
    cls = MAPPINGS.get(element.tag, None)
    if not cls:
        return []

    attrs = xml_children_as_dict(element)
    transformed = transform_attributes(attrs, cls)
    if hasattr(cls, "fill_extra_attributes"):
        transformed = cls.fill_extra_attributes(transformed)
    entity = cls(**transformed)
    # Add protocol name
    entity._source_protocol = "diaspora"
    # Save element object to entity for possible later use
    entity._source_object = etree.tostring(element)
    # Save receiving guid to object
    if user and hasattr(user, "guid"):
        entity._receiving_guid = user.guid
    if issubclass(cls, DiasporaRelayableMixin):
        # If relayable, fetch sender key for validation
        entity._xml_tags = get_element_child_info(element, "tag")
        if sender_key_fetcher:
            entity._sender_key = sender_key_fetcher(entity.handle)
        else:
            profile = retrieve_and_parse_profile(entity.handle)
            if profile:
                entity._sender_key = profile.public_key
    else:
        # If not relayable, ensure handles match
        if not check_sender_and_entity_handle_match(sender, entity.handle):
            return []
    try:
        entity.validate()
    except ValueError as ex:
        logger.error("Failed to validate entity %s: %s",
                     entity,
                     ex,
                     extra={
                         "attrs": attrs,
                         "transformed": transformed,
                     })
        return []
    # Do child elements
    for child in element:
        entity._children.extend(element_to_objects(child, sender))
    # Add to entities list
    entities.append(entity)
    if cls == DiasporaRequest:
        # We support sharing/following separately, so also generate base Relationship for the following part
        transformed.update({"relationship": "following"})
        relationship = Relationship(**transformed)
        entities.append(relationship)
    return entities
Esempio n. 12
0
 def test_retrieve_diaspora_hcard_is_called(self, mock_retrieve):
     retrieve_and_parse_profile("foo@bar")
     mock_retrieve.assert_called_with("foo@bar")
Esempio n. 13
0
 def test_retrieve_diaspora_hcard_is_called(self, mock_retrieve):
     retrieve_and_parse_profile("foo@bar")
     mock_retrieve.assert_called_with("foo@bar")