Diogo Cordeiro 2020-07-05 02:25:51 +01:00
parent 4d171b27a4
commit 2f284f4274
4 changed files with 85 additions and 58 deletions

View File

@ -189,11 +189,11 @@ class Activitypub_profile extends Managed_DataObject
/** /**
* Fetch the locally stored profile for this Activitypub_profile * Fetch the locally stored profile for this Activitypub_profile
* *
* @return get_called_class * @return Profile
* @throws NoProfileException if it was not found * @throws NoProfileException if it was not found
* @author Diogo Cordeiro <diogo@fc.up.pt> * @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
public function local_profile() public function local_profile(): Profile
{ {
$profile = Profile::getKV('id', $this->profile_id); $profile = Profile::getKV('id', $this->profile_id);
if (!$profile instanceof Profile) { if (!$profile instanceof Profile) {
@ -481,16 +481,22 @@ class Activitypub_profile extends Managed_DataObject
/** /**
* Update remote user profile in local instance * Update remote user profile in local instance
* Depends on do_update
* *
* @param Activitypub_profile $aprofile * @param Activitypub_profile $aprofile
* @param array $res remote response * @param array|false $res remote response, if array it updates, if false it deletes
* @return Profile remote Profile object * @return Profile remote Profile object
* @throws NoProfileException * @throws NoProfileException
* @author Diogo Cordeiro <diogo@fc.up.pt> * @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
public static function update_profile($aprofile, $res) public static function update_profile($aprofile, $res)
{ {
if ($res === false) {
$profile = $aprofile->local_profile();
$id = $profile->getID();
$profile->delete();
throw new NoProfileException($id, "410 Gone");
}
// ActivityPub Profile // ActivityPub Profile
$aprofile->uri = $res['id']; $aprofile->uri = $res['id'];
$aprofile->nickname = $res['preferredUsername']; $aprofile->nickname = $res['preferredUsername'];

View File

@ -431,14 +431,18 @@ class Activitypub_explorer
* profile updating and shall not be used for anything else) * profile updating and shall not be used for anything else)
* *
* @param string $url User's url * @param string $url User's url
* @return array * @return array|false If it is able to fetch, false if it's gone
* @throws Exception Either network issues or unsupported Activity format * @throws Exception Either network issues or unsupported Activity format
* @author Diogo Cordeiro <diogo@fc.up.pt> * @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
public static function get_remote_user_activity($url) public static function get_remote_user_activity(string $url)
{ {
$client = new HTTPClient(); $client = new HTTPClient();
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS); $response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
// If it was deleted
if ($response->getStatus() == 410) {
return false;
}
$res = json_decode($response->getBody(), true); $res = json_decode($response->getBody(), true);
if (Activitypub_explorer::validate_remote_response($res)) { if (Activitypub_explorer::validate_remote_response($res)) {
common_debug('ActivityPub Explorer: Found a valid remote actor for ' . $url); common_debug('ActivityPub Explorer: Found a valid remote actor for ' . $url);

View File

@ -232,64 +232,77 @@ class Activitypub_inbox_handler
* @throws NoProfileException * @throws NoProfileException
* @throws Exception * @throws Exception
* @author Bruno Casteleiro <brunoccast@fc.up.pt> * @author Bruno Casteleiro <brunoccast@fc.up.pt>
* @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
private function handle_delete() private function handle_delete()
{ {
$object = $this->object; $object = $this->object;
if (is_array($object)) { if (is_string($object)) {
$object = $object['id']; $client = new HTTPClient();
} $response = $client->get($object, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
$gone = !$response->isOk();
// profile deletion ? if (!$gone) { // It's not gone, we're updating it.
if ($this->activity['actor'] == $object) { $object = json_decode($response->getBody(), true);
$aprofile = Activitypub_profile::from_profile($this->actor); switch ($object['type']) {
$this->handle_delete_profile($aprofile); case 'Person':
return; try {
} // Update profile if we already have a copy of it
$aprofile = Activitypub_profile::fromUri($object['id'], false);
// note deletion ? Activitypub_profile::update_profile($aprofile, $object);
try { } catch (Exception $e) {
$notice = ActivityPubPlugin::grab_notice_from_url($object, false); // Import profile if we don't
if ($notice instanceof Notice) { Activitypub_explorer::get_profile_from_url($object['id']);
$this->handle_delete_note($notice); }
break;
case 'Tombstone':
try {
$notice = ActivityPubPlugin::grab_notice_from_url($object, false);
if ($notice instanceof Notice) {
$notice->delete();
}
return;
} catch (Exception $e) {
// either already deleted or not an object at all
// nothing to do..
}
break;
case 'Note':
// XXX: We do not support updating a note's contents so, we'll ignore it for now...
default:
common_log(LOG_INFO, "Ignoring Delete activity, we do not understand for {$object['type']}.");
}
} }
} else {
// We don't know the type of the deleted object :(
// Nor if it's gone or not.
try {
$aprofile = Activitypub_profile::fromUri($object, false);
$res = Activitypub_explorer::get_remote_user_activity($object);
Activitypub_profile::update_profile($aprofile, $res);
return;
} catch (Exception $e) {
// Means this wasn't a profile
}
try {
$client = new HTTPClient();
$response = $client->get($object, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
// If it was deleted
if ($response->getStatus() == 410) {
$notice = ActivityPubPlugin::grab_notice_from_url($object, false);
if ($notice instanceof Notice) {
$notice->delete();
}
} else {
// We can't update a note's contents so, we'll ignore it for now...
}
return;
} catch (Exception $e) {
// Means we didn't have this note already
}
return; return;
} catch (Exception $e) {
// either already deleted or not an object at all
// nothing to do..
} }
common_log(LOG_INFO, "Ignoring Delete activity, nothing that we can/need to handle.");
}
/**
* Handles a Delete-Profile Activity.
*
* Note that the actual ap_profile is deleted during the ProfileDeleteRelated event,
* subscribed by ActivityPubPlugin.
*
* @param Activitypub_profile $aprofile remote user being deleted
* @return void
* @throws NoProfileException
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
*/
private function handle_delete_profile(Activitypub_profile $aprofile): void
{
$profile = $aprofile->local_profile();
$profile->delete();
}
/**
* Handles a Delete-Note Activity.
*
* @param Notice $note remote note being deleted
* @return void
* @throws AuthorizationException
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
*/
private function handle_delete_note(Notice $note): void
{
$note->deleteAs($this->actor);
} }
/** /**

View File

@ -97,7 +97,11 @@ while ($user->fetch()) {
$res = Activitypub_explorer::get_remote_user_activity($user->uri); $res = Activitypub_explorer::get_remote_user_activity($user->uri);
$updated_profile = Activitypub_profile::update_profile($user, $res); $updated_profile = Activitypub_profile::update_profile($user, $res);
if (!$quiet) { if (!$quiet) {
echo "Updated ".$updated_profile->getBestName()."\n"; echo 'Updated '.$updated_profile->getBestName()."\n";
}
} catch (NoProfileException $e) {
if (!$quiet) {
echo 'Deleted '.$user->uri."\n";
} }
} catch (Exception $e) { } catch (Exception $e) {
// let it go // let it go