From a8078ce72bc93a7d095f19b3bdde055e68939fe8 Mon Sep 17 00:00:00 2001 From: Matthias Pfefferle Date: Fri, 22 Dec 2023 17:45:27 +0100 Subject: [PATCH] Shared Inbox (#617) * init shared inbox * try to get user id from activity * some code formatting * disable ACTIVITYPUB_SHARED_INBOX_FEATURE * done! * do not use the inbox-user at all * fix user check! * fix user check! --- activitypub.php | 1 + includes/handler/class-create.php | 7 +++++- includes/handler/class-delete.php | 23 ++++++++++++++---- includes/handler/class-follow.php | 40 ++++++++++++++++++++++++++----- includes/handler/class-undo.php | 22 ++++++++++++++--- includes/handler/class-update.php | 13 ++++++---- includes/model/class-user.php | 12 ++++++++++ includes/rest/class-inbox.php | 36 +++------------------------- 8 files changed, 101 insertions(+), 53 deletions(-) diff --git a/activitypub.php b/activitypub.php index 55d040b..3ec6cb5 100644 --- a/activitypub.php +++ b/activitypub.php @@ -33,6 +33,7 @@ require_once __DIR__ . '/includes/functions.php'; \defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "[ap_title]\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]" ); \defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false ); \defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false ); +\defined( 'ACTIVITYPUB_SHARED_INBOX_FEATURE' ) || \define( 'ACTIVITYPUB_SHARED_INBOX_FEATURE', false ); \define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); \define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); diff --git a/includes/handler/class-create.php b/includes/handler/class-create.php index 2e5d76a..64788da 100644 --- a/includes/handler/class-create.php +++ b/includes/handler/class-create.php @@ -15,7 +15,12 @@ class Create { * Initialize the class, registering WordPress hooks */ public static function init() { - \add_action( 'activitypub_inbox_create', array( self::class, 'handle_create' ), 10, 3 ); + \add_action( + 'activitypub_inbox_create', + array( self::class, 'handle_create' ), + 10, + 3 + ); } /** diff --git a/includes/handler/class-delete.php b/includes/handler/class-delete.php index a8611d4..f2571c0 100644 --- a/includes/handler/class-delete.php +++ b/includes/handler/class-delete.php @@ -15,11 +15,24 @@ class Delete { * Initialize the class, registering WordPress hooks */ public static function init() { - \add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ), 10, 2 ); + \add_action( + 'activitypub_inbox_delete', + array( self::class, 'handle_delete' ) + ); + // defer signature verification for `Delete` requests. - \add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 2 ); + \add_filter( + 'activitypub_defer_signature_verification', + array( self::class, 'defer_signature_verification' ), + 10, + 2 + ); + // side effect - \add_action( 'activitypub_delete_actor_interactions', array( self::class, 'delete_interactions' ), 10, 1 ); + \add_action( + 'activitypub_delete_actor_interactions', + array( self::class, 'delete_interactions' ) + ); } /** @@ -28,7 +41,7 @@ class Delete { * @param array $activity The delete activity. * @param int $user_id The ID of the user performing the delete activity. */ - public static function handle_delete( $activity, $user_id ) { + public static function handle_delete( $activity ) { $object_type = isset( $activity['object']['type'] ) ? $activity['object']['type'] : ''; switch ( $object_type ) { @@ -39,7 +52,7 @@ class Delete { case 'Organization': case 'Service': case 'Application': - self::maybe_delete_follower( $user_id, $activity ); + self::maybe_delete_follower( $activity ); break; // Object and Link Types // @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types diff --git a/includes/handler/class-follow.php b/includes/handler/class-follow.php index 6855dbd..810680b 100644 --- a/includes/handler/class-follow.php +++ b/includes/handler/class-follow.php @@ -14,8 +14,17 @@ class Follow { * Initialize the class, registering WordPress hooks */ public static function init() { - \add_action( 'activitypub_inbox_follow', array( self::class, 'handle_follow' ), 10, 2 ); - \add_action( 'activitypub_followers_post_follow', array( self::class, 'send_follow_response' ), 10, 4 ); + \add_action( + 'activitypub_inbox_follow', + array( self::class, 'handle_follow' ) + ); + + \add_action( + 'activitypub_followers_post_follow', + array( self::class, 'send_follow_response' ), + 10, + 4 + ); } /** @@ -24,11 +33,30 @@ class Follow { * @param array $activity The activity object * @param int $user_id The user ID */ - public static function handle_follow( $activity, $user_id ) { - // save follower - $follower = Followers::add_follower( $user_id, $activity['actor'] ); + public static function handle_follow( $activity ) { + $user = Users::get_by_resource( $activity['object'] ); - do_action( 'activitypub_followers_post_follow', $activity['actor'], $activity, $user_id, $follower ); + if ( ! $user || is_wp_error( $user ) ) { + // If we can not find a user, + // we can not initiate a follow process + return; + } + + $user_id = $user->get__id(); + + // save follower + $follower = Followers::add_follower( + $user_id, + $activity['actor'] + ); + + do_action( + 'activitypub_followers_post_follow', + $activity['actor'], + $activity, + $user_id, + $follower + ); } /** diff --git a/includes/handler/class-undo.php b/includes/handler/class-undo.php index 13c06f3..74d3dca 100644 --- a/includes/handler/class-undo.php +++ b/includes/handler/class-undo.php @@ -1,6 +1,7 @@ get__id(); + Followers::remove_follower( $user_id, $activity['actor'] ); } } diff --git a/includes/handler/class-update.php b/includes/handler/class-update.php index 00e0430..002c3d5 100644 --- a/includes/handler/class-update.php +++ b/includes/handler/class-update.php @@ -14,7 +14,10 @@ class Update { * Initialize the class, registering WordPress hooks */ public static function init() { - \add_action( 'activitypub_inbox_update', array( self::class, 'handle_update' ), 10, 2 ); + \add_action( + 'activitypub_inbox_update', + array( self::class, 'handle_update' ) + ); } /** @@ -23,7 +26,7 @@ class Update { * @param array $array The activity-object * @param int $user_id The id of the local blog-user */ - public static function handle_update( $array, $user_id ) { + public static function handle_update( $array ) { $object_type = isset( $array['object']['type'] ) ? $array['object']['type'] : ''; switch ( $object_type ) { @@ -45,7 +48,7 @@ class Update { case 'Video': case 'Event': case 'Document': - self::update_interaction( $array, $user_id ); + self::update_interaction( $array ); break; // Minimal Activity // @see https://www.w3.org/TR/activitystreams-core/#example-1 @@ -62,7 +65,7 @@ class Update { * * @return void */ - public static function update_interaction( $activity, $user_id ) { + public static function update_interaction( $activity ) { $state = Interactions::update_comment( $activity ); $reaction = null; @@ -70,7 +73,7 @@ class Update { $reaction = \get_comment( $state ); } - \do_action( 'activitypub_handled_update', $activity, $user_id, $state, $reaction ); + \do_action( 'activitypub_handled_update', $activity, null, $state, $reaction ); } /** diff --git a/includes/model/class-user.php b/includes/model/class-user.php index c713434..c22f83c 100644 --- a/includes/model/class-user.php +++ b/includes/model/class-user.php @@ -226,6 +226,18 @@ class User extends Actor { return get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $this->get__id() ) ); } + public function get_endpoints() { + $endpoints = null; + + if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) { + $endpoints = array( + 'sharedInbox' => get_rest_url_by_path( 'inbox' ), + ); + } + + return $endpoints; + } + /** * Extend the User-Output with Attachments. * diff --git a/includes/rest/class-inbox.php b/includes/rest/class-inbox.php index 938ca90..c527040 100644 --- a/includes/rest/class-inbox.php +++ b/includes/rest/class-inbox.php @@ -94,11 +94,8 @@ class Inbox { $json->generator = 'http://wordpress.org/?v=' . \get_bloginfo_rss( 'version' ); $json->type = 'OrderedCollectionPage'; $json->partOf = get_rest_url_by_path( sprintf( 'users/%d/inbox', $user->get__id() ) ); // phpcs:ignore - $json->totalItems = 0; // phpcs:ignore - $json->orderedItems = array(); // phpcs:ignore - $json->first = $json->partOf; // phpcs:ignore // filter output @@ -155,37 +152,10 @@ class Inbox { $data = $request->get_json_params(); $activity = Activity::init_from_array( $data ); $type = $request->get_param( 'type' ); - $users = self::get_recipients( $data ); + $type = \strtolower( $type ); - if ( ! $users ) { - return new WP_Error( - 'rest_invalid_param', - \__( 'No recipients found', 'activitypub' ), - array( - 'status' => 400, - 'params' => array( - 'to' => \__( 'Please check/validate "to" field', 'activitypub' ), - 'bto' => \__( 'Please check/validate "bto" field', 'activitypub' ), - 'cc' => \__( 'Please check/validate "cc" field', 'activitypub' ), - 'bcc' => \__( 'Please check/validate "bcc" field', 'activitypub' ), - 'audience' => \__( 'Please check/validate "audience" field', 'activitypub' ), - ), - ) - ); - } - - foreach ( $users as $user ) { - $user = User_Collection::get_by_various( $user ); - - if ( is_wp_error( $user ) ) { - continue; - } - - $type = \strtolower( $type ); - - \do_action( 'activitypub_inbox', $data, $user->ID, $type, $activity ); - \do_action( "activitypub_inbox_{$type}", $data, $user->ID, $activity ); - } + \do_action( 'activitypub_inbox', $data, null, $type, $activity ); + \do_action( "activitypub_inbox_{$type}", $data, null, $activity ); $rest_response = new WP_REST_Response( array(), 202 ); $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );