Update person, undo activity and improved security checks
This commit is contained in:
parent
8c7e5bb776
commit
094c27add6
1 changed files with 79 additions and 12 deletions
|
@ -43,16 +43,30 @@ use Friendica\Core\Config;
|
|||
* To-do:
|
||||
*
|
||||
* Receiver:
|
||||
* - Activities: Update (Notes, Person), Delete (Person, Activities, Notes)
|
||||
* - Object Types: Person, Tombstome
|
||||
* - Update Note
|
||||
* - Delete Note
|
||||
* - Delete Person
|
||||
* - Undo Announce
|
||||
* - Reject Follow
|
||||
* - Undo Accept
|
||||
* - Undo Follow
|
||||
* - Add
|
||||
* - Create Image
|
||||
* - Create Video
|
||||
* - Event
|
||||
* - Remove
|
||||
* - Block
|
||||
* - Flag
|
||||
*
|
||||
* Transmitter:
|
||||
* - Activities: Announce, Update (Person)
|
||||
* - Object Tyoes: Person
|
||||
* - Announce
|
||||
* - Undo Announce
|
||||
* - Update Person
|
||||
* - Reject Follow
|
||||
* - Event
|
||||
*
|
||||
* General:
|
||||
* - Queueing unsucessful deliveries
|
||||
* - Event support
|
||||
* - Polling the outboxes for missing content?
|
||||
*/
|
||||
class ActivityPub
|
||||
|
@ -270,7 +284,7 @@ class ActivityPub
|
|||
$exclude[] = $item['owner-link'];
|
||||
}
|
||||
|
||||
$permissions = [];
|
||||
$permissions['to'][] = $actor;
|
||||
|
||||
$elements = ['to', 'cc', 'bto', 'bcc'];
|
||||
foreach ($elements as $element) {
|
||||
|
@ -280,6 +294,7 @@ class ActivityPub
|
|||
if (is_string($activity[$element])) {
|
||||
$activity[$element] = [$activity[$element]];
|
||||
}
|
||||
|
||||
foreach ($activity[$element] as $receiver) {
|
||||
if ($receiver == $profile['followers'] && !empty($item_profile['followers'])) {
|
||||
$receiver = $item_profile['followers'];
|
||||
|
@ -346,10 +361,13 @@ class ActivityPub
|
|||
}
|
||||
}
|
||||
|
||||
// It is to decide whether we should include all profiles in a thread to the list of receivers
|
||||
/*
|
||||
$parents = Item::select(['author-link', 'owner-link', 'gravity'], ['parent' => $item['parent']]);
|
||||
while ($parent = Item::fetch($parents)) {
|
||||
// Don't include data from future posts
|
||||
if ($parent['id'] >= $item['id']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$profile = self::fetchprofile($parent['author-link'], false);
|
||||
if (!empty($profile) && empty($contacts[$profile['url']])) {
|
||||
$data['cc'][] = $profile['url'];
|
||||
|
@ -367,7 +385,7 @@ class ActivityPub
|
|||
}
|
||||
}
|
||||
DBA::close($parents);
|
||||
*/
|
||||
|
||||
if (empty($data['to'])) {
|
||||
$data['to'] = $data['cc'];
|
||||
$data['cc'] = [];
|
||||
|
@ -952,7 +970,7 @@ class ActivityPub
|
|||
}
|
||||
}
|
||||
|
||||
private static function prepareObjectData($activity, $uid, $trust_source)
|
||||
private static function prepareObjectData($activity, $uid, &$trust_source)
|
||||
{
|
||||
$actor = JsonLD::fetchElement($activity, 'actor', 'id');
|
||||
if (empty($actor)) {
|
||||
|
@ -982,12 +1000,18 @@ class ActivityPub
|
|||
}
|
||||
|
||||
// Fetch the content only on activities where this matters
|
||||
if (in_array($activity['type'], ['Create', 'Update', 'Announce'])) {
|
||||
if (in_array($activity['type'], ['Create', 'Announce'])) {
|
||||
$object_data = self::fetchObject($object_url, $activity['object'], $trust_source);
|
||||
if (empty($object_data)) {
|
||||
logger("Object data couldn't be processed", LOGGER_DEBUG);
|
||||
return [];
|
||||
}
|
||||
// We had been able to retrieve the object data - so we can trust the source
|
||||
$trust_source = true;
|
||||
} elseif ($activity['type'] == 'Update') {
|
||||
$object_data = [];
|
||||
$object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type');
|
||||
$object_data['object'] = $activity['object'];
|
||||
} elseif ($activity['type'] == 'Accept') {
|
||||
$object_data = [];
|
||||
$object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type');
|
||||
|
@ -995,7 +1019,11 @@ class ActivityPub
|
|||
} elseif ($activity['type'] == 'Undo') {
|
||||
$object_data = [];
|
||||
$object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type');
|
||||
$object_data['object'] = JsonLD::fetchElement($activity, 'object', 'object');
|
||||
if ($object_data['object_type'] == 'Follow') {
|
||||
$object_data['object'] = JsonLD::fetchElement($activity, 'object', 'object');
|
||||
} else {
|
||||
$object_data['object'] = $activity['object'];
|
||||
}
|
||||
} elseif (in_array($activity['type'], ['Like', 'Dislike'])) {
|
||||
// Create a mostly empty array out of the activity data (instead of the object).
|
||||
// This way we later don't have to check for the existence of ech individual array element.
|
||||
|
@ -1045,12 +1073,17 @@ class ActivityPub
|
|||
|
||||
logger('Processing activity: ' . $activity['type'], LOGGER_DEBUG);
|
||||
|
||||
// $trust_source is called by reference and is set to true if the content was retrieved successfully
|
||||
$object_data = self::prepareObjectData($activity, $uid, $trust_source);
|
||||
if (empty($object_data)) {
|
||||
logger('No object data found', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trust_source) {
|
||||
logger('No trust for activity type "' . $activity['type'] . '", so we quit now.', LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
switch ($activity['type']) {
|
||||
case 'Create':
|
||||
case 'Announce':
|
||||
|
@ -1066,6 +1099,9 @@ class ActivityPub
|
|||
break;
|
||||
|
||||
case 'Update':
|
||||
if (in_array($object_data['object_type'], ['Person', 'Organization', 'Service', 'Group', 'Application'])) {
|
||||
self::updatePerson($object_data, $body);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Delete':
|
||||
|
@ -1084,6 +1120,8 @@ class ActivityPub
|
|||
case 'Undo':
|
||||
if ($object_data['object_type'] == 'Follow') {
|
||||
self::undoFollowUser($object_data);
|
||||
} elseif (in_array($object_data['object_type'], ['Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept'])) {
|
||||
self::undoActivity($object_data);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1553,6 +1591,15 @@ class ActivityPub
|
|||
logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']);
|
||||
}
|
||||
|
||||
private static function updatePerson($activity)
|
||||
{
|
||||
if (empty($activity['object']['id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::fetchprofile($activity['object']['id'], true);
|
||||
}
|
||||
|
||||
private static function acceptFollowUser($activity)
|
||||
{
|
||||
$uid = self::getUserOfObject($activity['object']);
|
||||
|
@ -1580,6 +1627,26 @@ class ActivityPub
|
|||
logger('Accept contact request from contact ' . $cid . ' for user ' . $uid, LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
private static function undoActivity($activity)
|
||||
{
|
||||
$activity_url = JsonLD::fetchElement($activity, 'object', 'id');
|
||||
if (empty($activity_url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$actor = JsonLD::fetchElement($activity, 'object', 'actor');
|
||||
if (empty($actor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$author_id = Contact::getIdForURL($actor);
|
||||
if (empty($author_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Item::delete(['uri' => $activity_url, 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]);
|
||||
}
|
||||
|
||||
private static function undoFollowUser($activity)
|
||||
{
|
||||
$uid = self::getUserOfObject($activity['object']);
|
||||
|
|
Loading…
Reference in a new issue