Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/User Delete activities #552

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
bcf29e1
Profiles: update followers when profile fields change
mattwiebe Oct 31, 2023
e3a78fb
use static
mattwiebe Oct 31, 2023
af3e61c
only try to merge mention inboxes when valid
mattwiebe Nov 1, 2023
3785cee
Add Server Class, known_inboxes method
mediaformat Nov 8, 2023
d64ed73
Add a server dispatch activity
mediaformat Nov 8, 2023
565a6ca
Add a delete wp user action
mediaformat Nov 8, 2023
9e8065a
lint:fix
mediaformat Nov 8, 2023
4d83e1a
Merge branch 'master' into add/ServerActivities
pfefferle Nov 10, 2023
7543884
Add blog user followers to known inboxes
mediaformat Nov 10, 2023
05b4ebf
public function
mediaformat Nov 11, 2023
2bfb930
update send_server_activity
mediaformat Nov 11, 2023
6c548bc
update delete schedulers
mediaformat Nov 11, 2023
41f05ef
get temporary key for deleted user
mediaformat Nov 11, 2023
f101daf
Merge branch 'master' into add/ServerActivities
mediaformat Nov 11, 2023
87d32cb
Merge branch 'master' into add/ServerActivities
mediaformat Nov 13, 2023
06a023e
Rename to Application class
mediaformat Nov 13, 2023
5090e84
Merge branch 'master' into add/ServerActivities
mediaformat Nov 27, 2023
8499aa4
Merge branch 'master' into add/ServerActivities
pfefferle Nov 30, 2023
96b29a3
Merge branch 'master' into add/ServerActivities
pfefferle Dec 18, 2023
76771aa
Merge branch 'master' into add/ServerActivities
pfefferle May 6, 2024
fcbfa74
Fix PHP errors and lint issues
mattwiebe May 7, 2024
ca3d1bc
Update includes/class-scheduler.php
mediaformat May 8, 2024
e894bc6
Rename action and function
mediaformat May 8, 2024
1aa30ed
Use get_all_followers for inboxes
mediaformat May 8, 2024
fb0f679
schedule_actor_delete
mediaformat May 8, 2024
61951f7
has_cap activitypub
mediaformat May 8, 2024
4cef50d
activitypub_send_actor_delete_activity
mediaformat May 8, 2024
6c1fa00
remove Application class
mediaformat May 8, 2024
01b4d09
private key already stored
mediaformat May 8, 2024
22a664e
clean up user, delete signature options key
mediaformat May 8, 2024
aa448d3
get signing keys from options for actor delete activity
mediaformat May 9, 2024
f9fee8c
Send Delete activity to shared_inboxes
mediaformat May 9, 2024
2df226e
set temp signature option
mediaformat May 9, 2024
d1e0074
cleanup
mediaformat May 9, 2024
bf50942
phpcs
mediaformat May 9, 2024
c781662
phpcbf
mediaformat May 9, 2024
39fffc7
Merge branch 'master' into add/ServerActivities
pfefferle May 16, 2024
7af4eb1
Merge branch 'master' into add/ServerActivities
pfefferle May 16, 2024
c9477d7
Merge branch 'master' into add/ServerActivities
pfefferle Jun 4, 2024
dc88d91
Merge branch 'master' into add/ServerActivities
pfefferle Jun 25, 2024
b84286e
init cli
pfefferle Jun 25, 2024
0de423a
add http gone class
pfefferle Jun 26, 2024
2f33377
add http gone
pfefferle Jun 26, 2024
39e6e71
rewrite dispatcher a bit
pfefferle Jun 26, 2024
520c3fb
mark as federated
pfefferle Jun 26, 2024
962e6dd
cleanups
pfefferle Jun 26, 2024
2730907
remove lagacy code
pfefferle Jun 26, 2024
295d5bc
fix instance of check
pfefferle Jun 26, 2024
4fcf151
better $user handling
pfefferle Jun 27, 2024
f319cac
better support of system users
pfefferle Jun 27, 2024
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
14 changes: 14 additions & 0 deletions activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

namespace Activitypub;

use WP_CLI;

use function Activitypub\is_blog_public;
use function Activitypub\site_supports_blocks;

Expand Down Expand Up @@ -81,6 +83,7 @@ function plugin_init() {
\add_action( 'init', array( __NAMESPACE__ . '\Health_Check', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Scheduler', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Comment', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Http_Gone', 'init' ) );

if ( site_supports_blocks() ) {
\add_action( 'init', array( __NAMESPACE__ . '\Blocks', 'init' ) );
Expand Down Expand Up @@ -234,3 +237,14 @@ function get_plugin_version() {

return $meta['Version'];
}

// Check for CLI env, to add the CLI commands
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command(
'activitypub',
'\Activitypub\Cli',
array(
'shortdesc' => __( 'Some ActivityPub related commands.', 'activitypub' ),
)
);
}
27 changes: 26 additions & 1 deletion includes/class-activity-dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
use Activitypub\Transformer\Factory;
use Activitypub\Transformer\Post;
use Activitypub\Transformer\Comment;

use function Activitypub\is_single_user;
Expand All @@ -33,6 +32,7 @@ public static function init() {
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity' ), 10, 2 );
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity_or_announce' ), 10, 2 );
\add_action( 'activitypub_send_update_profile_activity', array( self::class, 'send_profile_update' ), 10, 1 );
\add_action( 'activitypub_send_actor_delete_activity', array( self::class, 'send_actor_delete_activity' ), 10, 2 );
}

/**
Expand Down Expand Up @@ -186,6 +186,31 @@ private static function send_activity_to_followers( $activity, $user_id, $wp_obj
set_wp_object_state( $wp_object, 'federated' );
}

/**
* Send an Activity to all known (shared_)inboxes.
*
* @param WP_User $user The deleted WordPress User.
*
* @return void
*/
public static function send_actor_delete_activity( $user ) {
$url = \get_author_posts_url( null, $user->user_nicename );

$activity = new Activity();
$activity->set_id( $url . '#delete' );
$activity->set_type( 'Delete' );
$activity->set_actor( $url );
$activity->set_object( $url );
$activity->set_to( 'https://www.w3.org/ns/activitystreams#Public' );

$json = $activity->to_json();
$inboxes = Followers::get_inboxes( Followers::ALL );

foreach ( $inboxes as $inbox ) {
safe_remote_post( $inbox, $json, $user );
}
}

/**
* Send a "Create" or "Update" Activity for a WordPress Post.
*
Expand Down
136 changes: 136 additions & 0 deletions includes/class-cli.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php
namespace Activitypub;

use WP_CLI;
use WP_CLI_Command;

/**
* WP-CLI commands
*
* @package Activitypub
*/
class Cli extends WP_CLI_Command {
/**
* See the Plugin Meta-Informations
*
* ## OPTIONS
*
* [--Name]
* The Plugin Name
*
* [--PluginURI]
* The Plugin URI
*
* [--Version]
* The Plugin Version
*
* [--Description]
* The Plugin Description
*
* [--Author]
* The Plugin Author
*
* [--AuthorURI]
* The Plugin Author URI
*
* [--TextDomain]
* The Plugin Text Domain
*
* [--DomainPath]
* The Plugin Domain Path
*
* [--Network]
* The Plugin Network
*
* [--RequiresWP]
* The Plugin Requires at least
*
* [--RequiresPHP]
* The Plugin Requires PHP
*
* [--UpdateURI]
* The Plugin Update URI
*
* See: https://developer.wordpress.org/reference/functions/get_plugin_data/#return
*
* ## EXAMPLES
*
* $ wp webmention meta
*
* $ wp webmention meta --Version
* Version: 1.0.0
*
* @param array|null $args The arguments.
* @param array|null $assoc_args The associative arguments.
*
* @return void
*/
public function meta( $args, $assoc_args ) {
$plugin_data = get_plugin_meta();

if ( $assoc_args ) {
$plugin_data = array_intersect_key( $plugin_data, $assoc_args );
} else {
WP_CLI::line( __( "ActivityPub Plugin Meta:\n", 'activitypub' ) );
}

foreach ( $plugin_data as $key => $value ) {
WP_CLI::line( $key . ': ' . $value );
}
}

/**
* Remove the blog from the Fediverse.
*
* ## EXAMPLES
*
* $ wp activitypub self-destruct
*
* @subcommand self-destruct
*
* @param array|null $args The arguments.
* @param array|null $assoc_args The associative arguments.
*
* @return void
*/
public function self_destruct( $args, $assoc_args ) {
$question = __( 'We are in the process of deleting your blog from the Fediverse. This action could be irreversible, so are you sure you want to continue?', 'activitypub' );
WP_CLI::confirm( WP_CLI::colorize( "%r{$question}%n" ), $assoc_args = array() );

WP_CLI::success( __( 'Deleting your Blog from the Fediverse...', 'activitypub' ) );

// Deactivate the ActivityPub Plugin after the deletion.
WP_CLI::runcommand( 'plugin deactivate activitypub' );
}

/**
* Delete or Update a User.
*
* ## OPTIONS
*
* <action>
* : The action to perform. Either `delete` or `update`.
* ---
* options:
* - delete
* - update
* ---
*
* <id>
* : The id of the registered WordPress user.
*
* ## EXAMPLES
*
* $ wp activitypub user delete 1
*
* @synopsis <action> <id>
*
* @param array|null $args The arguments.
* @param array|null $assoc_args The associative arguments.
*
* @return void
*/
public function user( $args, $assoc_args ) {
// @todo add code
}
}
71 changes: 71 additions & 0 deletions includes/class-http-gone.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Activitypub;

use WP_Query;

/**
* Send HTTP 410 for deleted Posts/Pages and Authors
*
* @author Matthias Pfefferle
*/
class Http_Gone {
/**
* Initialize Deleted Posts Plugin
*/
public static function init() {
add_action( 'template_redirect', array( static::class, 'handle_410' ), 99 );
}

public static function handle_410() {
$is_410 = false;

if ( ! is_404() ) {
return;
}

global $wp_query;

// Check Post Slug
if ( ! empty( $wp_query->query['pagename'] ) ) {
$query = new WP_Query(
array(
'pagename' => $wp_query->query['pagename'] . '__trashed',
'post_status' => 'trash',
)
);

if ( $query->get_posts() ) {
$is_410 = true;
}
} elseif ( ! empty( $wp_query->query['name'] ) ) {
$query = new WP_Query(
array(
'name' => $wp_query->query['name'] . '__trashed',
'post_status' => 'trash',
)
);

if ( $query->get_posts() ) {
$is_410 = true;
}
} elseif ( ! empty( $wp_query->query['author_name'] ) ) {
// Check if author is deleted
$is_410 = true;
} else {
return;
}

// Return 410 if trashed post exists
if ( $is_410 ) {
status_header( 410 );
// check if theme has a 410.php template
$template_410 = get_query_template( 410 );
// return 410 template
if ( $template_410 ) {
load_template( $template_410 );
exit;
}
}
}
}
14 changes: 7 additions & 7 deletions includes/class-http.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ class Http {
/**
* Send a POST Request with the needed HTTP Headers
*
* @param string $url The URL endpoint
* @param string $body The Post Body
* @param int $user_id The WordPress User-ID
* @param string $url The URL endpoint
* @param string $body The Post Body
* @param WP_User|int $user The WordPress User or ID
*
* @return array|WP_Error The POST Response or an WP_ERROR
*/
public static function post( $url, $body, $user_id ) {
\do_action( 'activitypub_pre_http_post', $url, $body, $user_id );
public static function post( $url, $body, $user ) {
\do_action( 'activitypub_pre_http_post', $url, $body, $user );

$date = \gmdate( 'D, d M Y H:i:s T' );
$digest = Signature::generate_digest( $body );
$signature = Signature::generate_signature( $user_id, 'post', $url, $date, $digest );
$signature = Signature::generate_signature( $user, 'post', $url, $date, $digest );

$wp_version = get_masked_wp_version();

Expand Down Expand Up @@ -58,7 +58,7 @@ public static function post( $url, $body, $user_id ) {
$response = new WP_Error( $code, __( 'Failed HTTP Request', 'activitypub' ), array( 'status' => $code ) );
}

\do_action( 'activitypub_safe_remote_post_response', $response, $url, $body, $user_id );
\do_action( 'activitypub_safe_remote_post_response', $response, $url, $body, $user );

return $response;
}
Expand Down
25 changes: 24 additions & 1 deletion includes/class-scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
use Activitypub\Transformer\Post;
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
use Activitypub\Activity\Activity;

use function Activitypub\was_comment_sent;
use function Activitypub\get_private_key_for;
use function Activitypub\is_user_type_disabled;
use function Activitypub\was_comment_sent;
use function Activitypub\should_comment_be_federated;
use function Activitypub\get_remote_metadata_by_actor;

Expand Down Expand Up @@ -75,6 +77,7 @@ function ( $comment_id ) {

// profile updates for user options
if ( ! is_user_type_disabled( 'user' ) ) {
mediaformat marked this conversation as resolved.
Show resolved Hide resolved
\add_action( 'delete_user', array( self::class, 'schedule_actor_delete' ), 10, 3 );
\add_action( 'wp_update_user', array( self::class, 'user_update' ) );
\add_action( 'updated_user_meta', array( self::class, 'user_meta_update' ), 10, 3 );
// @todo figure out a feasible way of updating the header image since it's not unique to any user.
Expand Down Expand Up @@ -330,4 +333,24 @@ public static function schedule_profile_update( $user_id ) {
array( $user_id )
);
}

/**
* Send an Actor Delete activity.
*
* @param int $id ID of the user to delete.
* @param int|null $reassign ID of the user to reassign posts and links to.
* Default null, for no reassignment.
* @param WP_User $user WP_User object of the user to delete.
*/
public static function schedule_actor_delete( $user_id, $reassign, $deleted_user ) {
$caps = $deleted_user->allcaps;

// Check if 'activitypub' capability is set.
if ( isset( $caps['activitypub'] ) ) {
// Do not send activities if user is not allowed to publish.
unset( $deleted_user->data->user_pass );
unset( $deleted_user->allcaps );
\wp_schedule_single_event( \time(), 'activitypub_send_actor_delete_activity', array( $deleted_user ) );
}
}
}
Loading
Loading