added health checks
This commit is contained in:
parent
b9fd26e755
commit
f4f46fc084
6 changed files with 233 additions and 29 deletions
|
@ -3,8 +3,8 @@
|
|||
**Donate link:** https://notiz.blog/donate/
|
||||
**Tags:** OStatus, fediverse, activitypub, activitystream
|
||||
**Requires at least:** 4.7
|
||||
**Tested up to:** 5.6
|
||||
**Stable tag:** 0.12.0
|
||||
**Tested up to:** 5.8
|
||||
**Stable tag:** 0.13.0
|
||||
**Requires PHP:** 5.6
|
||||
**License:** MIT
|
||||
**License URI:** http://opensource.org/licenses/MIT
|
||||
|
@ -88,6 +88,11 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
|
|||
|
||||
Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub).
|
||||
|
||||
### 0.13.0 ###
|
||||
|
||||
* add Autor URL and WebFinger health checks
|
||||
* fix NodeInfo endpoint
|
||||
|
||||
### 0.12.0 ###
|
||||
|
||||
* use "pre_option_require_name_email" filter instead of "check_comment_flood". props [@akirk](https://github.com/akirk)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Plugin Name: ActivityPub
|
||||
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
|
||||
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
|
||||
* Version: 0.12.0
|
||||
* Version: 0.13.0
|
||||
* Author: Matthias Pfefferle
|
||||
* Author URI: https://notiz.blog/
|
||||
* License: MIT
|
||||
|
@ -75,6 +75,10 @@ function init() {
|
|||
\add_filter( 'wp_rest_server_class', function() {
|
||||
return '\Activitypub\Rest\Server';
|
||||
} );
|
||||
|
||||
if ( \WP_DEBUG ) {
|
||||
require_once \dirname( __FILE__ ) . '/includes/debug.php';
|
||||
}
|
||||
}
|
||||
\add_action( 'plugins_loaded', '\Activitypub\init' );
|
||||
|
||||
|
|
|
@ -7,25 +7,36 @@ namespace Activitypub;
|
|||
* @author Matthias Pfefferle
|
||||
*/
|
||||
class Health_Check {
|
||||
|
||||
/**
|
||||
* Initialize health checks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init() {
|
||||
\add_filter( 'site_status_tests', array( '\Activitypub\Health_Check', 'add_tests' ) );
|
||||
}
|
||||
|
||||
public static function add_tests( $tests ) {
|
||||
$tests['direct']['activitypub_test_profile_url'] = array(
|
||||
'label' => \__( 'Profile URL test', 'activitypub' ),
|
||||
'test' => array( '\Activitypub\Health_Check', 'test_profile_url' ),
|
||||
$tests['direct']['activitypub_test_author_url'] = array(
|
||||
'label' => \__( 'Author URL test', 'activitypub' ),
|
||||
'test' => array( '\Activitypub\Health_Check', 'test_author_url' ),
|
||||
);
|
||||
|
||||
//$tests['direct']['activitypub_test_profile_url2'] = array(
|
||||
// 'label' => __( 'Profile URL Test', 'activitypub' ),
|
||||
// 'test' => array( '\Activitypub\Health_Check', 'test_profile_url' ),
|
||||
//);
|
||||
$tests['direct']['activitypub_test_webfinger'] = array(
|
||||
'label' => __( 'WebFinger Test', 'activitypub' ),
|
||||
'test' => array( '\Activitypub\Health_Check', 'test_webfinger' ),
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
public static function test_profile_url() {
|
||||
/**
|
||||
* Author URL tests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function test_author_url() {
|
||||
$result = array(
|
||||
'label' => \__( 'Author URL accessible', 'activitypub' ),
|
||||
'status' => 'good',
|
||||
|
@ -38,45 +49,208 @@ class Health_Check {
|
|||
\__( 'Your author URL is accessible and supports the required "Accept" header.', 'activitypub' )
|
||||
),
|
||||
'actions' => '',
|
||||
'test' => 'test_profile_url',
|
||||
'test' => 'test_author_url',
|
||||
);
|
||||
|
||||
$enum = self::is_profile_url_accessible();
|
||||
$check = self::is_author_url_accessible();
|
||||
|
||||
if ( true !== $enum ) {
|
||||
$result['status'] = 'critical';
|
||||
$result['label'] = \__( 'Profile URL is not accessible', 'activitypub' );
|
||||
$result['description'] = \sprintf(
|
||||
'<p>%s</p>',
|
||||
\__( 'Your author URL is not accessible and/or does not return valid JSON. Please check if the author URL is accessible and does not redirect to another page (often done by SEO plugins).', 'activitypub' )
|
||||
);
|
||||
if ( true === $check ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result['status'] = 'critical';
|
||||
$result['label'] = \__( 'Author URL is not accessible', 'activitypub' );
|
||||
$result['badge']['color'] = 'red';
|
||||
$result['description'] = \sprintf(
|
||||
'<p>%s</p>',
|
||||
$check->get_error_message()
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function is_profile_url_accessible() {
|
||||
/**
|
||||
* WebFinger tests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function test_webfinger() {
|
||||
$result = array(
|
||||
'label' => \__( 'WebFinger endpoint', 'activitypub' ),
|
||||
'status' => 'good',
|
||||
'badge' => array(
|
||||
'label' => \__( 'ActivityPub', 'activitypub' ),
|
||||
'color' => 'green',
|
||||
),
|
||||
'description' => \sprintf(
|
||||
'<p>%s</p>',
|
||||
\__( 'Your WebFinger endpoint is accessible and returns the correct informations.', 'activitypub' )
|
||||
),
|
||||
'actions' => '',
|
||||
'test' => 'test_webfinger',
|
||||
);
|
||||
|
||||
$check = self::is_webfinger_endpoint_accessible();
|
||||
|
||||
if ( true === $check ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result['status'] = 'critical';
|
||||
$result['label'] = \__( 'WebFinger endpoint is not accessible', 'activitypub' );
|
||||
$result['badge']['color'] = 'red';
|
||||
$result['description'] = \sprintf(
|
||||
'<p>%s</p>',
|
||||
$check->get_error_message()
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if `author_posts_url` is accessible and that requerst returns correct JSON
|
||||
*
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public static function is_author_url_accessible() {
|
||||
$user = \wp_get_current_user();
|
||||
$author_url = \get_author_posts_url( $user->ID );
|
||||
$reference_author_url = self::get_author_posts_url( $user->ID, $user->user_nicename );
|
||||
|
||||
// check for "author" in URL
|
||||
if ( $author_url !== $reference_author_url ) {
|
||||
return false;
|
||||
return new \WP_Error(
|
||||
'author_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your author URL <code>%s</code> was replaced, this is often done by plugins.</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$author_url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// try to access author URL
|
||||
$response = \wp_remote_get( $author_url, array( 'headers' => array( 'Accept' => 'application/activity+json' ) ) );
|
||||
$response = \wp_remote_get(
|
||||
$author_url,
|
||||
array(
|
||||
'headers' => array( 'Accept' => 'application/activity+json' ),
|
||||
'redirection' => 0,
|
||||
)
|
||||
);
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
return false;
|
||||
return new \WP_Error(
|
||||
'author_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your author URL <code>%s</code> is not accessible. Please check your WordPress setup or permalink structure. If the setup seems fine, maybe check if a plugin might restrict the access.</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$author_url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response_code = \wp_remote_retrieve_response_code( $response );
|
||||
|
||||
// check for redirects
|
||||
if ( \in_array( $response_code, array( 301, 302, 307, 308 ), true ) ) {
|
||||
return new \WP_Error(
|
||||
'author_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your author URL <code>%s</code> is redirecting to another page, this is often done by SEO plugins like "Yoast SEO".</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$author_url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// check if response is JSON
|
||||
$body = \wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( ! \is_string( $body ) || ! \is_array( \json_decode( $body, true ) ) ) {
|
||||
return false;
|
||||
return new \WP_Error(
|
||||
'author_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your author URL <code>%s</code> does not return valid JSON for <code>application/activity+json</code>. Please check if your hosting supports alternate <code>Accept</code> headers.</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$author_url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if WebFinger endoint is accessible and profile requerst returns correct JSON
|
||||
*
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public static function is_webfinger_endpoint_accessible() {
|
||||
$user = \wp_get_current_user();
|
||||
$webfinger = \Activitypub\get_webfinger_resource( $user->ID );
|
||||
|
||||
$url = \wp_parse_url( \home_url(), \PHP_URL_SCHEME ) . '://' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
|
||||
|
||||
if ( \wp_parse_url( \home_url(), \PHP_URL_PORT ) ) {
|
||||
$url .= ':' . \wp_parse_url( \home_url(), \PHP_URL_PORT );
|
||||
}
|
||||
|
||||
$url = \trailingslashit( $url ) . '.well-known/webfinger';
|
||||
|
||||
$url = \add_query_arg( 'resource', 'acct:' . $webfinger, $url );
|
||||
|
||||
// try to access author URL
|
||||
$response = \wp_remote_get(
|
||||
$url,
|
||||
array(
|
||||
'headers' => array( 'Accept' => 'application/activity+json' ),
|
||||
'redirection' => 0,
|
||||
)
|
||||
);
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
return new \WP_Error(
|
||||
'webfinger_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your WebFinger endpoint <code>%s</code> is not accessible. Please check your WordPress setup or permalink structure.</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response_code = \wp_remote_retrieve_response_code( $response );
|
||||
|
||||
// check if response is JSON
|
||||
$body = \wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( ! \is_string( $body ) || ! \is_array( \json_decode( $body, true ) ) ) {
|
||||
return new \WP_Error(
|
||||
'webfinger_url_not_accessible',
|
||||
\sprintf(
|
||||
// translators: %s: Author URL
|
||||
\__(
|
||||
'<p>Your WebFinger endpoint <code>%s</code> does not return valid JSON for <code>application/jrd+json</code>.</p>',
|
||||
'activitypub'
|
||||
),
|
||||
$url
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
16
includes/debug.php
Normal file
16
includes/debug.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
namespace Activitypub;
|
||||
|
||||
/**
|
||||
* Allow localhost URLs if WP_DEBUG is true.
|
||||
*
|
||||
* @param array $r Array of HTTP request args.
|
||||
* @param string $url The request URL.
|
||||
* @return array $args Array or string of HTTP request arguments.
|
||||
*/
|
||||
function allow_localhost( $r, $url ) {
|
||||
$r['reject_unsafe_urls'] = false;
|
||||
|
||||
return $r;
|
||||
}
|
||||
add_filter( 'http_request_args', '\Activitypub\allow_localhost', 10, 2 );
|
|
@ -20,11 +20,11 @@ function get_context() {
|
|||
'Hashtag' => 'as:Hashtag',
|
||||
'featured' => array(
|
||||
'@id' => 'toot:featured',
|
||||
'@type' => '@id'
|
||||
'@type' => '@id',
|
||||
),
|
||||
'featuredTags' => array(
|
||||
'@id' => 'toot:featuredTags',
|
||||
'@type' => '@id'
|
||||
'@type' => '@id',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -3,8 +3,8 @@ Contributors: pfefferle, mediaformat
|
|||
Donate link: https://notiz.blog/donate/
|
||||
Tags: OStatus, fediverse, activitypub, activitystream
|
||||
Requires at least: 4.7
|
||||
Tested up to: 5.6
|
||||
Stable tag: 0.12.0
|
||||
Tested up to: 5.8
|
||||
Stable tag: 0.13.0
|
||||
Requires PHP: 5.6
|
||||
License: MIT
|
||||
License URI: http://opensource.org/licenses/MIT
|
||||
|
@ -88,6 +88,11 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
|
|||
|
||||
Project maintained on GitHub at [pfefferle/wordpress-activitypub](https://github.com/pfefferle/wordpress-activitypub).
|
||||
|
||||
= 0.13.0 =
|
||||
|
||||
* add Autor URL and WebFinger health checks
|
||||
* fix NodeInfo endpoint
|
||||
|
||||
= 0.12.0 =
|
||||
|
||||
* use "pre_option_require_name_email" filter instead of "check_comment_flood". props [@akirk](https://github.com/akirk)
|
||||
|
|
Loading…
Reference in a new issue