Fix Accept delivery for Follow activities and actor profile
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 39s

- Fix sign_request() call: parse URL into path/host (was passing 'url' kwarg that doesn't exist)
- Fix verify_request_signature() call to match actual function signature
- Add manuallyApprovesFollowers: false to actor JSON-LD so Mastodon auto-accepts follows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-21 21:55:46 +00:00
parent f70f7d2f49
commit 725546f298

View File

@@ -62,12 +62,15 @@ async def _send_accept(
body_bytes = json.dumps(accept).encode() body_bytes = json.dumps(accept).encode()
key_id = f"{actor_url}#main-key" key_id = f"{actor_url}#main-key"
from urllib.parse import urlparse
parsed = urlparse(follower_inbox)
headers = sign_request( headers = sign_request(
method="POST",
url=follower_inbox,
body=body_bytes,
private_key_pem=actor.private_key_pem, private_key_pem=actor.private_key_pem,
key_id=key_id, key_id=key_id,
method="POST",
path=parsed.path,
host=parsed.netloc,
body=body_bytes,
) )
headers["Content-Type"] = AP_CONTENT_TYPE headers["Content-Type"] = AP_CONTENT_TYPE
@@ -107,6 +110,7 @@ def register(url_prefix="/users"):
"name": actor.display_name or username, "name": actor.display_name or username,
"preferredUsername": username, "preferredUsername": username,
"summary": actor.summary or "", "summary": actor.summary or "",
"manuallyApprovesFollowers": False,
"inbox": f"https://{domain}/users/{username}/inbox", "inbox": f"https://{domain}/users/{username}/inbox",
"outbox": f"https://{domain}/users/{username}/outbox", "outbox": f"https://{domain}/users/{username}/outbox",
"followers": f"https://{domain}/users/{username}/followers", "followers": f"https://{domain}/users/{username}/followers",
@@ -207,18 +211,20 @@ def register(url_prefix="/users"):
sig_valid = False sig_valid = False
try: try:
from shared.utils.http_signatures import verify_request_signature from shared.utils.http_signatures import verify_request_signature
raw_body = await request.get_data()
req_headers = dict(request.headers) req_headers = dict(request.headers)
req_headers["(request-target)"] = f"post /users/{username}/inbox" sig_header = req_headers.get("Signature", "")
# Fetch remote actor to get their public key # Fetch remote actor to get their public key
remote_actor = await _fetch_remote_actor(from_actor_url) remote_actor = await _fetch_remote_actor(from_actor_url)
if remote_actor: if remote_actor and sig_header:
pub_key_pem = (remote_actor.get("publicKey") or {}).get("publicKeyPem") pub_key_pem = (remote_actor.get("publicKey") or {}).get("publicKeyPem")
if pub_key_pem: if pub_key_pem:
sig_valid = verify_request_signature( sig_valid = verify_request_signature(
headers=req_headers,
public_key_pem=pub_key_pem, public_key_pem=pub_key_pem,
signature_header=sig_header,
method="POST",
path=f"/users/{username}/inbox",
headers=req_headers,
) )
except Exception: except Exception:
log.debug("Signature verification failed for %s", from_actor_url, exc_info=True) log.debug("Signature verification failed for %s", from_actor_url, exc_info=True)