Improved message handling / new activity relay handling

This commit is contained in:
Michael 2022-07-27 17:39:00 +00:00
parent 7834359957
commit 86105635ca
26 changed files with 280 additions and 428 deletions

View file

@ -110,7 +110,10 @@ class Delivery
} elseif ($cmd == WorkerDelivery::PROFILEUPDATE) {
$success = ActivityPub\Transmitter::sendProfileUpdate($uid, $inbox);
} else {
$data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id);
$data = Post\Activity::getByURIId($uri_id);
if (empty($data)) {
$data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id);
}
if (!empty($data)) {
$timestamp = microtime(true);
$response = HTTPSignature::post($data, $inbox, $uid);

View file

@ -361,8 +361,6 @@ class Processor
if (!empty($activity['raw'])) {
$item['source'] = $activity['raw'];
$item['protocol'] = Conversation::PARCEL_ACTIVITYPUB;
$item['conversation-href'] = $activity['context'] ?? '';
$item['conversation-uri'] = $activity['conversation'] ?? '';
if (isset($activity['push'])) {
$item['direction'] = $activity['push'] ? Conversation::PUSH : Conversation::PULL;
@ -475,7 +473,19 @@ class Processor
}
// @todo To ensure that the remote system is working correctly, we can check if the "Content-Type" contains JSON
return in_array($curlResult->getReturnCode(), [404]);
if (in_array($curlResult->getReturnCode(), [404])) {
return true;
}
$object = json_decode($curlResult->getBody(), true);
if (!empty($object)) {
$activity = JsonLD::compact($object);
if (JsonLD::fetchElement($activity, '@type') == 'as:Tombstone') {
return true;
}
}
return false;
}
/**
* Delete items

View file

@ -25,7 +25,9 @@ use Friendica\Core\Logger;
use Friendica\Database\Database;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Protocol\ActivityPub;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\JsonLD;
/**
* This class handles the processing of incoming posts
@ -214,6 +216,7 @@ class Queue
Logger::debug('Process leftover entry', $entry);
self::process($entry['id']);
}
DBA::close($entries);
}
/**
@ -247,5 +250,58 @@ class Queue
while ($entry = DBA::fetch($entries)) {
self::process($entry['id']);
}
DBA::close($entries);
}
/**
* Prepare the queue entry.
* This is a test function that is used solely for development.
*
* @param integer $id
* @return array
*/
public static function reprepareActivityById(int $id): array
{
$entry = DBA::selectFirst('inbox-entry', [], ['id' => $id]);
if (empty($entry)) {
return [];
}
$receiver = DBA::selectFirst('inbox-entry-receiver', ['uid'], ['queue-id' => $id]);
if (!empty($receiver)) {
$uid = $receiver['uid'];
} else {
$uid = 0;
}
$trust_source = $entry['trust'];
$data = json_decode($entry['activity'], true);
$activity = json_decode($data['raw'], true);
$ldactivity = JsonLD::compact($activity);
return [
'data' => Receiver::prepareObjectData($ldactivity, $uid, $entry['push'], $trust_source),
'trust' => $trust_source
];
}
/**
* Set the trust for all untrusted entries.
* This is a test function that is used solely for development.
*
* @return void
*/
public static function reprepareAll()
{
$entries = DBA::select('inbox-entry', ['id'], ["NOT `trust` AND `wid` IS NULL"], ['order' => ['id' => true]]);
while ($entry = DBA::fetch($entries)) {
$data = self::reprepareActivityById($entry['id'], false);
if ($data['trust']) {
DBA::update('inbox-entry', ['trust' => true], ['id' => $entry['id']]);
}
}
DBA::close($entries);
}
}

View file

@ -272,26 +272,39 @@ class Receiver
*/
public static function prepareObjectData(array $activity, int $uid, bool $push, bool &$trust_source): array
{
$id = JsonLD::fetchElement($activity, '@id');
$id = JsonLD::fetchElement($activity, '@id');
$type = JsonLD::fetchElement($activity, '@type');
$object_id = JsonLD::fetchElement($activity, 'as:object', '@id');
if (!empty($object_id) && in_array($type, ['as:Create', 'as:Update'])) {
$fetch_id = $object_id;
} else {
$fetch_id = $id;
}
if (!empty($activity['as:object'])) {
$object_type = JsonLD::fetchElement($activity['as:object'], '@type');
}
if (!empty($id) && !$trust_source) {
$fetch_uid = $uid ?: self::getBestUserForActivity($activity);
$fetched_activity = ActivityPub::fetchContent($id, $fetch_uid);
$fetched_activity = ActivityPub::fetchContent($fetch_id, $fetch_uid);
if (!empty($fetched_activity)) {
$object = JsonLD::compact($fetched_activity);
$fetched_id = JsonLD::fetchElement($object, '@id');
if ($fetched_id == $id) {
$fetched_id = JsonLD::fetchElement($object, '@id');
$fetched_type = JsonLD::fetchElement($object, '@type');
if (($fetched_id == $id) && !empty($fetched_type) && ($fetched_type == $type)) {
Logger::info('Activity had been fetched successfully', ['id' => $id]);
$trust_source = true;
if ($id != $object_id) {
$activity = $object;
} else {
Logger::info('Fetched data is the object instead of the activity', ['id' => $id]);
unset($object['@context']);
$activity['as:object'] = $object;
}
$activity = $object;
} elseif (($fetched_id == $object_id) && !empty($fetched_type) && ($fetched_type == $object_type)) {
Logger::info('Fetched data is the object instead of the activity', ['id' => $id]);
$trust_source = true;
unset($object['@context']);
$activity['as:object'] = $object;
} else {
Logger::info('Activity id is not equal', ['id' => $id, 'fetched' => $fetched_id]);
}
@ -371,9 +384,9 @@ class Receiver
$object_data['object_object'] = JsonLD::fetchElement($activity['as:object'], 'as:object');
$object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type');
$object_data['push'] = $push;
if ($type == 'as:Delete') {
if (!$trust_source && ($type == 'as:Delete')) {
$apcontact = APContact::getByURL($object_data['object_id'], true);
$trust_source = ($apcontact['type'] == 'Tombstone');
$trust_source = empty($apcontact) || ($apcontact['type'] == 'Tombstone') || $apcontact['suspended'];
}
} elseif (in_array($type, ['as:Create', 'as:Update', 'as:Announce', 'as:Invite']) || strpos($type, '#emojiReaction')) {
// Fetch the content only on activities where this matters
@ -430,8 +443,11 @@ class Receiver
$object_data['object_object_type'] = self::fetchObjectType([], $object_data['object_object'], $fetch_uid);
}
if (($type == 'as:Delete') && in_array($object_data['object_type'], array_merge(['as:Tombstone'], self::CONTENT_TYPES))) {
if (!$trust_source && ($type == 'as:Delete') && in_array($object_data['object_type'], array_merge(['as:Tombstone', ''], self::CONTENT_TYPES))) {
$trust_source = Processor::isActivityGone($object_data['object_id']);
if (!$trust_source) {
$trust_source = !empty(APContact::getByURL($object_data['object_id'], false));
}
}
}
@ -668,6 +684,9 @@ class Receiver
if (!empty($object_data['raw'])) {
$announce_object_data['raw'] = $object_data['raw'];
}
if (!empty($object_data['raw-object'])) {
$announce_object_data['raw-object'] = $object_data['raw-object'];
}
ActivityPub\Processor::createActivity($announce_object_data, Activity::ANNOUNCE);
}
} else {
@ -1305,7 +1324,7 @@ class Receiver
$object_data = self::processObject($object);
if (!empty($data)) {
$object_data['raw'] = json_encode($data);
$object_data['raw-object'] = json_encode($data);
}
return $object_data;
}

View file

@ -1232,10 +1232,8 @@ class Transmitter
}
if (!$item['deleted']) {
$condition = ['item-uri' => $item['uri'], 'protocol' => Conversation::PARCEL_ACTIVITYPUB];
$conversation = DBA::selectFirst('conversation', ['source'], $condition);
if (!$item['origin'] && DBA::isResult($conversation)) {
$data = json_decode($conversation['source'], true);
$data = Post\Activity::getByURIId($item['uri-id']);
if (!$item['origin'] && !empty($data)) {
if (!empty($data['type'])) {
if (in_array($data['type'], ['Create', 'Update'])) {
if ($object_mode) {