Example #1
0
def test_get_actor(factories, r_mock):
    actor = factories["federation.Actor"].build()
    payload = serializers.ActorSerializer(actor).data
    r_mock.get(actor.fid, json=payload)
    new_actor = actors.get_actor(actor.fid)

    assert new_actor.pk is not None
    assert serializers.ActorSerializer(new_actor).data == payload
Example #2
0
def test_get_actor(factories, r_mock, mocker):
    update_domain_nodeinfo = mocker.patch(
        "funkwhale_api.federation.tasks.update_domain_nodeinfo")
    actor = factories["federation.Actor"].build()
    payload = serializers.ActorSerializer(actor).data
    r_mock.get(actor.fid, json=payload)
    new_actor = actors.get_actor(actor.fid)

    assert new_actor.pk is not None
    assert serializers.ActorSerializer(new_actor).data == payload
    update_domain_nodeinfo.assert_called_once_with(
        domain_name=new_actor.domain_id)
Example #3
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,
    )
Example #4
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
Example #5
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
Example #6
0
def test_actor_serializer_only_mandatory_field_from_ap(db):
    payload = {
        "id": "https://test.federation/user",
        "type": "Person",
        "following": "https://test.federation/user/following",
        "followers": "https://test.federation/user/followers",
        "inbox": "https://test.federation/user/inbox",
        "outbox": "https://test.federation/user/outbox",
        "preferredUsername": "******",
    }

    serializer = serializers.ActorSerializer(data=payload)
    assert serializer.is_valid(raise_exception=True)

    actor = serializer.build()

    assert actor.fid == payload["id"]
    assert actor.inbox_url == payload["inbox"]
    assert actor.outbox_url == payload["outbox"]
    assert actor.followers_url == payload["followers"]
    assert actor.following_url == payload["following"]
    assert actor.preferred_username == payload["preferredUsername"]
    assert actor.domain == "test.federation"
    assert actor.type == "Person"
    assert actor.manually_approves_followers is None
Example #7
0
def test_local_actor_detail(factories, api_client):
    user = factories["users.User"](with_actor=True)
    url = reverse(
        "federation:actors-detail",
        kwargs={"preferred_username": user.actor.preferred_username},
    )
    serializer = serializers.ActorSerializer(user.actor)
    response = api_client.get(url)

    assert response.status_code == 200
    assert response.data == serializer.data
Example #8
0
def test_service_actor_detail(factories, api_client):
    actor = actors.get_service_actor()
    url = reverse(
        "federation:actors-detail",
        kwargs={"preferred_username": actor.preferred_username},
    )
    serializer = serializers.ActorSerializer(actor)
    response = api_client.get(url)

    assert response.status_code == 200
    assert response.data == serializer.data
Example #9
0
def test_actor_serializer_to_ap():
    expected = {
        "@context": [
            "https://www.w3.org/ns/activitystreams",
            "https://w3id.org/security/v1",
            {},
        ],
        "id":
        "https://test.federation/user",
        "type":
        "Person",
        "following":
        "https://test.federation/user/following",
        "followers":
        "https://test.federation/user/followers",
        "inbox":
        "https://test.federation/user/inbox",
        "outbox":
        "https://test.federation/user/outbox",
        "preferredUsername":
        "******",
        "name":
        "Real User",
        "summary":
        "Hello world",
        "manuallyApprovesFollowers":
        False,
        "publicKey": {
            "id": "https://test.federation/user#main-key",
            "owner": "https://test.federation/user",
            "publicKeyPem": "yolo",
        },
        "endpoints": {
            "sharedInbox": "https://test.federation/inbox"
        },
    }
    ac = models.Actor(
        fid=expected["id"],
        inbox_url=expected["inbox"],
        outbox_url=expected["outbox"],
        shared_inbox_url=expected["endpoints"]["sharedInbox"],
        followers_url=expected["followers"],
        following_url=expected["following"],
        public_key=expected["publicKey"]["publicKeyPem"],
        preferred_username=expected["preferredUsername"],
        name=expected["name"],
        domain="test.federation",
        summary=expected["summary"],
        type="Person",
        manually_approves_followers=False,
    )
    serializer = serializers.ActorSerializer(ac)

    assert serializer.data == expected
Example #10
0
def test_get_actor_refresh(factories, preferences, mocker):
    preferences["federation__actor_fetch_delay"] = 0
    actor = factories["federation.Actor"]()
    payload = serializers.ActorSerializer(actor).data
    # actor changed their username in the meantime
    payload["preferredUsername"] = "******"
    mocker.patch("funkwhale_api.federation.actors.get_actor_data", return_value=payload)
    new_actor = actors.get_actor(actor.fid)

    assert new_actor == actor
    assert new_actor.last_fetch_date > actor.last_fetch_date
    assert new_actor.preferred_username == "New me"
Example #11
0
def test_actor_serializer_from_ap(db):
    payload = {
        "id": "https://test.federation/user",
        "type": "Person",
        "following": "https://test.federation/user/following",
        "followers": "https://test.federation/user/followers",
        "inbox": "https://test.federation/user/inbox",
        "outbox": "https://test.federation/user/outbox",
        "preferredUsername": "******",
        "name": "Real User",
        "summary": "Hello world",
        "url": "https://test.federation/@user",
        "manuallyApprovesFollowers": False,
        "publicKey": {
            "id": "https://test.federation/user#main-key",
            "owner": "https://test.federation/user",
            "publicKeyPem": "yolo",
        },
        "endpoints": {
            "sharedInbox": "https://test.federation/inbox"
        },
    }

    serializer = serializers.ActorSerializer(data=payload)
    assert serializer.is_valid(raise_exception=True)

    actor = serializer.build()

    assert actor.fid == payload["id"]
    assert actor.inbox_url == payload["inbox"]
    assert actor.outbox_url == payload["outbox"]
    assert actor.shared_inbox_url == payload["endpoints"]["sharedInbox"]
    assert actor.followers_url == payload["followers"]
    assert actor.following_url == payload["following"]
    assert actor.public_key == payload["publicKey"]["publicKeyPem"]
    assert actor.preferred_username == payload["preferredUsername"]
    assert actor.name == payload["name"]
    assert actor.domain == "test.federation"
    assert actor.summary == payload["summary"]
    assert actor.type == "Person"
    assert actor.manually_approves_followers == payload[
        "manuallyApprovesFollowers"]
def test_reel2bits_channel_from_actor_ap(db, mocker):
    mocker.patch("funkwhale_api.federation.tasks.update_domain_nodeinfo")
    payload = {
        "@context": [
            "https://www.w3.org/ns/activitystreams",
            "https://w3id.org/security/v1",
            {
                "Hashtag": "as:Hashtag",
                "PropertyValue": "schema:PropertyValue",
                "artwork": "reel2bits:artwork",
                "featured": "toot:featured",
                "genre": "reel2bits:genre",
                "licence": "reel2bits:licence",
                "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
                "reel2bits": "http://reel2bits.org/ns#",
                "schema": "http://schema.org#",
                "sensitive": "as:sensitive",
                "tags": "reel2bits:tags",
                "toot": "http://joinmastodon.org/ns#",
                "transcode_url": "reel2bits:transcode_url",
                "transcoded": "reel2bits:transcoded",
                "value": "schema:value",
            },
        ],
        "endpoints": {
            "sharedInbox": "https://r2b.example/inbox"
        },
        "followers":
        "https://r2b.example/user/anna/followers",
        "following":
        "https://r2b.example/user/anna/followings",
        "icon": {
            "type": "Image",
            "url": "https://r2b.example/uploads/avatars/anna/f4930.jpg",
        },
        "id":
        "https://r2b.example/user/anna",
        "inbox":
        "https://r2b.example/user/anna/inbox",
        "manuallyApprovesFollowers":
        False,
        "name":
        "Anna",
        "outbox":
        "https://r2b.example/user/anna/outbox",
        "preferredUsername":
        "******",
        "publicKey": {
            "id": "https://r2b.example/user/anna#main-key",
            "owner": "https://r2b.example/user/anna",
            "publicKeyPem": "MIIBIxaeikqh",
        },
        "type":
        "Person",
        "url": [
            {
                "type": "Link",
                "mediaType": "text/html",
                "href": "https://r2b.example/@anna",
            },
            {
                "type": "Link",
                "mediaType": "application/rss+xml",
                "href": "https://r2b.example/@anna.rss",
            },
        ],
    }

    serializer = serializers.ActorSerializer(data=payload)
    assert serializer.is_valid(raise_exception=True)
    actor = serializer.save()

    assert actor.fid == payload["id"]
    assert actor.url == payload["url"][0]["href"]
    assert actor.inbox_url == payload["inbox"]
    assert actor.shared_inbox_url == payload["endpoints"]["sharedInbox"]
    assert actor.outbox_url is payload["outbox"]
    assert actor.following_url == payload["following"]
    assert actor.followers_url == payload["followers"]
    assert actor.followers_url == payload["followers"]
    assert actor.type == payload["type"]
    assert actor.preferred_username == payload["preferredUsername"]
    assert actor.name == payload["name"]
    assert actor.manually_approves_followers is payload[
        "manuallyApprovesFollowers"]
    assert actor.private_key is None
    assert actor.public_key == payload["publicKey"]["publicKeyPem"]
    assert actor.domain_id == "r2b.example"

    channel = actor.get_channel()

    assert channel.attributed_to == actor
    assert channel.rss_url == payload["url"][1]["href"]
    assert channel.artist.name == actor.name
    assert channel.artist.attributed_to == actor
def test_pleroma_actor_from_ap(factories):

    payload = {
        "@context": [
            "https://www.w3.org/ns/activitystreams",
            "https://test.federation/schemas/litepub-0.1.jsonld",
            {
                "@language": "und"
            },
        ],
        "endpoints": {
            "oauthAuthorizationEndpoint":
            "https://test.federation/oauth/authorize",
            "oauthRegistrationEndpoint": "https://test.federation/api/v1/apps",
            "oauthTokenEndpoint": "https://test.federation/oauth/token",
            "sharedInbox": "https://test.federation/inbox",
            "uploadMedia": "https://test.federation/api/ap/upload_media",
        },
        "followers":
        "https://test.federation/internal/fetch/followers",
        "following":
        "https://test.federation/internal/fetch/following",
        "id":
        "https://test.federation/internal/fetch",
        "inbox":
        "https://test.federation/internal/fetch/inbox",
        "invisible":
        True,
        "manuallyApprovesFollowers":
        False,
        "name":
        "Pleroma",
        "preferredUsername":
        "******",
        "publicKey": {
            "id": "https://test.federation/internal/fetch#main-key",
            "owner": "https://test.federation/internal/fetch",
            "publicKeyPem": "PEM",
        },
        "summary":
        "An internal service actor for this Pleroma instance.  No user-serviceable parts inside.",
        "type":
        "Application",
        "url":
        "https://test.federation/internal/fetch",
    }

    serializer = serializers.ActorSerializer(data=payload)
    assert serializer.is_valid(raise_exception=True)
    actor = serializer.save()

    assert actor.fid == payload["id"]
    assert actor.url == payload["url"]
    assert actor.inbox_url == payload["inbox"]
    assert actor.shared_inbox_url == payload["endpoints"]["sharedInbox"]
    assert actor.outbox_url is None
    assert actor.following_url == payload["following"]
    assert actor.followers_url == payload["followers"]
    assert actor.followers_url == payload["followers"]
    assert actor.type == payload["type"]
    assert actor.preferred_username == payload["preferredUsername"]
    assert actor.name == payload["name"]
    assert actor.summary_obj.text == payload["summary"]
    assert actor.summary_obj.content_type == "text/html"
    assert actor.fid == payload["url"]
    assert actor.manually_approves_followers is payload[
        "manuallyApprovesFollowers"]
    assert actor.private_key is None
    assert actor.public_key == payload["publicKey"]["publicKeyPem"]
    assert actor.domain_id == "test.federation"
Example #14
0
def test_local_actor_serializer_to_ap(factories):
    expected = {
        "@context": [
            "https://www.w3.org/ns/activitystreams",
            "https://w3id.org/security/v1",
            {},
        ],
        "id":
        "https://test.federation/user",
        "type":
        "Person",
        "following":
        "https://test.federation/user/following",
        "followers":
        "https://test.federation/user/followers",
        "inbox":
        "https://test.federation/user/inbox",
        "outbox":
        "https://test.federation/user/outbox",
        "preferredUsername":
        "******",
        "name":
        "Real User",
        "summary":
        "Hello world",
        "manuallyApprovesFollowers":
        False,
        "publicKey": {
            "id": "https://test.federation/user#main-key",
            "owner": "https://test.federation/user",
            "publicKeyPem": "yolo",
        },
        "endpoints": {
            "sharedInbox": "https://test.federation/inbox"
        },
    }
    ac = models.Actor.objects.create(
        fid=expected["id"],
        inbox_url=expected["inbox"],
        outbox_url=expected["outbox"],
        shared_inbox_url=expected["endpoints"]["sharedInbox"],
        followers_url=expected["followers"],
        following_url=expected["following"],
        public_key=expected["publicKey"]["publicKeyPem"],
        preferred_username=expected["preferredUsername"],
        name=expected["name"],
        domain="test.federation",
        summary=expected["summary"],
        type="Person",
        manually_approves_followers=False,
    )
    user = factories["users.User"]()
    user.actor = ac
    user.save()
    ac.refresh_from_db()
    expected["icon"] = {
        "type": "Image",
        "mediaType": "image/jpeg",
        "url": utils.full_url(user.avatar.crop["400x400"].url),
    }
    serializer = serializers.ActorSerializer(ac)

    assert serializer.data == expected