Merge pull request #9586 from annando/inbox-status

Don't transmit to archived inboxes
This commit is contained in:
Hypolite Petovan 2020-11-24 03:04:03 -05:00 committed by GitHub
commit 1342825401
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 21 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------ -- ------------------------------------------
-- Friendica 2020.12-dev (Red Hot Poker) -- Friendica 2020.12-dev (Red Hot Poker)
-- DB_UPDATE_VERSION 1378 -- DB_UPDATE_VERSION 1379
-- ------------------------------------------ -- ------------------------------------------
@ -332,6 +332,7 @@ CREATE TABLE IF NOT EXISTS `apcontact` (
INDEX `alias` (`alias`(190)), INDEX `alias` (`alias`(190)),
INDEX `followers` (`followers`(190)), INDEX `followers` (`followers`(190)),
INDEX `baseurl` (`baseurl`(190)), INDEX `baseurl` (`baseurl`(190)),
INDEX `sharedinbox` (`sharedinbox`(190)),
INDEX `gsid` (`gsid`), INDEX `gsid` (`gsid`),
FOREIGN KEY (`gsid`) REFERENCES `gserver` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT FOREIGN KEY (`gsid`) REFERENCES `gserver` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='ActivityPub compatible contacts - used in the ActivityPub implementation'; ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='ActivityPub compatible contacts - used in the ActivityPub implementation';
@ -1057,7 +1058,7 @@ CREATE TABLE IF NOT EXISTS `photo` (
INDEX `uid_album_scale_created` (`uid`,`album`(32),`scale`,`created`), INDEX `uid_album_scale_created` (`uid`,`album`(32),`scale`,`created`),
INDEX `uid_album_resource-id_created` (`uid`,`album`(32),`resource-id`,`created`), INDEX `uid_album_resource-id_created` (`uid`,`album`(32),`resource-id`,`created`),
INDEX `resource-id` (`resource-id`), INDEX `resource-id` (`resource-id`),
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE RESTRICT,
FOREIGN KEY (`contact-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT FOREIGN KEY (`contact-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='photo storage'; ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='photo storage';

View file

@ -32,6 +32,7 @@ use Friendica\Protocol\ActivityNamespace;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\HTTPSignature;
use Friendica\Util\JsonLD; use Friendica\Util\JsonLD;
use Friendica\Util\Network; use Friendica\Util\Network;
@ -148,6 +149,7 @@ class APContact
$data = ActivityPub::fetchContent($url); $data = ActivityPub::fetchContent($url);
if (empty($data)) { if (empty($data)) {
self::markForArchival($fetched_contact ?: []);
return $fetched_contact; return $fetched_contact;
} }
@ -350,10 +352,54 @@ class APContact
return $apcontact; return $apcontact;
} }
/**
* Mark the given AP Contact as "to archive"
*
* @param array $apcontact
* @return void
*/
public static function markForArchival(array $apcontact)
{
if (!empty($apcontact['inbox'])) {
Logger::info('Set inbox status to failure', ['inbox' => $apcontact['inbox']]);
HTTPSignature::setInboxStatus($apcontact['inbox'], false);
}
if (!empty($apcontact['sharedinbox'])) {
// Check if there are any available inboxes
$available = DBA::exists('apcontact', ["`sharedinbox` = ? AnD `inbox` IN (SELECT `url` FROM `inbox-status` WHERE `success` > `failure`)",
$apcontact['sharedinbox']]);
if (!$available) {
// If all known personal inboxes are failing then set their shared inbox to failure as well
Logger::info('Set shared inbox status to failure', ['sharedinbox' => $apcontact['sharedinbox']]);
HTTPSignature::setInboxStatus($apcontact['sharedinbox'], false, true);
}
}
}
/**
* Unmark the given AP Contact as "to archive"
*
* @param array $apcontact
* @return void
*/
public static function unmarkForArchival(array $apcontact)
{
if (!empty($apcontact['inbox'])) {
Logger::info('Set inbox status to success', ['inbox' => $apcontact['inbox']]);
HTTPSignature::setInboxStatus($apcontact['inbox'], true);
}
if (!empty($apcontact['sharedinbox'])) {
Logger::info('Set shared inbox status to success', ['sharedinbox' => $apcontact['sharedinbox']]);
HTTPSignature::setInboxStatus($apcontact['sharedinbox'], true, true);
}
}
/** /**
* Unarchive inboxes * Unarchive inboxes
* *
* @param string $url inbox url * @param string $url inbox url
* @param boolean $shared Shared Inbox
*/ */
private static function unarchiveInbox($url, $shared) private static function unarchiveInbox($url, $shared)
{ {
@ -361,15 +407,6 @@ class APContact
return; return;
} }
$now = DateTimeFormat::utcNow(); HTTPSignature::setInboxStatus($url, true, $shared);
$fields = ['archive' => false, 'success' => $now, 'shared' => $shared];
if (!DBA::exists('inbox-status', ['url' => $url])) {
$fields = array_merge($fields, ['url' => $url, 'created' => $now]);
DBA::replace('inbox-status', $fields);
} else {
DBA::update('inbox-status', $fields, ['url' => $url]);
}
} }
} }

View file

@ -104,6 +104,8 @@ class Receiver
return; return;
} }
APContact::unMarkForArchival($apcontact);
$http_signer = HTTPSignature::getSigner($body, $header); $http_signer = HTTPSignature::getSigner($body, $header);
if (empty($http_signer)) { if (empty($http_signer)) {
Logger::warning('Invalid HTTP signature, message will be discarded.'); Logger::warning('Invalid HTTP signature, message will be discarded.');
@ -233,6 +235,7 @@ class Receiver
$profile = APContact::getByURL($object_id); $profile = APContact::getByURL($object_id);
if (!empty($profile['type'])) { if (!empty($profile['type'])) {
APContact::unMarkForArchival($profile);
return 'as:' . $profile['type']; return 'as:' . $profile['type'];
} }

View file

@ -670,7 +670,7 @@ class Transmitter
* *
* @return boolean "true" if inbox is archived * @return boolean "true" if inbox is archived
*/ */
private static function archivedInbox($url) public static function archivedInbox($url)
{ {
return DBA::exists('inbox-status', ['url' => $url, 'archive' => true]); return DBA::exists('inbox-status', ['url' => $url, 'archive' => true]);
} }

View file

@ -314,14 +314,15 @@ class HTTPSignature
* *
* @param string $url The URL of the inbox * @param string $url The URL of the inbox
* @param boolean $success Transmission status * @param boolean $success Transmission status
* @param boolean $shared The inbox is a shared inbox
*/ */
static private function setInboxStatus($url, $success) static public function setInboxStatus($url, $success, $shared = false)
{ {
$now = DateTimeFormat::utcNow(); $now = DateTimeFormat::utcNow();
$status = DBA::selectFirst('inbox-status', [], ['url' => $url]); $status = DBA::selectFirst('inbox-status', [], ['url' => $url]);
if (!DBA::isResult($status)) { if (!DBA::isResult($status)) {
DBA::insert('inbox-status', ['url' => $url, 'created' => $now]); DBA::insert('inbox-status', ['url' => $url, 'created' => $now, 'shared' => $shared]);
$status = DBA::selectFirst('inbox-status', [], ['url' => $url]); $status = DBA::selectFirst('inbox-status', [], ['url' => $url]);
} }

View file

@ -42,7 +42,16 @@ class APDelivery
*/ */
public static function execute($cmd, $target_id, $inbox, $uid) public static function execute($cmd, $target_id, $inbox, $uid)
{ {
Logger::log('Invoked: ' . $cmd . ': ' . $target_id . ' to ' . $inbox, Logger::DEBUG); if (ActivityPub\Transmitter::archivedInbox($inbox)) {
Logger::info('Inbox is archived', ['cmd' => $cmd, 'inbox' => $inbox, 'id' => $target_id, 'uid' => $uid]);
if (in_array($cmd, [Delivery::POST])) {
$item = Item::selectFirst(['uri-id'], ['id' => $target_id]);
Post\DeliveryData::incrementQueueFailed($item['uri-id'] ?? 0);
}
return;
}
Logger::info('Invoked', ['cmd' => $cmd, 'inbox' => $inbox, 'id' => $target_id, 'uid' => $uid]);
$success = true; $success = true;

View file

@ -193,9 +193,9 @@ class Delivery
return; return;
} }
// We don't deliver our items to blocked or pending contacts, and not to ourselves either // We don't deliver our items to blocked, archived or pending contacts, and not to ourselves either
$contact = DBA::selectFirst('contact', [], $contact = DBA::selectFirst('contact', [],
['id' => $contact_id, 'blocked' => false, 'pending' => false, 'self' => false] ['id' => $contact_id, 'archive' => false, 'blocked' => false, 'pending' => false, 'self' => false]
); );
if (!DBA::isResult($contact)) { if (!DBA::isResult($contact)) {
self::setFailedQueue($cmd, $target_item); self::setFailedQueue($cmd, $target_item);

View file

@ -55,7 +55,7 @@
use Friendica\Database\DBA; use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) { if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1378); define('DB_UPDATE_VERSION', 1379);
} }
return [ return [
@ -395,6 +395,7 @@ return [
"alias" => ["alias(190)"], "alias" => ["alias(190)"],
"followers" => ["followers(190)"], "followers" => ["followers(190)"],
"baseurl" => ["baseurl(190)"], "baseurl" => ["baseurl(190)"],
"sharedinbox" => ["sharedinbox(190)"],
"gsid" => ["gsid"] "gsid" => ["gsid"]
] ]
], ],
@ -1081,7 +1082,7 @@ return [
"comment" => "photo storage", "comment" => "photo storage",
"fields" => [ "fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"], "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid", "on delete" => "restrict"], "comment" => "Owner User id"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "contact.id"], "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "contact.id"],
"guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this photo"], "guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this photo"],
"resource-id" => ["type" => "char(32)", "not null" => "1", "default" => "", "comment" => ""], "resource-id" => ["type" => "char(32)", "not null" => "1", "default" => "", "comment" => ""],