updated plugin ActivityPub version 2.4.0

This commit is contained in:
2024-06-27 12:10:38 +00:00
committed by Gitium
parent eeef5ad6e0
commit 4e493c268e
49 changed files with 1368 additions and 491 deletions

View File

@ -12,13 +12,13 @@ use Activitypub\Collection\Users as User_Collection;
use function Activitypub\is_activitypub_request;
/**
* ActivityPub Followers REST-Class
* ActivityPub Actors REST-Class
*
* @author Matthias Pfefferle
*
* @see https://www.w3.org/TR/activitypub/#followers
*/
class Users {
class Actors {
/**
* Initialize the class, registering WordPress hooks
*/
@ -32,7 +32,7 @@ class Users {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)',
'/(users|actors)/(?P<user_id>[\w\-\.]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -45,7 +45,7 @@ class Users {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/remote-follow',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/remote-follow',
array(
array(
'methods' => WP_REST_Server::READABLE,

View File

@ -1,13 +1,12 @@
<?php
namespace Activitypub\Rest;
use WP_Error;
use WP_REST_Server;
use WP_REST_Response;
use Activitypub\Transformer\Post;
use Activitypub\Activity\Actor;
use Activitypub\Activity\Base_Object;
use Activitypub\Collection\Users as User_Collection;
use Activitypub\Transformer\Factory;
use function Activitypub\esc_hashtag;
use function Activitypub\is_single_user;
@ -35,7 +34,7 @@ class Collection {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/collections/tags',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/collections/tags',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -48,7 +47,7 @@ class Collection {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/collections/featured',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/collections/featured',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -104,7 +103,7 @@ class Collection {
$response = array(
'@context' => Base_Object::JSON_LD_CONTEXT,
'id' => get_rest_url_by_path( sprintf( 'users/%d/collections/tags', $user->get__id() ) ),
'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $user->get__id() ) ),
'type' => 'Collection',
'totalItems' => is_countable( $tags ) ? count( $tags ) : 0,
'items' => array(),
@ -162,14 +161,20 @@ class Collection {
$response = array(
'@context' => Base_Object::JSON_LD_CONTEXT,
'id' => get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $user_id ) ),
'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $user_id ) ),
'type' => 'OrderedCollection',
'totalItems' => is_countable( $posts ) ? count( $posts ) : 0,
'orderedItems' => array(),
);
foreach ( $posts as $post ) {
$response['orderedItems'][] = Post::transform( $post )->to_object()->to_array( false );
$transformer = Factory::get_transformer( $post );
if ( \is_wp_error( $transformer ) ) {
continue;
}
$response['orderedItems'][] = $transformer->to_object()->to_array( false );
}
$rest_response = new WP_REST_Response( $response, 200 );

View File

@ -29,7 +29,7 @@ class Comment {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/comments/(?P<comment_id>\d+)/remote-reply',
'/(users|actors)/(?P<comment_id>\d+)/remote-reply',
array(
array(
'methods' => WP_REST_Server::READABLE,

View File

@ -32,7 +32,7 @@ class Followers {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/followers',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/followers',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -74,13 +74,13 @@ class Followers {
$json->{'@context'} = \Activitypub\get_context();
$json->id = get_rest_url_by_path( sprintf( 'users/%d/followers', $user->get__id() ) );
$json->id = get_rest_url_by_path( sprintf( 'actors/%d/followers', $user->get__id() ) );
$json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version();
$json->actor = $user->get_id();
$json->type = 'OrderedCollectionPage';
$json->totalItems = $data['total']; // phpcs:ignore
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/followers', $user->get__id() ) ); // phpcs:ignore
$json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/followers', $user->get__id() ) ); // phpcs:ignore
$json->first = \add_query_arg( 'page', 1, $json->partOf ); // phpcs:ignore
$json->last = \add_query_arg( 'page', \ceil ( $json->totalItems / $per_page ), $json->partOf ); // phpcs:ignore

View File

@ -31,7 +31,7 @@ class Following {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/following',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/following',
array(
array(
'methods' => \WP_REST_Server::READABLE,
@ -67,12 +67,12 @@ class Following {
$json->{'@context'} = \Activitypub\get_context();
$json->id = get_rest_url_by_path( sprintf( 'users/%d/following', $user->get__id() ) );
$json->id = get_rest_url_by_path( sprintf( 'actors/%d/following', $user->get__id() ) );
$json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version();
$json->actor = $user->get_id();
$json->type = 'OrderedCollectionPage';
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/following', $user->get__id() ) ); // phpcs:ignore
$json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/following', $user->get__id() ) ); // phpcs:ignore
$items = apply_filters( 'activitypub_rest_following', array(), $user ); // phpcs:ignore

View File

@ -48,7 +48,7 @@ class Inbox {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/inbox',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/inbox',
array(
array(
'methods' => WP_REST_Server::CREATABLE,
@ -90,10 +90,10 @@ class Inbox {
$json = new \stdClass();
$json->{'@context'} = get_context();
$json->id = get_rest_url_by_path( sprintf( 'users/%d/inbox', $user->get__id() ) );
$json->id = get_rest_url_by_path( sprintf( 'actors/%d/inbox', $user->get__id() ) );
$json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version();
$json->type = 'OrderedCollectionPage';
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/inbox', $user->get__id() ) ); // phpcs:ignore
$json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/inbox', $user->get__id() ) ); // phpcs:ignore
$json->totalItems = 0; // phpcs:ignore
$json->orderedItems = array(); // phpcs:ignore
$json->first = $json->partOf; // phpcs:ignore

View File

@ -5,9 +5,9 @@ use stdClass;
use WP_Error;
use WP_REST_Server;
use WP_REST_Response;
use Activitypub\Transformer\Post;
use Activitypub\Activity\Activity;
use Activitypub\Collection\Users as User_Collection;
use Activitypub\Transformer\Factory;
use function Activitypub\get_context;
use function Activitypub\get_rest_url_by_path;
@ -34,7 +34,7 @@ class Outbox {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/users/(?P<user_id>[\w\-\.]+)/outbox',
'/(users|actors)/(?P<user_id>[\w\-\.]+)/outbox',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -72,11 +72,11 @@ class Outbox {
$json = new stdClass();
$json->{'@context'} = get_context();
$json->id = get_rest_url_by_path( sprintf( 'users/%d/outbox', $user_id ) );
$json->id = get_rest_url_by_path( sprintf( 'actors/%d/outbox', $user_id ) );
$json->generator = 'http://wordpress.org/?v=' . get_masked_wp_version();
$json->actor = $user->get_id();
$json->type = 'OrderedCollectionPage';
$json->partOf = get_rest_url_by_path( sprintf( 'users/%d/outbox', $user_id ) ); // phpcs:ignore
$json->partOf = get_rest_url_by_path( sprintf( 'actors/%d/outbox', $user_id ) ); // phpcs:ignore
$json->totalItems = 0; // phpcs:ignore
if ( $user_id > 0 ) {
@ -111,7 +111,13 @@ class Outbox {
);
foreach ( $posts as $post ) {
$post = Post::transform( $post )->to_object();
$transformer = Factory::get_transformer( $post );
if ( \is_wp_error( $transformer ) ) {
continue;
}
$post = $transformer->to_object();
$activity = new Activity();
$activity->set_type( 'Create' );
$activity->set_object( $post );

View File

@ -5,7 +5,7 @@ use stdClass;
use WP_Error;
use WP_REST_Response;
use Activitypub\Signature;
use Activitypub\Model\Application_User;
use Activitypub\Model\Application;
/**
* ActivityPub Server REST-Class
@ -47,7 +47,7 @@ class Server {
* @return WP_REST_Response The JSON profile of the Application Actor.
*/
public static function application_actor() {
$user = new Application_User();
$user = new Application();
$json = $user->to_array();
@ -62,6 +62,9 @@ class Server {
*
* @see WP_REST_Request
*
* @see https://www.w3.org/wiki/SocialCG/ActivityPub/Primer/Authentication_Authorization#Authorized_fetch
* @see https://swicg.github.io/activitypub-http-signature/#authorized-fetch
*
* @param WP_REST_Response|WP_HTTP_Response|WP_Error|mixed $response Result to send to the client.
* Usually a WP_REST_Response or WP_Error.
* @param array $handler Route handler used for the request.
@ -80,7 +83,8 @@ class Server {
if (
! \str_starts_with( $route, '/' . ACTIVITYPUB_REST_NAMESPACE ) ||
\str_starts_with( $route, '/' . \trailingslashit( ACTIVITYPUB_REST_NAMESPACE ) . 'webfinger' ) ||
\str_starts_with( $route, '/' . \trailingslashit( ACTIVITYPUB_REST_NAMESPACE ) . 'nodeinfo' )
\str_starts_with( $route, '/' . \trailingslashit( ACTIVITYPUB_REST_NAMESPACE ) . 'nodeinfo' ) ||
\str_starts_with( $route, '/' . \trailingslashit( ACTIVITYPUB_REST_NAMESPACE ) . 'application' )
) {
return $response;
}
@ -102,17 +106,12 @@ class Server {
return $response;
}
// POST-Requets are always signed
if ( 'GET' !== $request->get_method() ) {
$verified_request = Signature::verify_http_signature( $request );
if ( \is_wp_error( $verified_request ) ) {
return new WP_Error(
'activitypub_signature_verification',
$verified_request->get_error_message(),
array( 'status' => 401 )
);
}
} elseif ( 'GET' === $request->get_method() && ACTIVITYPUB_AUTHORIZED_FETCH ) { // GET-Requests are only signed in secure mode
if (
// POST-Requests are always signed
'GET' !== $request->get_method() ||
// GET-Requests only require a signature in secure mode
( 'GET' === $request->get_method() && ACTIVITYPUB_AUTHORIZED_FETCH )
) {
$verified_request = Signature::verify_http_signature( $request );
if ( \is_wp_error( $verified_request ) ) {
return new WP_Error(