Improve update_activitypub_profiles.php daemon
Add sanity case to ensure public key method of rsa class
This commit is contained in:
parent
b2f6f9f08e
commit
6fbf37b7fe
@ -413,4 +413,57 @@ class Activitypub_profile extends Managed_DataObject
|
||||
// TRANS: Exception. %s is a webfinger address.
|
||||
throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'), $addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update remote user profile in local instance
|
||||
* Depends on do_update
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param array $res remote response
|
||||
* @return Profile remote Profile object
|
||||
*/
|
||||
public static function update_profile($aprofile, $res)
|
||||
{
|
||||
// ActivityPub Profile
|
||||
$aprofile->uri = $res['id'];
|
||||
$aprofile->nickname = $res['preferredUsername'];
|
||||
$aprofile->fullname = isset($res['name']) ? $res['name'] : null;
|
||||
$aprofile->bio = isset($res['summary']) ? substr(strip_tags($res['summary']), 0, 1000) : null;
|
||||
$aprofile->inboxuri = $res['inbox'];
|
||||
$aprofile->sharedInboxuri = isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : $res['inbox'];
|
||||
|
||||
$profile = $aprofile->local_profile();
|
||||
|
||||
$profile->modified = $aprofile->modified = common_sql_now();
|
||||
|
||||
$fields = [
|
||||
'uri' => 'profileurl',
|
||||
'nickname' => 'nickname',
|
||||
'fullname' => 'fullname',
|
||||
'bio' => 'bio'
|
||||
];
|
||||
|
||||
foreach ($fields as $af => $pf) {
|
||||
$profile->$pf = $aprofile->$af;
|
||||
}
|
||||
|
||||
// Profile
|
||||
$profile->update();
|
||||
$aprofile->update();
|
||||
|
||||
// Public Key
|
||||
Activitypub_rsa::update_public_key($profile, $res['publicKey']['publicKeyPem']);
|
||||
|
||||
// Avatar
|
||||
if (isset($res['icon']['url'])) {
|
||||
try {
|
||||
Activitypub_explorer::update_avatar($profile, $res['icon']['url']);
|
||||
} catch (Exception $e) {
|
||||
// Let the exception go, it isn't a serious issue
|
||||
common_debug('An error ocurred while grabbing remote avatar'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $profile;
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
return $apRSA->private_key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Guarantees a Public Key for a given profile.
|
||||
*
|
||||
@ -104,7 +103,8 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
} else {
|
||||
// This should never happen, but try to recover!
|
||||
if ($fetch) {
|
||||
// TODO: Call profile updater
|
||||
$res = Activitypub_explorer::get_remote_user_activity(ActivityPubPlugin::actor_uri($profile));
|
||||
Activitypub_rsa::update_public_key($profile, $res['publicKey']['publicKeyPem']);
|
||||
return ensure_public_key($profile, false);
|
||||
} else {
|
||||
throw new ServerException('Activitypub_rsa: Failed to find keys for given profile. That should have not happened!');
|
||||
@ -156,4 +156,23 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
$public_key = $pubKey["key"];
|
||||
unset($pubKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update public key.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile
|
||||
* @param string $public_key
|
||||
*/
|
||||
public static function update_public_key($profile, $public_key)
|
||||
{
|
||||
// Public Key
|
||||
$apRSA = new Activitypub_rsa();
|
||||
$apRSA->profile_id = $profile->getID();
|
||||
$apRSA->public_key = $public_key;
|
||||
$apRSA->modified = common_sql_now();
|
||||
if(!$apRSA->update()) {
|
||||
$apRSA->insert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
|
||||
|
||||
$shortoptions = 'u:af';
|
||||
$longoptions = ['uri=', 'all', 'force'];
|
||||
|
||||
$helptext = <<<END_OF_HELP
|
||||
update_activitypub_profiles.php [options]
|
||||
Refetch / update ActivityPub RSA keys, profile info and avatars. Useful if you
|
||||
do something like accidentally delete your avatars directory when
|
||||
you have no backup.
|
||||
|
||||
END_OF_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
||||
$quiet = have_option('q', 'quiet');
|
||||
|
||||
if (!$quiet) {
|
||||
echo "ActivityPub Profiles updater will now start!\n";
|
||||
echo "Summoning Diogo Cordeiro, Richard Stallman and Chuck Norris to help us with this task!\n";
|
||||
}
|
||||
|
||||
$user = new Activitypub_profile();
|
||||
$cnt = $user->find();
|
||||
if (!empty($cnt)) {
|
||||
if (!$quiet) {
|
||||
echo "Found {$cnt} ActivityPub profiles:\n";
|
||||
}
|
||||
} else {
|
||||
if (have_option('u', 'uri')) {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find an existing ActivityPub profile with that URI.\n";
|
||||
}
|
||||
} else {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find any existing ActivityPub profiles.\n";
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
while ($user->fetch()) {
|
||||
try {
|
||||
$res = grab_remote_user($user->uri);
|
||||
} catch (Exception $e) {
|
||||
// let it go
|
||||
}
|
||||
if (!$quiet) {
|
||||
echo "Updated ".update_profile($user, $res)->getBestName()."\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Profile and ActivityPub Profile objects
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @access public
|
||||
*/
|
||||
function do_update($aprofile)
|
||||
{
|
||||
$profile = $aprofile->local_profile();
|
||||
|
||||
$profile->modified = $aprofile->modified = common_sql_now();
|
||||
|
||||
$fields = [
|
||||
'uri' => 'profileurl',
|
||||
'nickname' => 'nickname',
|
||||
'fullname' => 'fullname',
|
||||
'bio' => 'bio'
|
||||
];
|
||||
|
||||
foreach ($fields as $af => $pf) {
|
||||
$profile->$pf = $aprofile->$af;
|
||||
}
|
||||
|
||||
$profile->update();
|
||||
$aprofile->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save remote user profile in local instance
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param array $res remote response
|
||||
* @return Profile remote Profile object
|
||||
*/
|
||||
function update_profile($aprofile, $res)
|
||||
{
|
||||
// ActivityPub Profile
|
||||
$aprofile->uri = $res['id'];
|
||||
$aprofile->nickname = $res['preferredUsername'];
|
||||
$aprofile->fullname = isset($res['name']) ? $res['name'] : null;
|
||||
$aprofile->bio = isset($res['summary']) ? substr(strip_tags($res['summary']), 0, 1000) : null;
|
||||
$aprofile->inboxuri = $res['inbox'];
|
||||
$aprofile->sharedInboxuri = isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : $res['inbox'];
|
||||
|
||||
do_update($aprofile);
|
||||
$profile = $aprofile->local_profile();
|
||||
|
||||
// Public Key
|
||||
$apRSA = new Activitypub_rsa();
|
||||
$apRSA->profile_id = $profile->getID();
|
||||
$apRSA->public_key = $res['publicKey']['publicKeyPem'];
|
||||
$apRSA->modified = common_sql_now();
|
||||
if(!$apRSA->update())
|
||||
$apRSA->insert();
|
||||
|
||||
// Avatar
|
||||
if (isset($res['icon']['url'])) {
|
||||
try {
|
||||
Activitypub_explorer::update_avatar($profile, $res['icon']['url']);
|
||||
} catch (Exception $e) {
|
||||
// Let the exception go, it isn't a serious issue
|
||||
common_debug('An error ocurred while grabbing remote avatar'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remote user(s) profile(s) from its URL
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param string $url User's url
|
||||
* @return boolean success state
|
||||
*/
|
||||
function grab_remote_user($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = [];
|
||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||
$response = $client->get($url, $headers);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
if (Activitypub_explorer::validate_remote_response($res)) {
|
||||
common_debug('ActivityPub Explorer: Found a valid remote actor for '.$url);
|
||||
return $res;
|
||||
}
|
||||
throw new Exception('Failed to grab.');
|
||||
}
|
104
daemons/update_activitypub_profiles.php
Executable file
104
daemons/update_activitypub_profiles.php
Executable file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
|
||||
|
||||
$shortoptions = 'u:af';
|
||||
$longoptions = ['uri=', 'all', 'force'];
|
||||
|
||||
$helptext = <<<END_OF_HELP
|
||||
update_activitypub_profiles.php [options]
|
||||
Refetch / update ActivityPub RSA keys, profile info and avatars. Useful if you
|
||||
do something like accidentally delete your avatars directory when
|
||||
you have no backup.
|
||||
|
||||
-u --uri ActivityPub profile URI to update
|
||||
-a --all update all
|
||||
|
||||
END_OF_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
||||
$quiet = have_option('q', 'quiet');
|
||||
|
||||
if (!$quiet) {
|
||||
echo "ActivityPub Profiles updater will now start!\n";
|
||||
echo "Summoning Diogo Cordeiro, Richard Stallman and Chuck Norris to help us with this task!\n";
|
||||
}
|
||||
|
||||
if (have_option('u', 'uri')) {
|
||||
$uri = get_option_value('u', 'uri');
|
||||
$discovery = new Activitypub_explorer();
|
||||
$discovery = $discovery->lookup($uri);
|
||||
if (empty($discovery)) {
|
||||
echo "Bad URI\n";
|
||||
exit(1);
|
||||
}
|
||||
$user = $discovery->lookup($uri)[0];
|
||||
try {
|
||||
$res = Activitypub_explorer::get_remote_user_activity($uri);
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage()."\n";
|
||||
exit(1);
|
||||
}
|
||||
if (!$quiet) {
|
||||
echo "Updated ".Activitypub_profile::update_profile($user, $res)->getBestName()."\n";
|
||||
}
|
||||
} else if (!have_option('a', 'all')) {
|
||||
show_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$user = new Activitypub_profile();
|
||||
$cnt = $user->find();
|
||||
if (!empty($cnt)) {
|
||||
if (!$quiet) {
|
||||
echo "Found {$cnt} ActivityPub profiles:\n";
|
||||
}
|
||||
} else {
|
||||
if (have_option('u', 'uri')) {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find an existing ActivityPub profile with that URI.\n";
|
||||
}
|
||||
} else {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find any existing ActivityPub profiles.\n";
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
while ($user->fetch()) {
|
||||
try {
|
||||
$res = Activitypub_explorer::get_remote_user_activity($user->uri);
|
||||
if (!$quiet) {
|
||||
echo "Updated ".Activitypub_profile::update_profile($user, $res)->getBestName()."\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// let it go
|
||||
}
|
||||
}
|
@ -438,4 +438,27 @@ class Activitypub_explorer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remote user array from its URL (this function is only used for
|
||||
* profile updating and shall not be used for anything else)
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param string $url User's url
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function get_remote_user_activity($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = [];
|
||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||
$response = $client->get($url, $headers);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
if (Activitypub_explorer::validate_remote_response($res)) {
|
||||
common_debug('ActivityPub Explorer: Found a valid remote actor for '.$url);
|
||||
return $res;
|
||||
}
|
||||
throw new Exception('ActivityPub Explorer: Failed to get activity.');
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user