Skip to content

Commit e3ba2f0

Browse files
authored
Deliver public activities to followers only (#2539)
1 parent ef3d2cd commit e3ba2f0

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fixed
3+
4+
Deliver public activities to followers only.

includes/rest/class-inbox-controller.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,8 @@ public function get_item_schema() {
368368
* @return array An array of user IDs who are the recipients of the activity.
369369
*/
370370
private function get_local_recipients( $activity ) {
371-
// Public activity, deliver to all local ActivityPub users.
372-
if ( is_activity_public( $activity ) ) {
373-
return Actors::get_all_ids();
371+
if ( is_activity_public( $activity ) ) { // Public activity, deliver to followers of the actor.
372+
return Following::get_follower_ids( $activity['actor'] );
374373
}
375374

376375
$recipients = extract_recipients_from_activity( $activity );

tests/phpunit/tests/includes/rest/class-test-inbox-controller.php

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,36 @@ public function test_create_item_with_invalid_request() {
458458
* @covers ::get_local_recipients
459459
*/
460460
public function test_get_local_recipients_no_recipients() {
461+
// Enable actor mode to allow user actors.
462+
\update_option( 'activitypub_actor_mode', ACTIVITYPUB_ACTOR_MODE );
463+
464+
// Create a remote actor and make a user follow them.
465+
$remote_actor_url = 'https://example.com/actor/no-recipients';
466+
467+
// Mock the remote actor fetch.
468+
$remote_object_filter = function ( $pre, $url ) use ( $remote_actor_url ) {
469+
if ( $url === $remote_actor_url ) {
470+
return array(
471+
'@context' => 'https://www.w3.org/ns/activitystreams',
472+
'id' => $remote_actor_url,
473+
'type' => 'Person',
474+
'preferredUsername' => 'testactor',
475+
'name' => 'Test Actor',
476+
'inbox' => 'https://example.com/actor/1/inbox',
477+
);
478+
}
479+
return $pre;
480+
};
481+
\add_filter( 'activitypub_pre_http_get_remote_object', $remote_object_filter, 10, 2 );
482+
483+
$remote_actor = \Activitypub\Collection\Remote_Actors::fetch_by_uri( $remote_actor_url );
484+
485+
// Make test user follow the remote actor.
486+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', self::$user_id );
487+
461488
$activity = array(
462-
'type' => 'Create',
489+
'type' => 'Create',
490+
'actor' => $remote_actor_url,
463491
);
464492

465493
// Use reflection to test the private method.
@@ -468,9 +496,13 @@ public function test_get_local_recipients_no_recipients() {
468496
$method->setAccessible( true );
469497

470498
$result = $method->invoke( $this->inbox_controller, $activity );
471-
// Activities with no recipients are treated as public and delivered to all local actors.
472-
$this->assertNotEmpty( $result, 'Should return all local actors when no recipients (treated as public)' );
473-
$this->assertEquals( Actors::get_all_ids(), $result, 'Should match all local actor IDs' );
499+
// Activities with no recipients are treated as public and delivered to followers only.
500+
$this->assertNotEmpty( $result, 'Should return followers when no recipients (treated as public)' );
501+
$this->assertContains( self::$user_id, $result, 'Should contain the follower' );
502+
503+
// Clean up.
504+
\delete_option( 'activitypub_actor_mode' );
505+
\remove_filter( 'activitypub_pre_http_get_remote_object', $remote_object_filter );
474506
}
475507

476508
/**
@@ -580,10 +612,10 @@ public function test_get_local_recipients_public_activity() {
580612
$remote_actor = \Activitypub\Collection\Remote_Actors::fetch_by_uri( $remote_actor_url );
581613

582614
// Make users follow the remote actor.
583-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', self::$user_id );
584-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', $user_id_1 );
585-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', $user_id_2 );
586-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', $user_id_3 );
615+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', self::$user_id );
616+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', $user_id_1 );
617+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', $user_id_2 );
618+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', $user_id_3 );
587619

588620
// Public activity with "to" containing the public collection.
589621
$activity = array(
@@ -651,8 +683,8 @@ public function test_get_local_recipients_public_activity_in_cc() {
651683
$remote_actor = \Activitypub\Collection\Remote_Actors::fetch_by_uri( $remote_actor_url );
652684

653685
// Make users follow the remote actor.
654-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', self::$user_id );
655-
\add_post_meta( $remote_actor->ID, '_activitypub_followers', $user_id );
686+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', self::$user_id );
687+
\add_post_meta( $remote_actor->ID, '_activitypub_followed_by', $user_id );
656688

657689
// Public activity with "cc" containing the public collection.
658690
$activity = array(

0 commit comments

Comments
 (0)