diff --git a/src/Module/Objects.php b/src/Module/Objects.php index 8080289f1..e03265486 100644 --- a/src/Module/Objects.php +++ b/src/Module/Objects.php @@ -25,9 +25,11 @@ use Friendica\BaseModule; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Network\HTTPException; use Friendica\Protocol\ActivityPub; +use Friendica\Util\HTTPSignature; use Friendica\Util\Network; /** @@ -45,17 +47,27 @@ class Objects extends BaseModule DI::baseUrl()->redirect(str_replace('objects/', 'display/', DI::args()->getQueryString())); } - /// @todo Add Authentication to enable fetching of non public content - // $requester = HTTPSignature::getSigner('', $_SERVER); + $item = Item::selectFirst(['id', 'uid', 'origin', 'author-link', 'changed', 'private', 'psid'], + ['guid' => $parameters['guid']], ['order' => ['origin' => true]]); + + $validated = false; + $requester = HTTPSignature::getSigner('', $_SERVER); + if (!empty($requester) && $item['origin']) { + $requester_id = Contact::getIdForURL($requester, $item['uid']); + if (!empty($requester_id)) { + $permissionSets = DI::permissionSet()->selectByContactId($requester_id, $item['uid']); + if (!empty($permissionSets)) { + $psid = array_merge($permissionSets->column('id'), + [DI::permissionSet()->getIdFromACL($item['uid'], '', '', '', '')]); + $validated = in_array($item['psid'], $psid); + } + } + } + + if (!$validated && !in_array($item['private'], [Item::PUBLIC, Item::UNLISTED])) { + unset($item); + } - $item = Item::selectFirst( - ['id', 'origin', 'author-link', 'changed'], - [ - 'guid' => $parameters['guid'], - 'private' => [Item::PUBLIC, Item::UNLISTED] - ], - ['order' => ['origin' => true]] - ); // Valid items are original post or posted from this node (including in the case of a forum) if (!DBA::isResult($item) || !$item['origin'] && (parse_url($item['author-link'], PHP_URL_HOST) != parse_url(DI::baseUrl()->get(), PHP_URL_HOST))) { throw new HTTPException\NotFoundException(); diff --git a/src/Module/Outbox.php b/src/Module/Outbox.php index 265c130b1..3a822cc6e 100644 --- a/src/Module/Outbox.php +++ b/src/Module/Outbox.php @@ -22,10 +22,10 @@ namespace Friendica\Module; use Friendica\BaseModule; -use Friendica\Core\System; use Friendica\DI; use Friendica\Model\User; use Friendica\Protocol\ActivityPub; +use Friendica\Util\HTTPSignature; /** * ActivityPub Outbox @@ -48,11 +48,8 @@ class Outbox extends BaseModule $page = $_REQUEST['page'] ?? null; - /// @todo Add Authentication to enable fetching of non public content - // $requester = HTTPSignature::getSigner('', $_SERVER); - - $outbox = ActivityPub\Transmitter::getOutbox($owner, $page); - + $requester = HTTPSignature::getSigner('', $_SERVER); + $outbox = ActivityPub\Transmitter::getOutbox($owner, $page, $requester); header('Content-Type: application/activity+json'); echo json_encode($outbox); exit(); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 2abc88307..c798e619e 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -141,20 +141,37 @@ class Transmitter /** * Public posts for the given owner * - * @param array $owner Owner array - * @param integer $page Page numbe + * @param array $owner Owner array + * @param integer $page Page number + * @param string $requester URL of requesting account * * @return array of posts * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function getOutbox($owner, $page = null) + public static function getOutbox($owner, $page = null, $requester = '') { $public_contact = Contact::getIdForURL($owner['url']); + $condition = ['uid' => 0, 'contact-id' => $public_contact, + 'private' => [Item::PUBLIC, Item::UNLISTED]]; + + if (!empty($requester)) { + $requester_id = Contact::getIdForURL($requester, $owner['uid']); + if (!empty($requester_id)) { + $permissionSets = DI::permissionSet()->selectByContactId($requester_id, $owner['uid']); + if (!empty($permissionSets)) { + $condition = ['uid' => $owner['uid'], 'origin' => true, + 'psid' => array_merge($permissionSets->column('id'), + [DI::permissionSet()->getIdFromACL($owner['uid'], '', '', '', '')])]; + } + } + } + + $condition = array_merge($condition, + ['author-id' => $public_contact, + 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], + 'deleted' => false, 'visible' => true, 'moderated' => false]); - $condition = ['uid' => 0, 'contact-id' => $public_contact, 'author-id' => $public_contact, - 'private' => [Item::PUBLIC, Item::UNLISTED], 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], - 'deleted' => false, 'visible' => true, 'moderated' => false]; $count = DBA::count('item', $condition); $data = ['@context' => ActivityPub::CONTEXT]; diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 5165f600f..cdee48bfc 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -484,7 +484,7 @@ class HTTPSignature } $headers = []; - $headers['(request-target)'] = strtolower($http_headers['REQUEST_METHOD']) . ' ' . $http_headers['REQUEST_URI']; + $headers['(request-target)'] = strtolower($http_headers['REQUEST_METHOD']) . ' ' . parse_url($http_headers['REQUEST_URI'], PHP_URL_PATH); // First take every header foreach ($http_headers as $k => $v) {