forked from GNUsocial/gnu-social
[ActivityPub] Autofix profile URIs through alias discovering
Activitypub_profile: - Add updateUri method explorer: - Add grab_aliases method - Update grab_local_user's online course to grab and test aliases
This commit is contained in:
parent
2183875e9e
commit
c6543e1f95
@ -495,6 +495,21 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
return $profile;
|
return $profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update remote user profile URI in local instance
|
||||||
|
*
|
||||||
|
* @param string $uri
|
||||||
|
* @return void
|
||||||
|
* @throws Exception (if the update fails)
|
||||||
|
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||||
|
*/
|
||||||
|
public function updateUri(string $uri)
|
||||||
|
{
|
||||||
|
$orig = clone($this);
|
||||||
|
$this->uri = $uri;
|
||||||
|
$this->updateWithKeys($orig);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for the number of subscribers of a
|
* Getter for the number of subscribers of a
|
||||||
* given local profile
|
* given local profile
|
||||||
|
@ -39,7 +39,6 @@ defined('GNUSOCIAL') || die();
|
|||||||
class Activitypub_explorer
|
class Activitypub_explorer
|
||||||
{
|
{
|
||||||
private $discovered_actor_profiles = [];
|
private $discovered_actor_profiles = [];
|
||||||
private $temp_res; // global variable to hold a temporary http response
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut function to get a single profile from its URL.
|
* Shortcut function to get a single profile from its URL.
|
||||||
@ -118,26 +117,26 @@ class Activitypub_explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This ensures that we are using a valid ActivityPub URI
|
* Fetch all the aliases for some actor
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url actor's url
|
||||||
* @return bool success state (related to the response)
|
* @return array aliases
|
||||||
* @throws Exception (If the HTTP request fails)
|
* @throws Exception (If the Discovery's HTTP requests fail)
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||||
*/
|
*/
|
||||||
private function ensure_proper_remote_uri($url)
|
private function grab_aliases(string $url): array
|
||||||
{
|
{
|
||||||
$client = new HTTPClient();
|
$disco = new Discovery();
|
||||||
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
$xrd = $disco->lookup($url);
|
||||||
$res = json_decode($response->getBody(), true);
|
|
||||||
if (self::validate_remote_response($res)) {
|
$all_ids = array_merge([$xrd->subject], $xrd->aliases);
|
||||||
$this->temp_res = $res;
|
|
||||||
return true;
|
if (!in_array($url, $all_ids)) {
|
||||||
} else {
|
common_debug('grab_aliases: The URI we got was not listed itself when doing discovery on it');
|
||||||
common_debug('ActivityPub Explorer: Invalid potential remote actor while ensuring URI: ' . $url . '. He returned the following: ' . json_encode($res, JSON_UNESCAPED_SLASHES));
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $all_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,44 +154,65 @@ class Activitypub_explorer
|
|||||||
{
|
{
|
||||||
if ($online) {
|
if ($online) {
|
||||||
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' with online resources.');
|
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' with online resources.');
|
||||||
|
$all_ids = $this->grab_aliases($uri);
|
||||||
} else {
|
} else {
|
||||||
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' offline.');
|
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' offline.');
|
||||||
}
|
$all_ids = [$uri];
|
||||||
// Ensure proper remote URI
|
|
||||||
// If an exception occurs here it's better to just leave everything
|
|
||||||
// break than to continue processing
|
|
||||||
if ($online && $this->ensure_proper_remote_uri($uri)) {
|
|
||||||
$uri = $this->temp_res["id"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try standard ActivityPub route
|
if (empty($all_ids)) {
|
||||||
// Is this a known filthy little mudblood?
|
common_debug('AcvitityPub Explorer: Unable to find a local profile for ' . $uri);
|
||||||
$aprofile = self::get_aprofile_by_url($uri);
|
return false;
|
||||||
if ($aprofile instanceof Activitypub_profile) {
|
}
|
||||||
// Assert: This AProfile has a Profile, no try catch.
|
|
||||||
$profile = $aprofile->local_profile();
|
foreach ($all_ids as $alias) {
|
||||||
common_debug('ActivityPub Explorer: Found a local Aprofile for ' . $uri);
|
// Try standard ActivityPub route
|
||||||
// We found something!
|
// Is this a known filthy little mudblood?
|
||||||
$this->discovered_actor_profiles[] = $profile;
|
$aprofile = self::get_aprofile_by_url($alias);
|
||||||
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
return true;
|
common_debug('ActivityPub Explorer: Found a local Aprofile for ' . $alias);
|
||||||
} else {
|
|
||||||
common_debug('ActivityPub Explorer: Unable to find a local Aprofile for ' . $uri . ' - looking for a Profile instead.');
|
// double check to confirm this alias as a legitimate one
|
||||||
// Well, maybe it is a pure blood?
|
if ($online) {
|
||||||
// Iff, we are in the same instance:
|
common_debug('ActivityPub Explorer: Double-checking ' . $alias . ' to confirm it as a legitimate alias');
|
||||||
$ACTIVITYPUB_BASE_ACTOR_URI = common_local_url('userbyid', ['id' => null], null, null, false, true); // @FIXME: Could this be too hardcoded?
|
|
||||||
$ACTIVITYPUB_BASE_ACTOR_URI_length = strlen($ACTIVITYPUB_BASE_ACTOR_URI);
|
$disco = new Discovery();
|
||||||
if (substr($uri, 0, $ACTIVITYPUB_BASE_ACTOR_URI_length) === $ACTIVITYPUB_BASE_ACTOR_URI) {
|
$xrd = $disco->lookup($aprofile->getUri());
|
||||||
try {
|
$doublecheck_aliases = array_merge(array($xrd->subject), $xrd->aliases);
|
||||||
$profile = Profile::getByID((int)substr($uri, $ACTIVITYPUB_BASE_ACTOR_URI_length));
|
|
||||||
common_debug('ActivityPub Explorer: Found a Profile for ' . $uri);
|
if (in_array($uri, $doublecheck_aliases)) {
|
||||||
// We found something!
|
// the original URI is present, we're sure now!
|
||||||
$this->discovered_actor_profiles[] = $profile;
|
// update aprofile's URI and proceed
|
||||||
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
common_debug('ActivityPub Explorer: ' . $alias . ' is a legitimate alias');
|
||||||
return true;
|
$aprofile->updateUri($uri);
|
||||||
} catch (Exception $e) {
|
} else {
|
||||||
// Let the exception go on its merry way.
|
common_debug('ActivityPub Explorer: ' . $alias . ' is not an alias we can trust');
|
||||||
common_debug('ActivityPub Explorer: Unable to find a Profile for ' . $uri);
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert: This AProfile has a Profile, no try catch.
|
||||||
|
$profile = $aprofile->local_profile();
|
||||||
|
// We found something!
|
||||||
|
$this->discovered_actor_profiles[] = $profile;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
common_debug('ActivityPub Explorer: Unable to find a local Aprofile for ' . $alias . ' - looking for a Profile instead.');
|
||||||
|
// Well, maybe it is a pure blood?
|
||||||
|
// Iff, we are in the same instance:
|
||||||
|
$ACTIVITYPUB_BASE_ACTOR_URI = common_local_url('userbyid', ['id' => null], null, null, false, true); // @FIXME: Could this be too hardcoded?
|
||||||
|
$ACTIVITYPUB_BASE_ACTOR_URI_length = strlen($ACTIVITYPUB_BASE_ACTOR_URI);
|
||||||
|
if (substr($alias, 0, $ACTIVITYPUB_BASE_ACTOR_URI_length) === $ACTIVITYPUB_BASE_ACTOR_URI) {
|
||||||
|
try {
|
||||||
|
$profile = Profile::getByID((int)substr($alias, $ACTIVITYPUB_BASE_ACTOR_URI_length));
|
||||||
|
common_debug('ActivityPub Explorer: Found a Profile for ' . $alias);
|
||||||
|
// We found something!
|
||||||
|
$this->discovered_actor_profiles[] = $profile;
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Let the exception go on its merry way.
|
||||||
|
common_debug('ActivityPub Explorer: Unable to find a Profile for ' . $alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,14 +241,10 @@ class Activitypub_explorer
|
|||||||
private function grab_remote_user($url)
|
private function grab_remote_user($url)
|
||||||
{
|
{
|
||||||
common_debug('ActivityPub Explorer: Trying to grab a remote actor for ' . $url);
|
common_debug('ActivityPub Explorer: Trying to grab a remote actor for ' . $url);
|
||||||
if (!isset($this->temp_res)) {
|
$client = new HTTPClient();
|
||||||
$client = new HTTPClient();
|
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
||||||
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
$res = json_decode($response->getBody(), true);
|
||||||
$res = json_decode($response->getBody(), true);
|
|
||||||
} else {
|
|
||||||
$res = $this->temp_res;
|
|
||||||
unset($this->temp_res);
|
|
||||||
}
|
|
||||||
if (isset($res['type']) && $res['type'] === 'OrderedCollection' && isset($res['first'])) { // It's a potential collection of actors!!!
|
if (isset($res['type']) && $res['type'] === 'OrderedCollection' && isset($res['first'])) { // It's a potential collection of actors!!!
|
||||||
common_debug('ActivityPub Explorer: Found a collection of actors for ' . $url);
|
common_debug('ActivityPub Explorer: Found a collection of actors for ' . $url);
|
||||||
$this->travel_collection($res['first']);
|
$this->travel_collection($res['first']);
|
||||||
|
Loading…
Reference in New Issue
Block a user