updated plugin ActivityPub version 9.1.0

This commit is contained in:
2026-07-28 15:03:10 +00:00
committed by Gitium
parent bf428f0e45
commit ff806e1811
217 changed files with 6098 additions and 3025 deletions

View File

@ -102,8 +102,8 @@ class Token {
$refresh_token = self::generate_token();
// Calculate expirations.
$access_expires_at = time() + $expires;
$refresh_expires_at = time() + self::REFRESH_EXPIRATION;
$access_expires_at = \time() + $expires;
$refresh_expires_at = \time() + self::REFRESH_EXPIRATION;
// Create token data.
$token_data = array(
@ -113,7 +113,7 @@ class Token {
'scopes' => Scope::validate( $scopes ),
'expires_at' => $access_expires_at,
'refresh_expires_at' => $refresh_expires_at,
'created_at' => time(),
'created_at' => \time(),
'last_used_at' => null,
);
@ -141,7 +141,8 @@ class Token {
self::enforce_token_limit( $user_id );
/*
* Get the actor URI for the 'me' parameter (IndieAuth convention).
* Get the actor URI for the 'me' parameter (IndieAuth convention) and
* `activitypub_actor_id` (SWICG ActivityPub API Basic Profile).
* Fall back to blog actor when user actors are disabled.
*/
$actor = Actors::get_by_id( $user_id );
@ -151,12 +152,13 @@ class Token {
$me = ! \is_wp_error( $actor ) ? $actor->get_id() : null;
return array(
'access_token' => $access_token,
'token_type' => 'Bearer',
'expires_in' => $expires,
'refresh_token' => $refresh_token,
'scope' => Scope::to_string( $token_data['scopes'] ),
'me' => $me,
'access_token' => $access_token,
'token_type' => 'Bearer',
'expires_in' => $expires,
'refresh_token' => $refresh_token,
'scope' => Scope::to_string( $token_data['scopes'] ),
'me' => $me,
'activitypub_actor_id' => $me,
);
}
@ -190,7 +192,7 @@ class Token {
$token_data = \get_user_meta( (int) $user_id, $meta_key, true );
if ( empty( $token_data ) || ! is_array( $token_data ) ) {
if ( empty( $token_data ) || ! \is_array( $token_data ) ) {
return new \WP_Error(
'activitypub_invalid_token',
\__( 'Invalid access token.', 'activitypub' ),
@ -200,7 +202,7 @@ class Token {
// Verify hash matches.
if ( ! isset( $token_data['access_token_hash'] ) ||
! hash_equals( $token_data['access_token_hash'], $token_hash ) ) {
! \hash_equals( $token_data['access_token_hash'], $token_hash ) ) {
return new \WP_Error(
'activitypub_invalid_token',
\__( 'Invalid access token.', 'activitypub' ),
@ -209,7 +211,7 @@ class Token {
}
// Check expiration.
if ( isset( $token_data['expires_at'] ) && $token_data['expires_at'] < time() ) {
if ( isset( $token_data['expires_at'] ) && $token_data['expires_at'] < \time() ) {
return new \WP_Error(
'activitypub_token_expired',
\__( 'Access token has expired.', 'activitypub' ),
@ -219,8 +221,8 @@ class Token {
// Throttle last_used_at writes to avoid a DB write on every request.
$last_used = $token_data['last_used_at'] ?? 0;
if ( empty( $last_used ) || ( time() - $last_used ) > 5 * MINUTE_IN_SECONDS ) {
$token_data['last_used_at'] = time();
if ( empty( $last_used ) || ( \time() - $last_used ) > 5 * MINUTE_IN_SECONDS ) {
$token_data['last_used_at'] = \time();
\update_user_meta( (int) $user_id, $meta_key, $token_data );
}
@ -272,7 +274,7 @@ class Token {
$meta_key = self::META_PREFIX . $access_hash;
$token_data = \get_user_meta( $user_id, $meta_key, true );
if ( empty( $token_data ) || ! is_array( $token_data ) ) {
if ( empty( $token_data ) || ! \is_array( $token_data ) ) {
return new \WP_Error(
'activitypub_invalid_refresh_token',
\__( 'Invalid refresh token.', 'activitypub' ),
@ -282,7 +284,7 @@ class Token {
// Verify refresh token hash matches.
if ( ! isset( $token_data['refresh_token_hash'] ) ||
! hash_equals( $token_data['refresh_token_hash'], $refresh_hash ) ) {
! \hash_equals( $token_data['refresh_token_hash'], $refresh_hash ) ) {
return new \WP_Error(
'activitypub_invalid_refresh_token',
\__( 'Invalid refresh token.', 'activitypub' ),
@ -301,7 +303,7 @@ class Token {
// Check refresh token expiration.
if ( isset( $token_data['refresh_expires_at'] ) &&
$token_data['refresh_expires_at'] < time() ) {
$token_data['refresh_expires_at'] < \time() ) {
// Delete the expired token and index.
\delete_user_meta( $user_id, $meta_key );
\delete_user_meta( $user_id, $refresh_index_key );
@ -353,7 +355,7 @@ class Token {
if ( $user_id ) {
$user_id = (int) $user_id;
$token_data = \get_user_meta( $user_id, $access_meta_key, true );
$client_id = is_array( $token_data ) ? ( $token_data['client_id'] ?? '' ) : '';
$client_id = \is_array( $token_data ) ? ( $token_data['client_id'] ?? '' ) : '';
if ( ! self::caller_owns_token( $user_id, $client_id, $caller_user_id, $caller_client_id ) ) {
return true;
@ -363,7 +365,7 @@ class Token {
\delete_user_meta( $user_id, $access_meta_key );
// Also delete the refresh token index if it exists.
if ( is_array( $token_data ) && isset( $token_data['refresh_token_hash'] ) ) {
if ( \is_array( $token_data ) && isset( $token_data['refresh_token_hash'] ) ) {
$refresh_index_key = self::REFRESH_INDEX_PREFIX . $token_data['refresh_token_hash'];
\delete_user_meta( $user_id, $refresh_index_key );
}
@ -388,7 +390,7 @@ class Token {
if ( $access_hash ) {
$token_data = \get_user_meta( $user_id, self::META_PREFIX . $access_hash, true );
$client_id = is_array( $token_data ) ? ( $token_data['client_id'] ?? '' ) : '';
$client_id = \is_array( $token_data ) ? ( $token_data['client_id'] ?? '' ) : '';
}
if ( ! self::caller_owns_token( $user_id, $client_id, $caller_user_id, $caller_client_id ) ) {
@ -482,22 +484,22 @@ class Token {
foreach ( $all_meta as $meta_key => $meta_values ) {
// Delete token entries and collect client IDs.
if ( 0 === strpos( $meta_key, self::META_PREFIX ) ) {
if ( 0 === \strpos( $meta_key, self::META_PREFIX ) ) {
$token_data = \maybe_unserialize( $meta_values[0] );
if ( is_array( $token_data ) && ! empty( $token_data['client_id'] ) ) {
if ( \is_array( $token_data ) && ! empty( $token_data['client_id'] ) ) {
$client_ids[] = $token_data['client_id'];
}
\delete_user_meta( $user_id, $meta_key );
++$count;
}
// Delete refresh token indices.
if ( 0 === strpos( $meta_key, self::REFRESH_INDEX_PREFIX ) ) {
if ( 0 === \strpos( $meta_key, self::REFRESH_INDEX_PREFIX ) ) {
\delete_user_meta( $user_id, $meta_key );
}
}
// Remove user from all client tracking.
foreach ( array_unique( $client_ids ) as $client_id ) {
foreach ( \array_unique( $client_ids ) as $client_id ) {
self::untrack_user( $user_id, $client_id );
}
@ -536,13 +538,13 @@ class Token {
$all_meta = \get_user_meta( $user_id );
foreach ( $all_meta as $meta_key => $meta_values ) {
if ( 0 !== strpos( $meta_key, self::META_PREFIX ) ) {
if ( 0 !== \strpos( $meta_key, self::META_PREFIX ) ) {
continue;
}
$token_data = \maybe_unserialize( $meta_values[0] );
if ( ! is_array( $token_data ) ) {
if ( ! \is_array( $token_data ) ) {
continue;
}
@ -575,13 +577,13 @@ class Token {
$tokens = array();
foreach ( $all_meta as $meta_key => $meta_values ) {
if ( 0 !== strpos( $meta_key, self::META_PREFIX ) ) {
if ( 0 !== \strpos( $meta_key, self::META_PREFIX ) ) {
continue;
}
$token_data = \maybe_unserialize( $meta_values[0] );
if ( is_array( $token_data ) ) {
if ( \is_array( $token_data ) ) {
// Don't expose hashes.
unset( $token_data['access_token_hash'], $token_data['refresh_token_hash'] );
$token_data['meta_key'] = $meta_key; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Not a DB query, just array key.
@ -645,7 +647,7 @@ class Token {
* @return bool True if expired.
*/
public function is_expired() {
return $this->get_expires_at() < time();
return $this->get_expires_at() < \time();
}
/**
@ -673,7 +675,7 @@ class Token {
* @return string The random token as a hex string.
*/
public static function generate_token( $length = 32 ) {
return bin2hex( random_bytes( $length ) );
return \bin2hex( \random_bytes( $length ) );
}
/**
@ -683,7 +685,7 @@ class Token {
* @return string The SHA-256 hash.
*/
public static function hash_token( $token ) {
return hash( 'sha256', $token );
return \hash( 'sha256', $token );
}
/**
@ -705,7 +707,7 @@ class Token {
$post_id = $client->get_post_id();
$existing = \get_post_meta( $post_id, self::USER_META_KEY, false );
if ( ! in_array( $user_id, array_map( 'intval', $existing ), true ) ) {
if ( ! \in_array( $user_id, \array_map( 'intval', $existing ), true ) ) {
\add_post_meta( $post_id, self::USER_META_KEY, $user_id );
}
}
@ -722,30 +724,30 @@ class Token {
$tokens = array();
foreach ( $all_meta as $meta_key => $meta_values ) {
if ( 0 !== strpos( $meta_key, self::META_PREFIX ) ) {
if ( 0 !== \strpos( $meta_key, self::META_PREFIX ) ) {
continue;
}
$token_data = \maybe_unserialize( $meta_values[0] );
if ( is_array( $token_data ) ) {
if ( \is_array( $token_data ) ) {
$tokens[ $meta_key ] = $token_data;
}
}
if ( count( $tokens ) <= self::MAX_TOKENS_PER_USER ) {
if ( \count( $tokens ) <= self::MAX_TOKENS_PER_USER ) {
return;
}
// Sort by created_at ascending (oldest first).
uasort(
\uasort(
$tokens,
function ( $a, $b ) {
return ( $a['created_at'] ?? 0 ) - ( $b['created_at'] ?? 0 );
}
);
$to_remove = count( $tokens ) - self::MAX_TOKENS_PER_USER;
$to_remove = \count( $tokens ) - self::MAX_TOKENS_PER_USER;
foreach ( $tokens as $meta_key => $token_data ) {
if ( $to_remove <= 0 ) {
@ -809,7 +811,7 @@ class Token {
$user_ids = \get_post_meta( $client->get_post_id(), self::USER_META_KEY, false );
return array_map( 'intval', $user_ids );
return \array_map( 'intval', $user_ids );
}
/**
@ -831,7 +833,7 @@ class Token {
)
);
return array_map( 'intval', $user_ids );
return \array_map( 'intval', $user_ids );
}
/**
@ -850,13 +852,13 @@ class Token {
$client_ids = array();
foreach ( $all_meta as $meta_key => $meta_values ) {
if ( 0 !== strpos( $meta_key, self::META_PREFIX ) ) {
if ( 0 !== \strpos( $meta_key, self::META_PREFIX ) ) {
continue;
}
$token_data = \maybe_unserialize( $meta_values[0] );
if ( ! is_array( $token_data ) ) {
if ( ! \is_array( $token_data ) ) {
\delete_user_meta( $user_id, $meta_key );
++$count;
continue;
@ -864,9 +866,9 @@ class Token {
// Check if both access and refresh tokens are expired.
$access_expired = isset( $token_data['expires_at'] ) &&
$token_data['expires_at'] < time() - DAY_IN_SECONDS;
$token_data['expires_at'] < \time() - DAY_IN_SECONDS;
$refresh_expired = isset( $token_data['refresh_expires_at'] ) &&
$token_data['refresh_expires_at'] < time();
$token_data['refresh_expires_at'] < \time();
if ( $access_expired && $refresh_expired ) {
\delete_user_meta( $user_id, $meta_key );
@ -883,7 +885,7 @@ class Token {
}
// Untrack user from clients where all tokens were removed.
foreach ( array_unique( $client_ids ) as $client_id ) {
foreach ( \array_unique( $client_ids ) as $client_id ) {
self::maybe_untrack_user( $user_id, $client_id );
}
}
@ -919,15 +921,16 @@ class Token {
$me = ! \is_wp_error( $actor ) ? $actor->get_id() : null;
return array(
'active' => true,
'scope' => Scope::to_string( $validated->get_scopes() ),
'client_id' => $validated->get_client_id(),
'username' => $user ? $user->user_login : null,
'token_type' => 'Bearer',
'exp' => $validated->get_expires_at(),
'iat' => $validated->get_created_at(),
'sub' => (string) $user_id,
'me' => $me,
'active' => true,
'scope' => Scope::to_string( $validated->get_scopes() ),
'client_id' => $validated->get_client_id(),
'username' => $user ? $user->user_login : null,
'token_type' => 'Bearer',
'exp' => $validated->get_expires_at(),
'iat' => $validated->get_created_at(),
'sub' => (string) $user_id,
'me' => $me,
'activitypub_actor_id' => $me,
);
}
}