Handle Accept activities in the outbox

This commit is contained in:
Jeremy Dormitzer 2018-09-23 19:29:20 -04:00
parent a0516187c0
commit 728d7a1c08
8 changed files with 137 additions and 8 deletions

View File

@ -2,6 +2,7 @@
namespace activities\accept;
require_once plugin_dir_path( __FILE__ ) . '/../following.php';
require_once plugin_dir_path( __FILE__ ) . '/../followers.php';
require_once plugin_dir_path( __FILE__ ) . '/../objects.php';
require_once plugin_dir_path( __FILE__ ) . '/../actors.php';
@ -37,4 +38,27 @@ function handle_inbox( $actor_slug, $activity ) {
}
return $activity;
}
function handle_outbox( $actor_slug, $activity ) {
if ( !array_key_exists( 'object', $activity ) ) {
return new \WP_Error(
'invalid_activity',
__( 'Activity must have an "object" field', 'pterotype' ),
array( 'status' => 400 )
);
}
$object = $activity['object'];
if ( array_key_exists( 'type', $object ) ) {
switch ( $object['type'] ) {
case 'Follow':
if ( !array_key_exists( 'actor', $object ) ) {
break;
}
$follower = $object['actor'];
\followers\add_follower( $actor_slug, $follower );
break;
}
}
return $activity;
}
?>

View File

@ -28,17 +28,51 @@ function handle_inbox( $actor_slug, $activity ) {
// For now, always Accept follow requests
// in the future, implement a UI to either accept or reject
// (or automatically accept if the user chooses to enable that setting)
$accept = make_accept( $actor_slug, $activity );
if ( is_wp_error( $accept ) ) {
return $accept;
}
$res = \outbox\handle_activity( $actor_slug, $accept );
if ( is_wp_error( $res ) ) {
return $res;
if ( actor_is_object( $actor_slug, $activity ) ) {
if ( !array_key_exists( 'actor', $activity ) ) {
return new \WP_Error(
'invalid_activity',
__( 'Activity must have an "actor" field', 'pterotype' ),
array( 'status' => 400 )
);
}
$follower = $activity['actor'];
\objects\upsert_object( $follower );
$accept = make_accept( $actor_slug, $activity );
if ( is_wp_error( $accept ) ) {
return $accept;
}
$res = \outbox\handle_activity( $actor_slug, $accept );
if ( is_wp_error( $res ) ) {
return $res;
}
}
return $activity;
}
/*
Return true if the actor denoted by $actor_slug is the object of $activity
*/
function actor_is_object( $actor_slug, $activity ) {
if ( !array_key_exists( 'object', $activity ) ) {
return false;
}
$actor = \actors\get_actor_by_slug( $actor_slug );
if ( is_wp_error( $actor ) ) {
return false;
}
$object = $activity['object'];
if ( !array_key_exists( 'type', $object ) ) {
return false;
}
switch ( $object['type'] ) {
case 'Link':
return array_key_exists( 'href', $object ) && $object['href'] === $actor['id'];
default:
return array_key_exists( 'id', $object ) && $object['id'] === $actor['id'];
}
}
function make_accept( $actor_slug, $follow ) {
if ( !array_key_exists( 'actor', $follow ) ) {
return new \WP_Error(

View File

@ -25,6 +25,11 @@ function get_actor_id( $slug ) {
}
function get_actor_from_row( $row ) {
if ( !$row ) {
return new \WP_Error(
'not_found', __( 'Actor not found', 'pterotype' ), array( 'status' => 404 )
);
}
switch ( $row->type ) {
case "user":
$user = get_user_by( 'slug', $row->slug );

37
inc/followers.php Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace followers;
require_once plugin_dir_path( __FILE__ ) . '/actors.php';
require_once plugin_dir_path( __FILE__ ) . '/objects.php';
function add_follower( $actor_slug, $follower ) {
global $wpdb;
$actor_id = \actors\get_actor_id( $actor_slug );
if ( !$actor_id ) {
return new \WP_Error(
'not_found',
__( 'Actor not found', 'pterotype' ),
array( 'status' => 404 )
);
}
if ( !array_key_exists( 'id', $follower ) ) {
return new \WP_Error(
'invalid_object',
__( 'Object must have an "id" field', 'pterotype' ),
array( 'status' => 400 )
);
}
$object_id = \objects\get_object_id( $follower['id'] );
if ( !$object_id ) {
$row = \objects\upsert_object( $follower );
$object_id = $row->id;
}
$wpdb->insert(
'pterotype_followers',
array(
'actor_id' => $actor_id,
'object_id' = $object_id,
);
);
}
?>

View File

@ -22,6 +22,7 @@ function run_migrations() {
}
apply_migration( '0.0.1', 'migration_0_0_1' );
apply_migration( '0.0.2', 'migration_0_0_2' );
apply_migration( '0.0.3', 'migration_0_0_3' );
update_option( 'pterotype_previously_migrated_version', PTEROTYPE_VERSION );
}
@ -159,4 +160,22 @@ function migration_0_0_2() {
"
);
}
function migration_0_0_3() {
global $wpdb;
$wpdb->query(
"
CREATE TABLE pterotype_followers(
actor_id INT UNSIGNED NOT NULL,
object_id INT UNSIGNED NOT NULL,
PRIMARY KEY (actor_id, object_id),
FOREIGN KEY following_actor_fk(actor_id)
REFERENCES pterotype_actors(id),
FOREIGN KEY following_object_fk(object_id)
REFERENCES pterotype_objects(id)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
"
);
}
?>

View File

@ -170,6 +170,13 @@ function get_object_by_activitypub_id( $activitypub_id ) {
return json_decode( $object_json, true );
}
function get_object_id( $activitypub_id ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare(
'SELECT id FROM pterotype_objects WHERE activitypub_id = %s', $activitypub_id
) );
}
function delete_object( $object ) {
global $wpdb;
if ( !array_key_exists( 'id', $object ) ) {

View File

@ -71,6 +71,9 @@ function handle_activity( $actor_slug, $activity ) {
array( 'status' => 501 )
);
break;
case 'Accept':
$activity = \activities\accept\handle_inbox( $actor_slug, $activity );
break;
default:
$create_activity = wrap_object_in_create( $activity );
if ( is_wp_error( $create_activity ) ) {

View File

@ -4,7 +4,7 @@ Plugin Name: Pterotype
*/
require_once plugin_dir_path( __FILE__ ) . 'inc/init.php';
define( 'PTEROTYPE_VERSION', '0.0.2' );
define( 'PTEROTYPE_VERSION', '0.0.3' );
function pterotype_init() {
do_action( 'pterotype_init' );