Merge pull request #13294 from annando/restricted-access
The access to the profile and the list of followers/followings can now be restricted
This commit is contained in:
commit
4a5abd1527
|
@ -84,7 +84,7 @@ class Profile extends BaseProfile
|
|||
$user = $this->database->selectFirst('user', ['uid'], ['nickname' => $this->parameters['nickname'] ?? '', 'account_removed' => false]);
|
||||
if ($user) {
|
||||
try {
|
||||
$data = ActivityPub\Transmitter::getProfile($user['uid']);
|
||||
$data = ActivityPub\Transmitter::getProfile($user['uid'], ActivityPub::isAcceptedRequester($user['uid']));
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Cache-Control: max-age=23200, stale-while-revalidate=23200');
|
||||
System::jsonExit($data, 'application/activity+json');
|
||||
|
|
|
@ -23,7 +23,9 @@ namespace Friendica\Protocol;
|
|||
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Model\APContact;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Util\HTTPSignature;
|
||||
use Friendica\Util\JsonLD;
|
||||
|
@ -59,26 +61,29 @@ use Friendica\Util\JsonLD;
|
|||
class ActivityPub
|
||||
{
|
||||
const PUBLIC_COLLECTION = 'https://www.w3.org/ns/activitystreams#Public';
|
||||
const CONTEXT = ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1',
|
||||
['vcard' => 'http://www.w3.org/2006/vcard/ns#',
|
||||
'dfrn' => 'http://purl.org/macgirvin/dfrn/1.0/',
|
||||
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||
'litepub' => 'http://litepub.social/ns#',
|
||||
'toot' => 'http://joinmastodon.org/ns#',
|
||||
'featured' => [
|
||||
"@id" => "toot:featured",
|
||||
"@type" => "@id",
|
||||
],
|
||||
'schema' => 'http://schema.org#',
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag',
|
||||
'quoteUrl' => 'as:quoteUrl',
|
||||
'conversation' => 'ostatus:conversation',
|
||||
'directMessage' => 'litepub:directMessage',
|
||||
'discoverable' => 'toot:discoverable',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
]];
|
||||
const CONTEXT = [
|
||||
'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1',
|
||||
[
|
||||
'vcard' => 'http://www.w3.org/2006/vcard/ns#',
|
||||
'dfrn' => 'http://purl.org/macgirvin/dfrn/1.0/',
|
||||
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||
'litepub' => 'http://litepub.social/ns#',
|
||||
'toot' => 'http://joinmastodon.org/ns#',
|
||||
'featured' => [
|
||||
"@id" => "toot:featured",
|
||||
"@type" => "@id",
|
||||
],
|
||||
'schema' => 'http://schema.org#',
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag',
|
||||
'quoteUrl' => 'as:quoteUrl',
|
||||
'conversation' => 'ostatus:conversation',
|
||||
'directMessage' => 'litepub:directMessage',
|
||||
'discoverable' => 'toot:discoverable',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
]
|
||||
];
|
||||
const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application', 'Tombstone'];
|
||||
/**
|
||||
* Checks if the web request is done for the AP protocol
|
||||
|
@ -117,7 +122,7 @@ class ActivityPub
|
|||
{
|
||||
$accounttype = -1;
|
||||
|
||||
switch($apcontact['type']) {
|
||||
switch ($apcontact['type']) {
|
||||
case 'Person':
|
||||
$accounttype = User::ACCOUNT_TYPE_PERSON;
|
||||
break;
|
||||
|
@ -277,4 +282,38 @@ class ActivityPub
|
|||
{
|
||||
return !empty(APContact::getByURL($url, $update));
|
||||
}
|
||||
|
||||
public static function isAcceptedRequester(int $uid = 0): bool
|
||||
{
|
||||
$called_by = System::callstack(1);
|
||||
|
||||
$signer = HTTPSignature::getSigner('', $_SERVER);
|
||||
if (!$signer) {
|
||||
Logger::debug('No signer or invalid signature', ['uid' => $uid, 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'called_by' => $called_by]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$apcontact = APContact::getByURL($signer);
|
||||
if (empty($apcontact)) {
|
||||
Logger::info('APContact not found', ['uid' => $uid, 'handle' => $signer, 'called_by' => $called_by]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($apcontact['gsid'] || empty($apcontact['baseurl']))) {
|
||||
Logger::debug('No server found', ['uid' => $uid, 'signer' => $signer, 'called_by' => $called_by]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$contact = Contact::getByURL($signer, false, ['id', 'baseurl', 'gsid']);
|
||||
if (!empty($contact) && Contact\User::isBlocked($contact['id'], $uid)) {
|
||||
Logger::info('Requesting contact is blocked', ['uid' => $uid, 'id' => $contact['id'], 'signer' => $signer, 'baseurl' => $contact['baseurl'], 'called_by' => $called_by]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// @todo Look for user blocked domains
|
||||
|
||||
Logger::debug('Server is an accepted requester', ['uid' => $uid, 'id' => $apcontact['gsid'], 'url' => $apcontact['baseurl'], 'signer' => $signer, 'called_by' => $called_by]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ class Transmitter
|
|||
}
|
||||
|
||||
// When we hide our friends we will only show the pure number but don't allow more.
|
||||
$show_contacts = empty($owner['hide-friends']);
|
||||
$show_contacts = ActivityPub::isAcceptedRequester($owner['uid']) && empty($owner['hide-friends']);
|
||||
|
||||
// Allow fetching the contact list when the requester is part of the list.
|
||||
if (($owner['page-flags'] == User::PAGE_FLAGS_PRVGROUP) && !empty($requester)) {
|
||||
|
@ -337,12 +337,13 @@ class Transmitter
|
|||
/**
|
||||
* Return the ActivityPub profile of the given user
|
||||
*
|
||||
* @param int $uid User ID
|
||||
* @param int $uid User ID
|
||||
* @param bool $full If not full, only the basic information is returned
|
||||
* @return array with profile data
|
||||
* @throws HTTPException\NotFoundException
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getProfile(int $uid): array
|
||||
public static function getProfile(int $uid, bool $full = true): array
|
||||
{
|
||||
$owner = User::getOwnerDataById($uid);
|
||||
if (!isset($owner['id'])) {
|
||||
|
@ -372,16 +373,16 @@ class Transmitter
|
|||
$data['preferredUsername'] = $owner['nick'];
|
||||
$data['name'] = $owner['name'];
|
||||
|
||||
if (!empty($owner['country-name'] . $owner['region'] . $owner['locality'])) {
|
||||
if (!$full && !empty($owner['country-name'] . $owner['region'] . $owner['locality'])) {
|
||||
$data['vcard:hasAddress'] = ['@type' => 'vcard:Home', 'vcard:country-name' => $owner['country-name'],
|
||||
'vcard:region' => $owner['region'], 'vcard:locality' => $owner['locality']];
|
||||
}
|
||||
|
||||
if (!empty($owner['about'])) {
|
||||
if ($full && !empty($owner['about'])) {
|
||||
$data['summary'] = BBCode::convertForUriId($owner['uri-id'] ?? 0, $owner['about'], BBCode::EXTERNAL);
|
||||
}
|
||||
|
||||
if (!empty($owner['xmpp']) || !empty($owner['matrix'])) {
|
||||
if ($full && (!empty($owner['xmpp']) || !empty($owner['matrix']))) {
|
||||
$data['vcard:hasInstantMessage'] = [];
|
||||
|
||||
if (!empty($owner['xmpp'])) {
|
||||
|
@ -399,7 +400,7 @@ class Transmitter
|
|||
'owner' => $owner['url'],
|
||||
'publicKeyPem' => $owner['pubkey']];
|
||||
$data['endpoints'] = ['sharedInbox' => DI::baseUrl() . '/inbox'];
|
||||
if ($uid != 0) {
|
||||
if ($full && $uid != 0) {
|
||||
$data['icon'] = ['type' => 'Image', 'url' => User::getAvatarUrl($owner)];
|
||||
|
||||
$resourceid = Photo::ridFromURI($owner['photo']);
|
||||
|
|
Loading…
Reference in New Issue
Block a user