Exemple #1
0
def test_fetch_channel_actor_returns_channel_and_fetch_outbox(
        factories, r_mock, settings, mocker):
    obj = factories["audio.Channel"]()
    fetch = factories["federation.Fetch"](url=obj.actor.fid)
    payload = serializers.ActorSerializer(obj.actor).data
    fetch_collection = mocker.patch.object(
        tasks,
        "fetch_collection",
        return_value={"next_page": "http://outbox.url/page2"})
    fetch_collection_delayed = mocker.patch.object(tasks.fetch_collection,
                                                   "delay")

    r_mock.get(obj.fid, json=payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "finished"
    assert fetch.object == obj
    fetch_collection.assert_called_once_with(
        obj.actor.outbox_url,
        channel_id=obj.pk,
        max_pages=1,
    )
    fetch_collection_delayed.assert_called_once_with(
        "http://outbox.url/page2",
        max_pages=settings.FEDERATION_COLLECTION_MAX_PAGES - 1,
        is_page=True,
        channel_id=obj.pk,
    )
Exemple #2
0
def test_fetch_rel_alternate(factories, r_mock, mocker):
    actor = factories["federation.Actor"]()
    fetch = factories["federation.Fetch"](url="http://example.page")
    html_text = """
    <html>
        <head>
            <link rel="alternate" type="application/activity+json" href="{}" />
        </head>
    </html>
    """.format(actor.fid)
    ap_payload = serializers.ActorSerializer(actor).data
    init = mocker.spy(serializers.ActorSerializer, "__init__")
    save = mocker.spy(serializers.ActorSerializer, "save")
    r_mock.get(fetch.url, text=html_text)
    r_mock.get(actor.fid, json=ap_payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "finished"
    assert fetch.object == actor
    assert init.call_count == 1
    assert init.call_args[0][1] == actor
    assert init.call_args[1]["data"] == ap_payload
    assert save.call_count == 1
Exemple #3
0
def test_fetch_webfinger(factories, r_mock, mocker):
    actor = factories["federation.Actor"]()
    fetch = factories["federation.Fetch"](
        url="webfinger://{}".format(actor.full_username))
    payload = serializers.ActorSerializer(actor).data
    init = mocker.spy(serializers.ActorSerializer, "__init__")
    save = mocker.spy(serializers.ActorSerializer, "save")
    webfinger_payload = {
        "subject":
        "acct:{}".format(actor.full_username),
        "aliases": ["https://test.webfinger"],
        "links": [{
            "rel": "self",
            "type": "application/activity+json",
            "href": actor.fid
        }],
    }
    webfinger_url = "https://{}/.well-known/webfinger?resource={}".format(
        actor.domain_id, webfinger_payload["subject"])
    r_mock.get(actor.fid, json=payload)
    r_mock.get(webfinger_url, json=webfinger_payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "finished"
    assert fetch.object == actor
    assert init.call_count == 1
    assert init.call_args[0][1] == actor
    assert init.call_args[1]["data"] == payload
    assert save.call_count == 1
Exemple #4
0
def refetch_obj(obj, queryset):
    """
    Given an Artist/Album/Track instance, if the instance is from a remote pod,
    will attempt to update local data with the latest ActivityPub representation.
    """
    if obj.is_local:
        return obj

    now = timezone.now()
    limit = now - datetime.timedelta(minutes=settings.FEDERATION_OBJECT_FETCH_DELAY)
    last_fetch = obj.fetches.order_by("-creation_date").first()
    if last_fetch is not None and last_fetch.creation_date > limit:
        # we fetched recently, no need to do it again
        return obj

    logger.info("Refetching %s:%s at %s…", obj._meta.label, obj.pk, obj.fid)
    actor = actors.get_service_actor()
    fetch = federation_models.Fetch.objects.create(actor=actor, url=obj.fid, object=obj)
    try:
        federation_tasks.fetch(fetch_id=fetch.pk)
    except Exception:
        logger.exception(
            "Error while refetching %s:%s at %s…", obj._meta.label, obj.pk, obj.fid
        )
    else:
        fetch.refresh_from_db()
        if fetch.status == "finished":
            obj = queryset.get(pk=obj.pk)
    return obj
Exemple #5
0
def test_fetch_honor_instance_policy_different_url_and_id(r_mock, factories):
    domain = factories["moderation.InstancePolicy"](
        block_all=True, for_domain=True).target_domain
    fid = "https://ok/test"
    r_mock.get(fid, json={"id": "http://{}/test".format(domain.name)})
    fetch = factories["federation.Fetch"](url=fid)
    tasks.fetch(fetch_id=fetch.pk)
    fetch.refresh_from_db()

    assert fetch.status == "errored"
    assert fetch.detail["error_code"] == "blocked"
Exemple #6
0
def test_fetch_honor_instance_policy_domain(factories):
    domain = factories["moderation.InstancePolicy"](
        block_all=True, for_domain=True).target_domain
    fid = "https://{}/test".format(domain.name)

    fetch = factories["federation.Fetch"](url=fid)
    tasks.fetch(fetch_id=fetch.pk)
    fetch.refresh_from_db()

    assert fetch.status == "errored"
    assert fetch.detail["error_code"] == "blocked"
Exemple #7
0
def test_fetch_errored(factories, r_mock_args, expected_error_code, r_mock):
    url = "https://fetch.object"
    fetch = factories["federation.Fetch"](url=url)
    r_mock.get(url, **r_mock_args)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "errored"
    assert fetch.detail["error_code"] == expected_error_code
Exemple #8
0
def test_fetch_skipped(factories, r_mock):
    url = "https://fetch.object"
    fetch = factories["federation.Fetch"](url=url)
    payload = {"@context": jsonld.get_default_context(), "type": "Unhandled"}
    r_mock.get(url, json=payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "skipped"
    assert fetch.detail["reason"] == "unhandled_type"
Exemple #9
0
def test_fetch_honor_mrf_inbox_before_http(mrf_inbox_registry, factories,
                                           mocker):
    apply = mocker.patch.object(mrf_inbox_registry,
                                "apply",
                                return_value=(None, False))
    fid = "http://domain/test"
    fetch = factories["federation.Fetch"](url=fid)
    tasks.fetch(fetch_id=fetch.pk)
    fetch.refresh_from_db()

    assert fetch.status == "errored"
    assert fetch.detail["error_code"] == "blocked"
    apply.assert_called_once_with({"id": fid})
Exemple #10
0
def test_fetch_honor_mrf_inbox_after_http(r_mock, mrf_inbox_registry,
                                          factories, mocker):
    apply = mocker.patch.object(mrf_inbox_registry,
                                "apply",
                                side_effect=[(True, False), (None, False)])
    payload = {"id": "http://domain/test", "actor": "hello"}
    r_mock.get(payload["id"], json=payload)
    fetch = factories["federation.Fetch"](url=payload["id"])
    tasks.fetch(fetch_id=fetch.pk)
    fetch.refresh_from_db()

    assert fetch.status == "errored"
    assert fetch.detail["error_code"] == "blocked"

    apply.assert_any_call({"id": payload["id"]})
    apply.assert_any_call(payload)
Exemple #11
0
def test_fetch_success(factories, r_mock, mocker):
    artist = factories["music.Artist"]()
    fetch = factories["federation.Fetch"](url=artist.fid)
    payload = serializers.ArtistSerializer(artist).data
    init = mocker.spy(serializers.ArtistSerializer, "__init__")
    save = mocker.spy(serializers.ArtistSerializer, "save")

    r_mock.get(artist.fid, json=payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "finished"
    assert init.call_count == 1
    assert init.call_args[0][1] == artist
    assert init.call_args[1]["data"] == payload
    assert save.call_count == 1
Exemple #12
0
def test_fetch_url(factory_name, factory_kwargs, serializer_class, factories,
                   r_mock, mocker):
    obj = factories[factory_name](**factory_kwargs)
    fetch = factories["federation.Fetch"](url=obj.fid)
    payload = serializer_class(obj).data
    init = mocker.spy(serializer_class, "__init__")
    save = mocker.spy(serializer_class, "save")

    r_mock.get(obj.fid, json=payload)

    tasks.fetch(fetch_id=fetch.pk)

    fetch.refresh_from_db()

    assert fetch.status == "finished"
    assert fetch.object == obj
    assert init.call_count == 1
    assert init.call_args[0][1] == obj
    assert init.call_args[1]["data"] == payload
    assert save.call_count == 1