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

Generate a WP_User for the Blog and Application User #709

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ function rest_init() {
* Initialize plugin.
*/
function plugin_init() {
\add_action( 'init', array( __NAMESPACE__ . '\Migration', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Activitypub', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Activity_Dispatcher', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Handler', 'init' ) );
Expand Down Expand Up @@ -103,6 +102,9 @@ function plugin_init() {
}
\add_action( 'plugins_loaded', __NAMESPACE__ . '\plugin_init' );

\add_action( 'init', array( __NAMESPACE__ . '\Migration', 'init' ) );
\add_action( 'activate_blog', array( __NAMESPACE__ . '\Setup', 'init' ) );
\add_action( 'wp_initialize_site', array( __NAMESPACE__ . '\Setup', 'init' ) );

/**
* Class Autoloader
Expand Down
61 changes: 61 additions & 0 deletions includes/activity/class-actor.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,65 @@ class Actor extends Base_Object {
* @var boolean
*/
protected $manually_approves_followers = false;

/**
* The Featured-Posts.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#featured
*
* @context {
* "@id": "http://joinmastodon.org/ns#featured",
* "@type": "@id"
* }
*
* @var string
*/
protected $featured;

/**
* Moderators endpoint.
*
* @see https://join-lemmy.org/docs/contributors/05-federation.html
*
* @var string
*/
protected $moderators;

/**
* If the User is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
* @context http://joinmastodon.org/ns#discoverable
*
* @var boolean
*/
protected $discoverable = true;

/**
* If the User is indexable.
*
* @context http://joinmastodon.org/ns#indexable
*
* @var boolean
*/
protected $indexable;

/**
* The WebFinger Resource.
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/2c59/fep-2c59.md
*
* @var string<url>
*/
protected $webfinger;

/**
* Restrict posting to mods
*
* @see https://join-lemmy.org/docs/contributors/05-federation.html
*
* @var boolean
*/
protected $posting_restricted_to_mods = null;
}
39 changes: 5 additions & 34 deletions includes/class-migration.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php
namespace Activitypub;

use Activitypub\Setup;
use Activitypub\Activitypub;
use Activitypub\Model\Blog_User;
use Activitypub\Activity\Actor;
use Activitypub\Collection\Followers;

/**
Expand Down Expand Up @@ -112,7 +113,8 @@ public static function maybe_migrate() {

// check for inital migration
if ( ! $version_from_db ) {
self::add_default_settings();
Setup::init();
\do_action( 'activitypub_initialize_plugin' );
$version_from_db = self::get_target_version();
}

Expand Down Expand Up @@ -251,37 +253,6 @@ private static function migrate_from_2_0_0() {
* @return void
*/
private static function migrate_from_2_1_0() {
// add the ActivityPub capability to all users that can publish posts
self::add_activitypub_capability();
}

/**
* Set the defaults needed for the plugin to work
*
* * Add the ActivityPub capability to all users that can publish posts
*
* @return void
*/
public static function add_default_settings() {
self::add_activitypub_capability();
}

/**
* Add the ActivityPub capability to all users that can publish posts
*
* @return void
*/
private static function add_activitypub_capability() {
// get all WP_User objects that can publish posts
$users = \get_users(
array(
'capability__in' => array( 'publish_posts' ),
)
);

// add ActivityPub capability to all users that can publish posts
foreach ( $users as $user ) {
$user->add_cap( 'activitypub' );
}
Setup::init();
}
}
133 changes: 133 additions & 0 deletions includes/class-setup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php
namespace Activitypub;

use WP_Roles;

/**
* ActivityPub Migration Class
*
* @author Matthias Pfefferle
*/
class Setup {
/**
* Initialize the class, registering WordPress hooks
*/
public static function init() {
self::add_roles();
self::add_activitypub_capability();
self::generate_blog_user();
self::generate_aplication_user();
}

/**
* Add the ActivityPub capability to all users that can publish posts
*
* @return void
*/
private static function add_activitypub_capability() {
// get all WP_User objects that can publish posts
$users = \get_users(
array(
'capability__in' => array( 'publish_posts' ),
)
);

// add ActivityPub capability to all users that can publish posts
foreach ( $users as $user ) {
$user->add_cap( 'activitypub' );
}
}

/**
* Generate the ActivityPub Blog User
*
* @return void
*/
public static function generate_blog_user() {
$user_pass = wp_generate_password( 15, true, true );

// check if domain host has a subdomain
$host = \wp_parse_url( \get_home_url(), \PHP_URL_HOST );
$host = \preg_replace( '/^www\./i', '', $host );

wp_insert_user(
array(
'user_login' => $host,
'user_pass' => $user_pass,
'display_name' => 'The ActivityPub Blog User',
'description' => \get_bloginfo( 'description' ),
'role' => 'activitypub_blog',
)
);
}

/**
* Generate the ActivityPub Application User
*
* @return void
*/
public static function generate_aplication_user() {
$user_pass = wp_generate_password( 15, true, true );

wp_insert_user(
array(
'user_login' => 'application',
'display_name' => 'The ActivityPub Application User',
'user_pass' => $user_pass,
'description' => \get_bloginfo( 'description' ),
'role' => 'activitypub_application',
)
);
}

/**
* Add the ActivityPub roles to the site
*
* @return void
*/
public static function add_roles() {
$default_roles = array(
'activitypub_application' => _x( 'ActivityPub Application', 'User role', 'activitypub' ),
'activitypub_blog' => _x( 'ActivityPub Blog', 'User role', 'activitypub' ),
);

$roles = new WP_Roles();

foreach ( $default_roles as $type => $name ) {
$role = false;
foreach ( $roles->roles as $slug => $data ) {
if ( isset( $data['capabilities'][ $type ] ) ) {
$role = get_role( $slug );
break;
}
}
if ( ! $role ) {
$role = add_role( $type, $name, self::get_role_capabilities( $type ) );
continue;
}

// This might update missing capabilities.
foreach ( array_keys( self::get_role_capabilities( $type ) ) as $cap ) {
$role->add_cap( $cap );
}
}
}

public static function get_role_capabilities( $role ) {
$capabilities = array();

$capabilities['activitypub_application'] = array(
'activitypub' => true,
);

$capabilities['activitypub_blog'] = array(
'activitypub' => true,
);

if ( ! isset( $capabilities[ $role ] ) ) {
return array();
}

return $capabilities[ $role ];
}
}
2 changes: 1 addition & 1 deletion includes/class-signature.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ protected static function check_legacy_key_pair_for( $user_id ) {
*/
public static function generate_signature( $user_id, $http_method, $url, $date, $digest = null ) {
$user = Users::get_by_id( $user_id );
$key = self::get_private_key_for( $user->get__id() );
$key = self::get_private_key_for( $user_id );

$url_parts = \wp_parse_url( $url );

Expand Down
54 changes: 43 additions & 11 deletions includes/collection/class-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

use WP_Error;
use WP_User_Query;
use Activitypub\Model\User;
use Activitypub\Model\Blog_User;
use Activitypub\Model\Application_User;
use Activitypub\Transformer\User;

use function Activitypub\url_to_authorid;
use function Activitypub\is_user_disabled;
Expand Down Expand Up @@ -45,12 +43,18 @@ public static function get_by_id( $user_id ) {
);
}

$user = null;

if ( self::BLOG_USER_ID === $user_id ) {
return Blog_User::from_wp_user( $user_id );
$user = self::get_blog();
} elseif ( self::APPLICATION_USER_ID === $user_id ) {
return Application_User::from_wp_user( $user_id );
$user = self::get_application();
} elseif ( $user_id > 0 ) {
return User::from_wp_user( $user_id );
$user = get_user_by( 'id', $user_id );
}

if ( $user ) {
return User::transform( $user )->to_actor();
}

return new WP_Error(
Expand All @@ -69,10 +73,6 @@ public static function get_by_id( $user_id ) {
*/
public static function get_by_username( $username ) {
// check for blog user.
if ( Blog_User::get_default_username() === $username ) {
return self::get_by_id( self::BLOG_USER_ID );
}

if ( get_option( 'activitypub_blog_user_identifier' ) === $username ) {
return self::get_by_id( self::BLOG_USER_ID );
}
Expand Down Expand Up @@ -275,9 +275,41 @@ public static function get_collection() {
$return = array();

foreach ( $users as $user ) {
$return[] = User::from_wp_user( $user->ID );
$return[] = User::transform( $user )->to_actor();
}

return $return;
}

public static function get_blog() {
$users = get_users(
array(
'role' => 'activitypub_blog',
'orderby' => 'user_nicename',
'order' => 'ASC',
)
);

if ( ! empty( $users ) ) {
return current( $users );
}

return null;
}

public static function get_application() {
$users = get_users(
array(
'role' => 'activitypub_application',
'orderby' => 'user_nicename',
'order' => 'ASC',
)
);

if ( ! empty( $users ) ) {
return current( $users );
}

return null;
}
}
2 changes: 1 addition & 1 deletion includes/rest/class-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use WP_Error;
use WP_REST_Response;
use Activitypub\Signature;
use Activitypub\Model\Application_User;
use Activitypub\Activity\Actor;

/**
* ActivityPub Server REST-Class
Expand Down