component AP gateway: don't percent-encode @:

Mastodon doesn't like when "@" is percent-encoded (because it doesn't do it, and it checks
that the URL matches the ID without taking care of percent-encoding).
This commit is contained in:
Goffi 2023-02-10 17:20:02 +01:00
commit 52f7a2b11f
3 changed files with 21 additions and 18 deletions

View file

@ -838,7 +838,7 @@ class APGateway:
"""
return parse.urljoin(
self.base_ap_url,
str(Path(type_).joinpath(*(parse.quote_plus(a) for a in args)))
str(Path(type_).joinpath(*(parse.quote_plus(a, safe="@") for a in args)))
)
def isLocalURL(self, url: str) -> bool:

View file

@ -592,7 +592,9 @@ class HTTPAPGServer(web_resource.Resource):
"https://w3id.org/security/v1"
],
"id": ap_url,
# XXX: Mastodon doesn't like percent-encode arobas, so we have to unescape it
# if it is escaped
"id": ap_url.replace("%40", "@"),
"type": "Person",
"preferredUsername": preferred_username,
"inbox": inbox,
@ -637,7 +639,8 @@ class HTTPAPGServer(web_resource.Resource):
return parse.urljoin(
f"https://{self.apg.public_url}",
request.path.decode().rstrip("/")
)
# we unescape "@" for the same reason as in [APActorRequest]
).replace("%40", "@")
def queryData2RSMRequest(
self,

View file

@ -255,7 +255,7 @@ AP_REQUESTS = {
"id": f"{TEST_BASE_URL}/users/{TEST_USER}/following?page=1",
"orderedItems": [
f"{TEST_BASE_URL}/users/ext_user",
f"https://{PUBLIC_URL}/_ap/{TYPE_ACTOR}/local_user%40{PUBLIC_URL}",
f"https://{PUBLIC_URL}/_ap/{TYPE_ACTOR}/local_user@{PUBLIC_URL}",
],
"partOf": "{TEST_BASE_URL}/users/{TEST_USER}/following",
"totalItems": 2,
@ -273,7 +273,7 @@ AP_REQUESTS = {
"id": f"{TEST_BASE_URL}/users/{TEST_USER}/followers?page=1",
"orderedItems": [
f"{TEST_BASE_URL}/users/ext_user",
f"https://{PUBLIC_URL}/_ap/{TYPE_ACTOR}/local_user%40{PUBLIC_URL}",
f"https://{PUBLIC_URL}/_ap/{TYPE_ACTOR}/local_user@{PUBLIC_URL}",
],
"partOf": "{TEST_BASE_URL}/users/{TEST_USER}/followers",
"totalItems": 2,
@ -643,7 +643,7 @@ class TestActivityPubGateway:
"""
assert type_ and url is None or url and type_ is None
if type_ is not None:
path = f"_ap/{type_}/some_user%40test.example"
path = f"_ap/{type_}/some_user@test.example"
else:
url_parsed = parse.urlparse(url)
path = url_parsed.path.lstrip("/")
@ -685,7 +685,7 @@ class TestActivityPubGateway:
**self.ap_request_params(ap_gateway, "outbox")
)
assert outbox["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert outbox["id"] == "https://test.example/_ap/outbox/some_user%40test.example"
assert outbox["id"] == "https://test.example/_ap/outbox/some_user@test.example"
assert outbox["totalItems"] == len(XMPP_ITEMS)
assert outbox["type"] == "OrderedCollection"
assert outbox["first"]
@ -697,7 +697,7 @@ class TestActivityPubGateway:
assert first_page["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert (
first_page["id"]
== "https://test.example/_ap/outbox/some_user%40test.example?page=first"
== "https://test.example/_ap/outbox/some_user@test.example?page=first"
)
assert first_page["type"] == "OrderedCollectionPage"
assert first_page["partOf"] == outbox["id"]
@ -705,11 +705,11 @@ class TestActivityPubGateway:
first_item = first_page["orderedItems"][0]
assert first_item["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert (
first_item["id"] == "https://test.example/_ap/item/some_user%40test.example/4"
first_item["id"] == "https://test.example/_ap/item/some_user@test.example/4"
)
assert (
first_item["actor"]
== "https://test.example/_ap/actor/some_user%40test.example"
== "https://test.example/_ap/actor/some_user@test.example"
)
assert first_item["type"] == "Create"
first_item_obj = first_item["object"]
@ -794,7 +794,7 @@ class TestActivityPubGateway:
assert following["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert (
following["id"]
== "https://test.example/_ap/following/some_user%40test.example"
== "https://test.example/_ap/following/some_user@test.example"
)
assert following["totalItems"] == len(subscriptions)
assert following["type"] == "OrderedCollection"
@ -832,7 +832,7 @@ class TestActivityPubGateway:
assert followers["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert (
followers["id"]
== "https://test.example/_ap/followers/some_user%40test.example"
== "https://test.example/_ap/followers/some_user@test.example"
)
assert followers["totalItems"] == len(subscribers)
assert followers["type"] == "OrderedCollection"
@ -861,14 +861,14 @@ class TestActivityPubGateway:
await ap_gateway.onMessage(ap_gateway.client, mess_data)
url, actor_id, doc = signAndPost.call_args[0]
assert url == "https://example.org/users/test_user/inbox"
assert actor_id == "https://test.example/_ap/actor/some_user%40test.example"
assert actor_id == "https://test.example/_ap/actor/some_user@test.example"
obj = doc["object"]
assert doc["@context"] == ["https://www.w3.org/ns/activitystreams"]
assert doc["actor"] == "https://test.example/_ap/actor/some_user%40test.example"
assert doc["actor"] == "https://test.example/_ap/actor/some_user@test.example"
assert obj["type"] == "Note"
assert obj["content"] == "This is a test message."
assert obj["attributedTo"] == (
"https://test.example/_ap/actor/some_user%40test.example"
"https://test.example/_ap/actor/some_user@test.example"
)
# we must have a direct message, thus the item must be only addressed to destinee
# ("to" attribute of the message), and the "Public" namespace must not be set
@ -1669,11 +1669,11 @@ class TestActivityPubGateway:
ap_object = ap_item["object"]
actor_id = (
"https://test.example/_ap/actor/"
"___urn.3Axmpp.3Aevents.3A0---some_user%40test.example"
"___urn.3Axmpp.3Aevents.3A0---some_user@test.example"
)
event_id = (
"https://test.example/_ap/item/"
"___urn.3Axmpp.3Aevents.3A0---some_user%40test.example/event_123"
"___urn.3Axmpp.3Aevents.3A0---some_user@test.example/event_123"
)
assert ap_object["name"] == "test event"
assert ap_object["actor"] == actor_id
@ -1700,7 +1700,7 @@ class TestActivityPubGateway:
@ed
async def test_ap_event_2_xmpp_event(self, ap_gateway):
"""AP events are converted to XMPP events"""
test_actor = "___urn.3Axmpp.3Aevents.3A0---some_user%40test.example"
test_actor = "___urn.3Axmpp.3Aevents.3A0---some_user@test.example"
ap_object = {
"actor": f"https://test.example/_ap/actor/{test_actor}",
"attachment": [