[ActivityPub] Handle DELETE-Person activity
ActivityPubPlugin: - update grab_notice_from_url to make online grab optional - subscribe events of user and profile deletion - bump minor version number Activitypub_inbox_handler: - separate handle_delete for delete-note and delete-person Activitypub_postman: - add delete-person logic Activitypub_delete: - update validation method to check for the "Person" type - update to_array method to target the activity
This commit is contained in:
parent
f79cd8cee3
commit
c06182c38f
@ -50,7 +50,7 @@ const ACTIVITYPUB_PUBLIC_TO = ['https://www.w3.org/ns/activitystreams#Public',
|
|||||||
*/
|
*/
|
||||||
class ActivityPubPlugin extends Plugin
|
class ActivityPubPlugin extends Plugin
|
||||||
{
|
{
|
||||||
const PLUGIN_VERSION = '0.2.0alpha0';
|
const PLUGIN_VERSION = '0.3.0alpha0';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Actor's URI from its local $profile
|
* Returns a Actor's URI from its local $profile
|
||||||
@ -89,10 +89,11 @@ class ActivityPubPlugin extends Plugin
|
|||||||
*
|
*
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $url Notice's URL
|
* @param string $url Notice's URL
|
||||||
* @return Notice The Notice object
|
* @param bool $grabOnline whether to try online grabbing, defaults to true
|
||||||
* @throws Exception This function or provides a Notice or fails with exception
|
* @return Notice|null The Notice object
|
||||||
|
* @throws Exception This function or provides a Notice, null, or fails with exception
|
||||||
*/
|
*/
|
||||||
public static function grab_notice_from_url($url)
|
public static function grab_notice_from_url(string $url, bool $grabOnline = true): ?Notice
|
||||||
{
|
{
|
||||||
/* Offline Grabbing */
|
/* Offline Grabbing */
|
||||||
try {
|
try {
|
||||||
@ -113,6 +114,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($grabOnline) {
|
||||||
/* Online Grabbing */
|
/* Online Grabbing */
|
||||||
$client = new HTTPClient();
|
$client = new HTTPClient();
|
||||||
$headers = [];
|
$headers = [];
|
||||||
@ -124,6 +126,10 @@ class ActivityPubPlugin extends Plugin
|
|||||||
return Activitypub_notice::create_notice($object);
|
return Activitypub_notice::create_notice($object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_debug('ActivityPubPlugin Notice Grabber: failed to find: '.$url);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route/Reroute urls
|
* Route/Reroute urls
|
||||||
*
|
*
|
||||||
@ -326,6 +332,30 @@ class ActivityPubPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark an ap_profile object for deletion
|
||||||
|
*
|
||||||
|
* @param Profile profile being deleted
|
||||||
|
* @param array &$related objects with same profile_id to be deleted
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onProfileDeleteRelated(Profile $profile, array &$related): void
|
||||||
|
{
|
||||||
|
if ($profile->isLocal()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$aprofile = Activitypub_profile::getKV('profile_id', $profile->getID());
|
||||||
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
|
// mark for deletion
|
||||||
|
$related[] = 'Activitypub_profile';
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin Nodeinfo information
|
* Plugin Nodeinfo information
|
||||||
*
|
*
|
||||||
@ -907,10 +937,22 @@ class ActivityPubPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
$postman = new Activitypub_postman($profile, $other);
|
$postman = new Activitypub_postman($profile, $other);
|
||||||
$postman->delete($notice);
|
$postman->delete_note($notice);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify remote followers when a user gets deleted
|
||||||
|
*
|
||||||
|
* @param Action $action
|
||||||
|
* @param User $user user being deleted
|
||||||
|
*/
|
||||||
|
public function onEndDeleteUser(Action $action, User $user): void
|
||||||
|
{
|
||||||
|
$postman = new Activitypub_postman($user->getProfile());
|
||||||
|
$postman->delete_profile();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Federate private message
|
* Federate private message
|
||||||
*
|
*
|
||||||
|
@ -226,18 +226,54 @@ class Activitypub_inbox_handler
|
|||||||
$object = $object['id'];
|
$object = $object['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already deleted? (By some admin, perhaps?)
|
// profile deletion ?
|
||||||
try {
|
$aprofile = Activitypub_explorer::get_aprofile_by_url($object);
|
||||||
$found = Deleted_notice::getByUri($object);
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
$deleted = ($found instanceof Deleted_notice);
|
$this->handle_delete_profile($aprofile);
|
||||||
} catch (NoResultException $e) {
|
return;
|
||||||
$deleted = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$deleted) {
|
// note deletion ?
|
||||||
$notice = ActivityPubPlugin::grab_notice_from_url($object);
|
try {
|
||||||
$notice->deleteAs($this->actor);
|
$notice = ActivityPubPlugin::grab_notice_from_url($object, false);
|
||||||
|
if ($notice instanceof Notice) {
|
||||||
|
$this->handle_delete_note($notice);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// either already deleted or not a notice 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
|
||||||
|
* @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
|
||||||
|
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||||
|
*/
|
||||||
|
private function handle_delete_note(Notice $note): void
|
||||||
|
{
|
||||||
|
$note->deleteAs($this->actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,6 +50,7 @@ class Activitypub_delete
|
|||||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
'id' => $object.'/delete',
|
'id' => $object.'/delete',
|
||||||
'type' => 'Delete',
|
'type' => 'Delete',
|
||||||
|
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||||
'actor' => $actor,
|
'actor' => $actor,
|
||||||
'object' => $object
|
'object' => $object
|
||||||
];
|
];
|
||||||
@ -73,10 +74,10 @@ class Activitypub_delete
|
|||||||
} else {
|
} else {
|
||||||
if (!isset($object['type'])) {
|
if (!isset($object['type'])) {
|
||||||
throw new Exception('Object type was not specified for Delete Activity.');
|
throw new Exception('Object type was not specified for Delete Activity.');
|
||||||
} else if ($object['type'] !== "Tombstone") {
|
}
|
||||||
|
if ($object['type'] !== "Tombstone" && $object['type'] !== "Person") {
|
||||||
throw new Exception('Invalid Object type for Delete Activity.');
|
throw new Exception('Invalid Object type for Delete Activity.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($object['id'])) {
|
if (!isset($object['id'])) {
|
||||||
throw new Exception('Object id was not specified for Delete Activity.');
|
throw new Exception('Object id was not specified for Delete Activity.');
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class Activitypub_postman
|
|||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
*/
|
*/
|
||||||
public function __construct(Profile $from, array $to)
|
public function __construct(Profile $from, array $to = [])
|
||||||
{
|
{
|
||||||
$this->actor = $from;
|
$this->actor = $from;
|
||||||
$this->to = $to;
|
$this->to = $to;
|
||||||
@ -359,10 +359,9 @@ class Activitypub_postman
|
|||||||
* @throws HTTP_Request2_Exception
|
* @throws HTTP_Request2_Exception
|
||||||
* @throws InvalidUrlException
|
* @throws InvalidUrlException
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @throws Exception
|
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
*/
|
*/
|
||||||
public function delete($notice)
|
public function delete_note($notice)
|
||||||
{
|
{
|
||||||
$data = Activitypub_delete::delete_to_array(
|
$data = Activitypub_delete::delete_to_array(
|
||||||
ActivityPubPlugin::actor_uri($notice->getProfile()),
|
ActivityPubPlugin::actor_uri($notice->getProfile()),
|
||||||
@ -383,6 +382,37 @@ class Activitypub_postman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a Delete notification to remote followers of some deleted profile
|
||||||
|
*
|
||||||
|
* @param Notice $notice
|
||||||
|
* @throws HTTP_Request2_Exception
|
||||||
|
* @throws InvalidUrlException
|
||||||
|
* @throws Exception
|
||||||
|
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||||
|
*/
|
||||||
|
public function delete_profile()
|
||||||
|
{
|
||||||
|
$data = Activitypub_delete::delete_to_array($this->actor_uri, $this->actor_uri);
|
||||||
|
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
foreach ($this->to_inbox() as $inbox) {
|
||||||
|
$res = $this->send($data, $inbox);
|
||||||
|
|
||||||
|
// accummulate errors for later use, if needed
|
||||||
|
if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) {
|
||||||
|
$res_body = json_decode($res->getBody(), true);
|
||||||
|
$errors[] = isset($res_body[0]['error']) ?
|
||||||
|
$res_body[0]['error'] : "An unknown error occurred.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
common_log(LOG_ERR, sizeof($errors) . " instance/s failed to handle the delete_profile activity!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean list of inboxes to deliver messages
|
* Clean list of inboxes to deliver messages
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user