From a951402dcbf972f58092ab1178d7122bc9925e2b Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 18 Sep 2026 04:19:37 -0600 Subject: [PATCH] Update account delete command, fix federation bug --- .../Commands/User/UserAccountDelete.php | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/app/Console/Commands/User/UserAccountDelete.php b/app/Console/Commands/User/UserAccountDelete.php index 3bc3715be..74e3e8e67 100644 --- a/app/Console/Commands/User/UserAccountDelete.php +++ b/app/Console/Commands/User/UserAccountDelete.php @@ -323,27 +323,30 @@ class UserAccountDelete extends Command $urlList = $urls->values()->all(); - $responses = Http::pool(function (Pool $pool) use ($urlList, $privateKey, $keyId, $digest, $payload, $payloadLen) { - foreach ($urlList as $url) { - // Pass User-Agent/Accept per request so they are actually sent - // (and signed); Http::pool does not inherit the makeHttpClient - // instance headers, so without this Guzzle sends its default UA. - $headers = HttpSignature::signRawWithDigest($privateKey, $keyId, $url, $digest, [ - 'User-Agent' => 'Pixelfed ('.config('app.url').')', - 'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"', - ]); - $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; - $headers['Content-Length'] = (string) $payloadLen; - - $pool->as($url) - ->timeout(10) - ->connectTimeout(5) - ->withOptions(['allow_redirects' => false]) - ->withHeaders($headers) - ->withBody($payload, 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"') - ->post($url); - } - }); + $responses = Http::pool( + function (Pool $pool) use ($urlList, $privateKey, $keyId, $digest, $payload, $payloadLen) { + foreach ($urlList as $url) { + // Pass User-Agent/Accept per request so they are actually sent + // (and signed); Http::pool does not inherit the makeHttpClient + // instance headers, so without this Guzzle sends its default UA. + $headers = HttpSignature::signRawWithDigest($privateKey, $keyId, $url, $digest, [ + 'User-Agent' => 'Pixelfed ('.config('app.url').')', + 'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + ]); + $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; + $headers['Content-Length'] = (string) $payloadLen; + + $pool->as($url) + ->timeout(10) + ->connectTimeout(5) + ->withOptions(['allow_redirects' => false]) + ->withHeaders($headers) + ->withBody($payload, 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"') + ->post($url); + } + }, + self::concurrency() + ); foreach ($urlList as $url) { $response = $responses[$url] ?? null; @@ -399,6 +402,14 @@ class UserAccountDelete extends Command ]; } + private static function concurrency(): int + { + return max( + 1, + (int) config('federation.activitypub.delivery.concurrency', 10) + ); + } + protected function sendDebug(string $url, string $payload, string $digest, string $privateKey, string $keyId): int { $headers = HttpSignature::signRawWithDigest($privateKey, $keyId, $url, $digest, [