| @@ -7,16 +7,13 @@ | ||
| 7 | 7 | |
| 8 | 8 | namespace Activitypub\Handler; |
| 9 | 9 | |
| 10 | 10 | use Activitypub\Activity\Activity; |
| 11 | -use Activitypub\Application; | |
| 12 | 11 | use Activitypub\Collection\Actors; |
| 13 | 12 | use Activitypub\Collection\Followers; |
| 14 | 13 | use Activitypub\Collection\Remote_Actors; |
| 15 | -use Activitypub\Http; | |
| 16 | 14 | |
| 17 | 15 | use function Activitypub\add_to_outbox; |
| 18 | -use function Activitypub\object_to_uri; | |
| 19 | 16 | |
| 20 | 17 | /** |
| 21 | 18 | * Handle Follow requests. |
| 22 | 19 | */ |
| @@ -26,11 +23,8 @@ | ||
| 26 | 23 | */ |
| 27 | 24 | public static function init() { |
| 28 | 25 | \add_action( 'activitypub_inbox_follow', array( self::class, 'handle_follow' ), 10, 2 ); |
| 29 | 26 | \add_action( 'activitypub_handled_follow', array( self::class, 'queue_accept' ), 10, 4 ); |
| 30 | - | |
| 31 | - // The Application actor cannot be followed; explicitly reject such Follows so they don't sit "pending" on the remote instance forever. | |
| 32 | - \add_action( 'activitypub_inbox_shared_follow', array( self::class, 'reject_application_follow' ), 10, 2 ); | |
| 33 | 27 | } |
| 34 | 28 | |
| 35 | 29 | /** |
| 36 | 30 | * Handle "Follow" requests. |
| @@ -41,8 +35,13 @@ | ||
| 41 | 35 | public static function handle_follow( $activity, $user_ids ) { |
| 42 | 36 | // Extract the user ID (follow requests are always for a single user). |
| 43 | 37 | $user_id = \is_array( $user_ids ) ? \reset( $user_ids ) : $user_ids; |
| 44 | 38 | |
| 39 | + if ( Actors::APPLICATION_USER_ID === $user_id ) { | |
| 40 | + self::queue_reject( $activity, $user_id ); | |
| 41 | + return; | |
| 42 | + } | |
| 43 | + | |
| 45 | 44 | // Check if the actor already follows the user. |
| 46 | 45 | $already_following = false; |
| 47 | 46 | $remote_actor = Remote_Actors::get_by_uri( $activity['actor'] ); |
| 48 | 47 | if ( ! \is_wp_error( $remote_actor ) ) { |
| @@ -103,9 +102,9 @@ | ||
| 103 | 102 | |
| 104 | 103 | $actor = $activity_object['actor']; |
| 105 | 104 | |
| 106 | 105 | // Only send minimal data. |
| 107 | - $activity_object = \array_intersect_key( | |
| 106 | + $activity_object = array_intersect_key( | |
| 108 | 107 | $activity_object, |
| 109 | 108 | array( |
| 110 | 109 | 'id' => 1, |
| 111 | 110 | 'type' => 1, |
| @@ -123,45 +122,16 @@ | ||
| 123 | 122 | add_to_outbox( $activity, null, $user_id, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE ); |
| 124 | 123 | } |
| 125 | 124 | |
| 126 | 125 | /** |
| 127 | - * Reject Follow requests aimed at the Application actor. | |
| 126 | + * Send Reject response. | |
| 128 | 127 | * |
| 129 | - * The Application advertises `manuallyApprovesFollowers` but is not followable, | |
| 130 | - * so an explicit Reject is the only way a remote follow request gets resolved. | |
| 131 | - * The Reject is sent directly instead of through the Outbox, which only | |
| 132 | - * dispatches for real actors, and is signed with the Application key. | |
| 133 | - * | |
| 134 | - * @since 9.1.0 | |
| 135 | - * | |
| 136 | - * @param array $activity The Follow activity data. | |
| 137 | - * @param int[] $user_ids The local recipient IDs the inbox resolved. | |
| 128 | + * @param array $activity The Activity array. | |
| 129 | + * @param int $user_id The ID of the WordPress User. | |
| 138 | 130 | */ |
| 139 | - public static function reject_application_follow( $activity, $user_ids ) { | |
| 140 | - // A resolved recipient means the Follow targets a real actor, not the Application. | |
| 141 | - if ( ! empty( $user_ids ) ) { | |
| 142 | - return; | |
| 143 | - } | |
| 144 | - | |
| 145 | - if ( empty( $activity['object'] ) || ! Application::is_application_resource( object_to_uri( $activity['object'] ) ) ) { | |
| 146 | - return; | |
| 147 | - } | |
| 148 | - | |
| 149 | - $actor = object_to_uri( $activity['actor'] ); | |
| 150 | - $remote_actor = Remote_Actors::fetch_by_uri( $actor ); | |
| 151 | - | |
| 152 | - if ( \is_wp_error( $remote_actor ) ) { | |
| 153 | - return; | |
| 154 | - } | |
| 155 | - | |
| 156 | - $inbox = \get_post_meta( $remote_actor->ID, '_activitypub_inbox', true ); | |
| 157 | - | |
| 158 | - if ( ! $inbox ) { | |
| 159 | - return; | |
| 160 | - } | |
| 161 | - | |
| 131 | + public static function queue_reject( $activity, $user_id ) { | |
| 162 | 132 | // Only send minimal data. |
| 163 | - $origin_activity = \array_intersect_key( | |
| 133 | + $origin_activity = array_intersect_key( | |
| 164 | 134 | $activity, |
| 165 | 135 | array( |
| 166 | 136 | 'id' => 1, |
| 167 | 137 | 'type' => 1, |
| @@ -169,14 +139,13 @@ | ||
| 169 | 139 | 'object' => 1, |
| 170 | 140 | ) |
| 171 | 141 | ); |
| 172 | 142 | |
| 173 | - $reject = new Activity(); | |
| 174 | - $reject->set_type( 'Reject' ); | |
| 175 | - $reject->set_id( Application::get_id() . '#reject-' . \md5( \wp_json_encode( $origin_activity ) ) ); | |
| 176 | - $reject->set_actor( Application::get_id() ); | |
| 177 | - $reject->set_object( $origin_activity ); | |
| 178 | - $reject->set_to( array( $actor ) ); | |
| 143 | + $activity = new Activity(); | |
| 144 | + $activity->set_type( 'Reject' ); | |
| 145 | + $activity->set_actor( Actors::get_by_id( $user_id )->get_id() ); | |
| 146 | + $activity->set_object( $origin_activity ); | |
| 147 | + $activity->set_to( array( $origin_activity['actor'] ) ); | |
| 179 | 148 | |
| 180 | - Http::post( $inbox, $reject->to_json(), null ); | |
| 149 | + add_to_outbox( $activity, null, $user_id, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE ); | |
| 181 | 150 | } |
| 182 | 151 | } |