Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions includes/class-migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

namespace Activitypub;

use Activitypub\Activity\Activity;
use Activitypub\Collection\Actors;
use Activitypub\Collection\Extra_Fields;
use Activitypub\Collection\Followers;
use Activitypub\Collection\Following;
use Activitypub\Collection\Outbox;
use Activitypub\Collection\Remote_Actors;
use Activitypub\Model\Blog;
use Activitypub\Model\User;
use Activitypub\Transformer\Factory;

/**
Expand Down Expand Up @@ -227,6 +230,11 @@ public static function maybe_migrate() {
*/
\add_action( 'init', array( Activitypub::class, 'flush_rewrite_rules' ), 20 );

if ( \version_compare( $version_from_db, 'unreleased', '<' ) ) {
self::migrate_blog_user_to_query_param_id();
self::migrate_users_to_query_param_id();
}

// Ensure all required cron schedules are registered.
Scheduler::register_schedules();

Expand Down Expand Up @@ -1093,6 +1101,66 @@ private static function clean_up_inbox() {
}
}

/**
* Migrate blog user from permalink-based ID to query param ID.
*
* This sends a Move activity from the old @username URL to the new ?author= URL
* for the blog actor, allowing followers to update their records.
*/
private static function migrate_blog_user_to_query_param_id() {
$use_permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false );

if ( ! $use_permalink ) {
return;
}

$blog = new Blog();
$old_id = \esc_url( \trailingslashit( get_home_url() ) . '@' . $blog->get_preferred_username() );

$activity = new Activity();
$activity->set_type( 'Move' );
$activity->set_actor( $old_id );
$activity->set_origin( $old_id );
$activity->set_object( $old_id );
$activity->set_target( $blog->get_id() );

add_to_outbox( $activity, null, Actors::BLOG_USER_ID, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE );
}

/**
* Migrate users from permalink-based ID to query param ID.
*
* This sends a Move activity from the old author URL to the new ?author= URL
* for each user that had the permalink-as-id setting.
*/
private static function migrate_users_to_query_param_id() {
$users = \get_users(
array(
'capability__in' => array( 'activitypub' ),
)
);

foreach ( $users as $wp_user ) {
$use_permalink = \get_user_option( 'activitypub_use_permalink_as_id', $wp_user->ID );

if ( '1' !== $use_permalink ) {
continue;
}

$user = new User( $wp_user->ID );
$old_id = $user->get_url();

$activity = new Activity();
$activity->set_type( 'Move' );
$activity->set_actor( $old_id );
$activity->set_origin( $old_id );
$activity->set_object( $old_id );
$activity->set_target( $user->get_id() );

add_to_outbox( $activity, null, $wp_user->ID, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE );
}
}

/**
* Migrate URLs from the legacy `activitypub_tombstone_urls` option into the
* `ap_tombstone` custom post type.
Expand Down
4 changes: 2 additions & 2 deletions includes/class-move.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static function externally( $from, $to ) {
$activity->set_target( $target_actor->get_id() );

// Add to outbox.
return add_to_outbox( $activity, null, $user->get__id(), ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC );
return add_to_outbox( $activity, null, $user->get__id(), ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE );
}

/**
Expand Down Expand Up @@ -162,7 +162,7 @@ public static function internally( $from, $to ) {
$activity->set_object( $actor );
$activity->set_target( $to );

return add_to_outbox( $activity, null, $user->get__id(), ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC );
return add_to_outbox( $activity, null, $user->get__id(), ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE );
}

/**
Expand Down
5 changes: 3 additions & 2 deletions includes/collection/class-followers.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,9 @@ public static function get_inboxes( $user_id ) {
*/
public static function get_inboxes_for_activity( $json, $actor_id, $batch_size = 50, $offset = 0 ) {
$activity = \json_decode( $json, true );
// Only if this is a Delete. Create handles its own "Announce" in dual user mode.
if ( 'Delete' === ( $activity['type'] ?? null ) ) {
// Delete and Move activities should be sent to all known inboxes.
// Create handles its own "Announce" in dual user mode.
if ( \in_array( $activity['type'] ?? null, array( 'Delete', 'Move' ), true ) ) {
$inboxes = Remote_Actors::get_inboxes();
} else {
$inboxes = self::get_inboxes( $actor_id );
Expand Down
30 changes: 22 additions & 8 deletions includes/model/class-blog.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,6 @@ public function get_id() {
return $id;
}

$permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false );

if ( $permalink ) {
return \esc_url( \home_url( '/@' . $this->get_preferred_username() ) );
}

return \add_query_arg( 'author', $this->_id, \home_url( '/' ) );
}

Expand Down Expand Up @@ -594,11 +588,31 @@ public function get_also_known_as() {
/**
* Returns the movedTo.
*
* @return string The movedTo.
* @return string|null The movedTo URL or null.
*/
public function get_moved_to() {
$moved_to = \get_option( 'activitypub_blog_user_moved_to' );

return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
if ( $moved_to && $moved_to !== $this->get_id() ) {
return $moved_to;
}

// If the blog had the old permalink-as-id setting and is being accessed
// via the old permalink URL (no author in query string), return the new ID.
$use_permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false );

if ( $use_permalink ) {
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
$query_string = \wp_parse_url( $request_uri, \PHP_URL_QUERY );
$query_params = array();

\wp_parse_str( $query_string ?? '', $query_params );

if ( ! isset( $query_params['author'] ) ) {
return $this->get_id();
}
}

return null;
}
}
30 changes: 22 additions & 8 deletions includes/model/class-user.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ public function get_id() {
return $id;
}

$permalink = \get_user_option( 'activitypub_use_permalink_as_id', $this->_id );

if ( '1' === $permalink ) {
return $this->get_url();
}

return \add_query_arg( 'author', $this->_id, \home_url( '/' ) );
}

Expand Down Expand Up @@ -476,11 +470,31 @@ public function get_also_known_as() {
/**
* Returns the movedTo.
*
* @return string The movedTo.
* @return string|null The movedTo URL or null.
*/
public function get_moved_to() {
$moved_to = \get_user_option( 'activitypub_moved_to', $this->_id );

return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
if ( $moved_to && $moved_to !== $this->get_id() ) {
return $moved_to;
}

// If this user had the old permalink-as-id setting and is being accessed
// via the old permalink URL (no author in query string), return the new ID.
$use_permalink = \get_user_option( 'activitypub_use_permalink_as_id', $this->_id );

if ( '1' === $use_permalink ) {
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
$query_string = \wp_parse_url( $request_uri, \PHP_URL_QUERY );
$query_params = array();

\wp_parse_str( $query_string ?? '', $query_params );

if ( ! isset( $query_params['author'] ) ) {
return $this->get_id();
}
}

return null;
}
}