[OStatus] Port remote-follow to the RemoteFollow plugin

OStatusPlugin:
- Stop adding the remote-follow button
- Subscribe to required RemoteFollow plugin events
- Drop main/ostatussub route and update urls to the main/RemoteFollowSub route
- Bump plugin minor version number

actions/ostatusgroup,
actions/ostatuspeopletag:
- Update urls to the main/RemoteFollowSub route

lib/util:
- Port required functions from OStatusSubAction and adapt to be used with the new events
This commit is contained in:
tenma 2019-08-25 03:14:50 +01:00 committed by Diogo Peralta Cordeiro
parent 32ae48358d
commit 66c5d17469
5 changed files with 123 additions and 52 deletions

View File

@ -28,9 +28,11 @@
if (!defined('GNUSOCIAL')) { exit(1); } if (!defined('GNUSOCIAL')) { exit(1); }
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'util.php';
class OStatusPlugin extends Plugin class OStatusPlugin extends Plugin
{ {
const PLUGIN_VERSION = '2.0.3'; const PLUGIN_VERSION = '2.1.0';
/** /**
* Hook for RouterInitialized event. * Hook for RouterInitialized event.
@ -46,9 +48,6 @@ class OStatusPlugin extends Plugin
$m->connect('main/ostatustag?nickname=:nickname', $m->connect('main/ostatustag?nickname=:nickname',
['action' => 'ostatustag'], ['action' => 'ostatustag'],
['nickname' => '[A-Za-z0-9_-]+']); ['nickname' => '[A-Za-z0-9_-]+']);
$m->connect('main/ostatus/nickname/:nickname',
['action' => 'ostatusinit'],
['nickname' => '[A-Za-z0-9_-]+']);
$m->connect('main/ostatus/group/:group', $m->connect('main/ostatus/group/:group',
['action' => 'ostatusinit'], ['action' => 'ostatusinit'],
['group' => '[A-Za-z0-9_-]+']); ['group' => '[A-Za-z0-9_-]+']);
@ -60,8 +59,6 @@ class OStatusPlugin extends Plugin
['action' => 'ostatusinit']); ['action' => 'ostatusinit']);
// Remote subscription actions // Remote subscription actions
$m->connect('main/ostatussub',
['action' => 'ostatussub']);
$m->connect('main/ostatusgroup', $m->connect('main/ostatusgroup',
['action' => 'ostatusgroup']); ['action' => 'ostatusgroup']);
$m->connect('main/ostatuspeopletag', $m->connect('main/ostatuspeopletag',
@ -176,12 +173,16 @@ class OStatusPlugin extends Plugin
} }
/** /**
* Add in an OStatus subscribe button * Add in an OStatus list button
*
* @param HTMLOutputter $output
* @param Profile $profile
* @return bool hook return value
*/ */
function onStartProfileRemoteSubscribe($output, $profile) function onStartProfileRemoteSubscribe(HTMLOutputter $output, Profile $profile): bool
{ {
$this->onStartProfileListItemActionElements($output, $profile); $this->onStartProfileListItemActionElements($output);
return false; return true;
} }
function onStartGroupSubscribe($widget, $group) function onStartGroupSubscribe($widget, $group)
@ -547,7 +548,7 @@ class OStatusPlugin extends Plugin
function onEndProfileSettingsActions($out) { function onEndProfileSettingsActions($out) {
$siteName = common_config('site', 'name'); $siteName = common_config('site', 'name');
$js = 'navigator.registerContentHandler("application/vnd.mozilla.maybe.feed", "'.addslashes(common_local_url('ostatussub', null, array('profile' => '%s'))).'", "'.addslashes($siteName).'")'; $js = 'navigator.registerContentHandler("application/vnd.mozilla.maybe.feed", "'.addslashes(common_local_url('RemoteFollowSub', null, array('profile' => '%s'))).'", "'.addslashes($siteName).'")';
$out->elementStart('li'); $out->elementStart('li');
$out->element('a', $out->element('a',
array('href' => 'javascript:'.$js), array('href' => 'javascript:'.$js),
@ -1169,21 +1170,7 @@ class OStatusPlugin extends Plugin
} }
} }
function onStartShowSubscriptionsContent($action)
{
$this->showEntityRemoteSubscribe($action);
return true;
}
function onStartShowUserGroupsContent($action) function onStartShowUserGroupsContent($action)
{
$this->showEntityRemoteSubscribe($action, 'ostatusgroup');
return true;
}
function onEndShowSubscriptionsMiniList($action)
{ {
$this->showEntityRemoteSubscribe($action); $this->showEntityRemoteSubscribe($action);
@ -1192,12 +1179,12 @@ class OStatusPlugin extends Plugin
function onEndShowGroupsMiniList($action) function onEndShowGroupsMiniList($action)
{ {
$this->showEntityRemoteSubscribe($action, 'ostatusgroup'); $this->showEntityRemoteSubscribe($action);
return true; return true;
} }
function showEntityRemoteSubscribe($action, $target='ostatussub') function showEntityRemoteSubscribe($action)
{ {
if (!$action->getScoped() instanceof Profile) { if (!$action->getScoped() instanceof Profile) {
// early return if we're not logged in // early return if we're not logged in
@ -1208,7 +1195,7 @@ class OStatusPlugin extends Plugin
$action->elementStart('div', 'entity_actions'); $action->elementStart('div', 'entity_actions');
$action->elementStart('p', array('id' => 'entity_remote_subscribe', $action->elementStart('p', array('id' => 'entity_remote_subscribe',
'class' => 'entity_subscribe')); 'class' => 'entity_subscribe'));
$action->element('a', array('href' => common_local_url($target), $action->element('a', array('href' => common_local_url('ostatusgroup'),
'class' => 'entity_remote_subscribe'), 'class' => 'entity_remote_subscribe'),
// TRANS: Link text for link to remote subscribe. // TRANS: Link text for link to remote subscribe.
_m('Remote')); _m('Remote'));
@ -1306,7 +1293,11 @@ class OStatusPlugin extends Plugin
if (common_logged_in()) { if (common_logged_in()) {
// only non-logged in users get to see the "remote subscribe" form // only non-logged in users get to see the "remote subscribe" form
return true; return true;
} elseif (!$item->getTarget()->isLocal()) { }
$target = $item->getTarget();
if (!$target->isLocal()) {
// we can (for now) only provide remote subscribe forms for local users // we can (for now) only provide remote subscribe forms for local users
return true; return true;
} }
@ -1320,21 +1311,11 @@ class OStatusPlugin extends Plugin
throw new ServerException('Bad item type for onStartProfileListItemActionElements'); throw new ServerException('Bad item type for onStartProfileListItemActionElements');
} }
// Add an OStatus subscribe
$output->elementStart('li', 'entity_subscribe');
$url = common_local_url('ostatusinit',
array('nickname' => $item->getTarget()->getNickname()));
$output->element('a', array('href' => $url,
'class' => 'entity_remote_subscribe'),
// TRANS: Link text for a user to subscribe to an OStatus user.
_m('Subscribe'));
$output->elementEnd('li');
$output->elementStart('li', 'entity_tag'); $output->elementStart('li', 'entity_tag');
$url = common_local_url('ostatustag', $url = common_local_url('ostatustag', ['nickname' => $target->getNickname()]);
array('nickname' => $item->getTarget()->getNickname())); $output->element('a',
$output->element('a', array('href' => $url, ['href' => $url,
'class' => 'entity_remote_tag'), 'class' => 'entity_remote_tag'],
// TRANS: Link text for a user to list an OStatus user. // TRANS: Link text for a user to list an OStatus user.
_m('List')); _m('List'));
$output->elementEnd('li'); $output->elementEnd('li');
@ -1480,12 +1461,6 @@ class OStatusPlugin extends Plugin
$xrd->links[] = new XML_XRD_Element_Link(Salmon::NS_REPLIES, $salmon_url); $xrd->links[] = new XML_XRD_Element_Link(Salmon::NS_REPLIES, $salmon_url);
$xrd->links[] = new XML_XRD_Element_Link(Salmon::NS_MENTIONS, $salmon_url); $xrd->links[] = new XML_XRD_Element_Link(Salmon::NS_MENTIONS, $salmon_url);
// TODO - finalize where the redirect should go on the publisher
$xrd->links[] = new XML_XRD_Element_Link('http://ostatus.org/schema/1.0/subscribe',
common_local_url('ostatussub') . '?profile={uri}',
null, // type not set
true); // isTemplate
return true; return true;
} }
@ -1611,4 +1586,31 @@ class OStatusPlugin extends Plugin
$qm->enqueue($item, 'pushrenew'); $qm->enqueue($item, 'pushrenew');
} }
} }
/**
* Try to grab and store the remote profile by the given uri
*
* @param string $uri
* @param Profile &$profile
* @return bool
*/
public function onRemoteFollowPullProfile(string $uri, ?Profile &$profile): bool
{
$oprofile = pullRemoteProfile($uri);
if ($oprofile instanceof Ostatus_profile) {
// validation
if ($oprofile->isGroup()) {
$target = common_local_url('ostatusgroup', [], ['profile' => $uri]);
common_redirect($target, 303);
} else if ($oprofile->isPeopletag()) {
$target = common_local_url('ostatuspeopletag', [], ['profile' => $uri]);
common_redirect($target, 303);
}
$profile = $oprofile->localProfile();
}
return is_null($profile);
}
} }

View File

@ -8,6 +8,11 @@ currently non-WebSub feeds cannot be subscribed unless an external
WebSub hub proxy is used. WebSub hub proxy is used.
Additional functionality:
The RemoteFollow plugin is highly recommended as it is the only way to remote
follow a user in OStatus, it adds a remote follow button to user profiles.
Configuration options available: Configuration options available:
$config['ostatus']['hub'] $config['ostatus']['hub']

View File

@ -47,7 +47,7 @@ class OStatusGroupAction extends OStatusSubAction
{ {
if (!$this->oprofile->isGroup()) { if (!$this->oprofile->isGroup()) {
// Send us to the user subscription form for conf // Send us to the user subscription form for conf
$target = common_local_url('ostatussub', array(), array('profile' => $this->profile_uri)); $target = common_local_url('RemoteFollowSub', array(), array('profile' => $this->profile_uri));
common_redirect($target, 303); common_redirect($target, 303);
} }
} }

View File

@ -47,7 +47,7 @@ class OStatusPeopletagAction extends OStatusSubAction
{ {
if (!$this->oprofile->isPeopletag()) { if (!$this->oprofile->isPeopletag()) {
// Send us to the user subscription form for conf // Send us to the user subscription form for conf
$target = common_local_url('ostatussub', array(), array('profile' => $this->profile_uri)); $target = common_local_url('RemoteFollowSub', array(), array('profile' => $this->profile_uri));
common_redirect($target, 303); common_redirect($target, 303);
} }
} }

View File

@ -0,0 +1,64 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Pull (and store) remote profile from the its uri
*
* @param string $uri
* @return null|Ostatus_profile
*/
function pullRemoteProfile(string $uri): ?Ostatus_profile
{
$validate = new Validate();
try {
$uri = Discovery::normalize($uri);
} catch (Exception $e) {
return null;
}
try {
if (Discovery::isAcct($uri) && $validate->email(mb_substr($uri, 5))) {
$profile = Ostatus_profile::ensureWebfinger($uri);
} else if ($validate->uri($uri)) {
$profile = Ostatus_profile::ensureProfileURL($uri);
} else {
common_log(LOG_ERR, 'Invalid address format.');
return null;
}
return $profile;
} catch (FeedSubBadURLException $e) {
common_log(LOG_ERR, 'Invalid URL or could not reach server.');
} catch (FeedSubBadResponseException $e) {
common_log(LOG_ERR, 'Cannot read feed; server returned error.');
} catch (FeedSubEmptyException $e) {
common_log(LOG_ERR, 'Cannot read feed; server returned an empty page.');
} catch (FeedSubBadHTMLException $e) {
common_log(LOG_ERR, 'Bad HTML, could not find feed link.');
} catch (FeedSubNoFeedException $e) {
common_log(LOG_ERR, 'Could not find a feed linked from this URL.');
} catch (FeedSubUnrecognizedTypeException $e) {
common_log(LOG_ERR, 'Not a recognized feed type.');
} catch (FeedSubNoHubException $e) {
common_log(LOG_ERR, 'No hub found.');
} catch (Exception $e) {
common_log(LOG_ERR, sprintf('Bad feed URL: %s %s', get_class($e), $e->getMessage()));
}
return null;
}