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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* given local profile
|
||||
|
@ -39,7 +39,6 @@ defined('GNUSOCIAL') || die();
|
||||
class Activitypub_explorer
|
||||
{
|
||||
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.
|
||||
@ -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
|
||||
* @return bool success state (related to the response)
|
||||
* @throws Exception (If the HTTP request fails)
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param string $url actor's url
|
||||
* @return array aliases
|
||||
* @throws Exception (If the Discovery's HTTP requests fail)
|
||||
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||
*/
|
||||
private function ensure_proper_remote_uri($url)
|
||||
private function grab_aliases(string $url): array
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
if (self::validate_remote_response($res)) {
|
||||
$this->temp_res = $res;
|
||||
return true;
|
||||
} else {
|
||||
common_debug('ActivityPub Explorer: Invalid potential remote actor while ensuring URI: ' . $url . '. He returned the following: ' . json_encode($res, JSON_UNESCAPED_SLASHES));
|
||||
$disco = new Discovery();
|
||||
$xrd = $disco->lookup($url);
|
||||
|
||||
$all_ids = array_merge([$xrd->subject], $xrd->aliases);
|
||||
|
||||
if (!in_array($url, $all_ids)) {
|
||||
common_debug('grab_aliases: The URI we got was not listed itself when doing discovery on it');
|
||||
return [];
|
||||
}
|
||||
|
||||
return false;
|
||||
return $all_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,44 +154,65 @@ class Activitypub_explorer
|
||||
{
|
||||
if ($online) {
|
||||
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' with online resources.');
|
||||
$all_ids = $this->grab_aliases($uri);
|
||||
} else {
|
||||
common_debug('ActivityPub Explorer: Searching locally for ' . $uri . ' offline.');
|
||||
}
|
||||
// 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"];
|
||||
$all_ids = [$uri];
|
||||
}
|
||||
|
||||
// Try standard ActivityPub route
|
||||
// Is this a known filthy little mudblood?
|
||||
$aprofile = self::get_aprofile_by_url($uri);
|
||||
if ($aprofile instanceof Activitypub_profile) {
|
||||
// Assert: This AProfile has a Profile, no try catch.
|
||||
$profile = $aprofile->local_profile();
|
||||
common_debug('ActivityPub Explorer: Found a local Aprofile for ' . $uri);
|
||||
// We found something!
|
||||
$this->discovered_actor_profiles[] = $profile;
|
||||
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
||||
return true;
|
||||
} else {
|
||||
common_debug('ActivityPub Explorer: Unable to find a local Aprofile for ' . $uri . ' - 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($uri, 0, $ACTIVITYPUB_BASE_ACTOR_URI_length) === $ACTIVITYPUB_BASE_ACTOR_URI) {
|
||||
try {
|
||||
$profile = Profile::getByID((int)substr($uri, $ACTIVITYPUB_BASE_ACTOR_URI_length));
|
||||
common_debug('ActivityPub Explorer: Found a Profile for ' . $uri);
|
||||
// We found something!
|
||||
$this->discovered_actor_profiles[] = $profile;
|
||||
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Let the exception go on its merry way.
|
||||
common_debug('ActivityPub Explorer: Unable to find a Profile for ' . $uri);
|
||||
if (empty($all_ids)) {
|
||||
common_debug('AcvitityPub Explorer: Unable to find a local profile for ' . $uri);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($all_ids as $alias) {
|
||||
// Try standard ActivityPub route
|
||||
// Is this a known filthy little mudblood?
|
||||
$aprofile = self::get_aprofile_by_url($alias);
|
||||
if ($aprofile instanceof Activitypub_profile) {
|
||||
common_debug('ActivityPub Explorer: Found a local Aprofile for ' . $alias);
|
||||
|
||||
// double check to confirm this alias as a legitimate one
|
||||
if ($online) {
|
||||
common_debug('ActivityPub Explorer: Double-checking ' . $alias . ' to confirm it as a legitimate alias');
|
||||
|
||||
$disco = new Discovery();
|
||||
$xrd = $disco->lookup($aprofile->getUri());
|
||||
$doublecheck_aliases = array_merge(array($xrd->subject), $xrd->aliases);
|
||||
|
||||
if (in_array($uri, $doublecheck_aliases)) {
|
||||
// the original URI is present, we're sure now!
|
||||
// update aprofile's URI and proceed
|
||||
common_debug('ActivityPub Explorer: ' . $alias . ' is a legitimate alias');
|
||||
$aprofile->updateUri($uri);
|
||||
} else {
|
||||
common_debug('ActivityPub Explorer: ' . $alias . ' is not an alias we can trust');
|
||||
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)
|
||||
{
|
||||
common_debug('ActivityPub Explorer: Trying to grab a remote actor for ' . $url);
|
||||
if (!isset($this->temp_res)) {
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
} else {
|
||||
$res = $this->temp_res;
|
||||
unset($this->temp_res);
|
||||
}
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($url, ACTIVITYPUB_HTTP_CLIENT_HEADERS);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
|
||||
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);
|
||||
$this->travel_collection($res['first']);
|
||||
|
Loading…
Reference in New Issue
Block a user