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:
parent
895ddd36be
commit
52f7a2b11f
3 changed files with 21 additions and 18 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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": [
|
||||
|
|
|
|||
Loading…
Reference in a new issue