From 9fcccd8b5adee4710d1b791d5139c5837ba482c9 Mon Sep 17 00:00:00 2001 From: tenma Date: Tue, 31 Mar 2020 08:13:52 +0100 Subject: [PATCH] [ActivityPub] Add TheFreeNetwork module's support in handling profile insertion Activitypub_profile: - Update do_insert to trigger TFN's assistance in inserting the profile explorer: - Use the new LRDD's method for grabbing profile aliases --- .../classes/Activitypub_profile.php | 98 ++++++++++++------- plugins/ActivityPub/lib/explorer.php | 27 +---- 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/plugins/ActivityPub/classes/Activitypub_profile.php b/plugins/ActivityPub/classes/Activitypub_profile.php index 28fea5aa27..1cb1a6f390 100644 --- a/plugins/ActivityPub/classes/Activitypub_profile.php +++ b/plugins/ActivityPub/classes/Activitypub_profile.php @@ -147,33 +147,42 @@ class Activitypub_profile extends Managed_DataObject */ public function do_insert() { - $profile = new Profile(); + // Does any other protocol have this remote entity we're about to add ? + if (!Event::handle('StartTFNLookup', [$this->uri, get_class($this), &$profile_id])) { + // Yes! Avoid creating a new profile + $this->profile_id = $profile_id; + $this->created = $this->modified = common_sql_now(); - $profile->created = $this->created = $this->modified = common_sql_now(); + if ($this->insert() === false) { + $this->query('ROLLBACK'); + throw new ServerException('Cannot save ActivityPub profile.'); + } - $fields = [ - 'profileurl' => 'profileurl', - 'nickname' => 'nickname', - 'fullname' => 'fullname', - 'bio' => 'bio' - ]; + // Update existing profile with received data + $profile = Profile::getKV('id', $profile_id); + self::update_local_profile($profile, $this); - foreach ($fields as $af => $pf) { - $profile->$pf = $this->$af; - } + // Ask TFN to handle profile duplication + Event::handle('EndTFNLookup', [get_class($this), $profile_id]); + } else { + // No, create both a new profile and remote profile + $profile = new Profile(); + $profile->created = $this->created = $this->modified = common_sql_now(); + self::update_local_profile($profile, $this); - $this->profile_id = $profile->insert(); - if ($this->profile_id === false) { - $profile->query('ROLLBACK'); - throw new ServerException('Profile insertion failed.'); - } + $this->profile_id = $profile->insert(); + if ($this->profile_id === false) { + $profile->query('ROLLBACK'); + throw new ServerException('Profile insertion failed.'); + } - $ok = $this->insert(); + $ok = $this->insert(); - if ($ok === false) { - $profile->query('ROLLBACK'); - $this->query('ROLLBACK'); - throw new ServerException('Cannot save ActivityPub profile.'); + if ($ok === false) { + $profile->query('ROLLBACK'); + $this->query('ROLLBACK'); + throw new ServerException('Cannot save ActivityPub profile.'); + } } } @@ -439,6 +448,37 @@ class Activitypub_profile extends Managed_DataObject throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'), $addr)); } + /** + * Update local profile with info from some AP profile + * + * @param Profile $profile + * @param Activitypub_profile $aprofile + * @return void + * @author Bruno Casteleiro + * @author Diogo Cordeiro + */ + public static function update_local_profile(Profile $profile, Activitypub_profile $aprofile): void + { + $fields = [ + 'profileurl' => 'profileurl', + 'nickname' => 'nickname', + 'fullname' => 'fullname', + 'bio' => 'bio' + ]; + + $orig = clone($profile); + + foreach ($fields as $af => $pf) { + $profile->$pf = $aprofile->$af; + } + + if ($profile->id) { + common_debug('Updating local Profile:' . $profile->id . ' from remote ActivityPub profile'); + $profile->modified = common_sql_now(); + $profile->update($orig); + } + } + /** * Update remote user profile in local instance * Depends on do_update @@ -459,24 +499,12 @@ class Activitypub_profile extends Managed_DataObject $aprofile->inboxuri = $res['inbox']; $aprofile->sharedInboxuri = $res['endpoints']['sharedInbox'] ?? $res['inbox']; $aprofile->profileurl = $res['url'] ?? $aprofile->uri; + $aprofile->modified = common_sql_now(); $profile = $aprofile->local_profile(); - $profile->modified = $aprofile->modified = common_sql_now(); - - $fields = [ - 'profileurl' => 'profileurl', - 'nickname' => 'nickname', - 'fullname' => 'fullname', - 'bio' => 'bio' - ]; - - foreach ($fields as $af => $pf) { - $profile->$pf = $aprofile->$af; - } - // Profile - $profile->update(); + self::update_local_profile($profile, $aprofile); $aprofile->update(); // Public Key diff --git a/plugins/ActivityPub/lib/explorer.php b/plugins/ActivityPub/lib/explorer.php index 08e66ad1ce..a1c6889104 100644 --- a/plugins/ActivityPub/lib/explorer.php +++ b/plugins/ActivityPub/lib/explorer.php @@ -116,29 +116,6 @@ class Activitypub_explorer return $this->discovered_actor_profiles; } - /** - * Fetch all the aliases for some actor - * - * @param string $url actor's url - * @return array aliases - * @throws Exception (If the Discovery's HTTP requests fail) - * @author Bruno Casteleiro - */ - private function grab_aliases(string $url): array - { - $disco = new Discovery(); - $xrd = $disco->lookup($url); - - $all_ids = array_merge([$xrd->subject], $xrd->aliases); - - if (!in_array($url, $all_ids)) { - common_debug('grab_aliases: The URI we got was not listed itself when doing discovery on it'); - return []; - } - - return $all_ids; - } - /** * Get a local user profile from its URL and joins it on * $this->discovered_actor_profiles @@ -154,13 +131,13 @@ class Activitypub_explorer { if ($online) { common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' with online resources.'); - $all_ids = $this->grab_aliases($uri); + $all_ids = LRDDPlugin::grab_profile_aliases($uri); } else { common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' offline.'); $all_ids = [$uri]; } - if (empty($all_ids)) { + if (is_null($all_ids)) { common_debug('AcvitityPub Explorer: Unable to find a local profile for ' . $uri); return false; }