From ffc364f2a4c8ed14c28fa01061d11c4f1a28af06 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 11 Nov 2020 02:50:22 -0500 Subject: [PATCH] Reject replies when author is blocked by thread owner in Model\Item::insert - Move user-level item permission to Model\Item::isAllowedByUser - Add user-level check for comments on top-level item --- src/Model/Contact/User.php | 4 +-- src/Model/Item.php | 63 +++++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/Model/Contact/User.php b/src/Model/Contact/User.php index 34a3d6f341..be60c119bf 100644 --- a/src/Model/Contact/User.php +++ b/src/Model/Contact/User.php @@ -64,7 +64,7 @@ class User { $cdata = Contact::getPublicAndUserContacID($cid, $uid); if (empty($cdata)) { - return; + return false; } $public_blocked = false; @@ -127,7 +127,7 @@ class User { $cdata = Contact::getPublicAndUserContacID($cid, $uid); if (empty($cdata)) { - return; + return false; } $public_ignored = false; diff --git a/src/Model/Item.php b/src/Model/Item.php index e67b862346..3239c4a8f9 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1415,11 +1415,6 @@ class Item return false; } - if (!empty($item['uid']) && !empty($item['author-id']) && Contact\User::isBlocked($item['author-id'], $item['uid'])) { - Logger::notice('Author is blocked by user', ['author-link' => $item['author-link'], 'uid' => $item['uid'], 'item-uri' => $item['uri']]); - return false; - } - if (!empty($item['owner-id']) && Contact::isBlocked($item['owner-id'])) { Logger::notice('Owner is blocked node-wide', ['owner-link' => $item['owner-link'], 'item-uri' => $item['uri']]); return false; @@ -1430,22 +1425,10 @@ class Item return false; } - if (!empty($item['uid']) && !empty($item['owner-id']) && Contact\User::isBlocked($item['owner-id'], $item['uid'])) { - Logger::notice('Owner is blocked by user', ['owner-link' => $item['owner-link'], 'uid' => $item['uid'], 'item-uri' => $item['uri']]); + if (!empty($item['uid']) && !self::isAllowedByUser($item, $item['uid'])) { return false; } - // The causer is set during a thread completion, for example because of a reshare. It countains the responsible actor. - if (!empty($item['uid']) && !empty($item['causer-id']) && Contact\User::isBlocked($item['causer-id'], $item['uid'])) { - Logger::notice('Causer is blocked by user', ['causer-link' => $item['causer-link'], 'uid' => $item['uid'], 'item-uri' => $item['uri']]); - return false; - } - - if (!empty($item['uid']) && !empty($item['causer-id']) && ($item['parent-uri'] == $item['uri']) && Contact\User::isIgnored($item['causer-id'], $item['uid'])) { - Logger::notice('Causer is ignored by user', ['causer-link' => $item['causer-link'], 'uid' => $item['uid'], 'item-uri' => $item['uri']]); - return false; - } - if ($item['verb'] == Activity::FOLLOW) { if (!$item['origin'] && ($item['author-id'] == Contact::getPublicIdByUserId($item['uid']))) { // Our own follow request can be relayed to us. We don't store it to avoid notification chaos. @@ -1533,6 +1516,13 @@ class Item return []; } + if ($toplevel_parent['wall'] + && $toplevel_parent['uid'] && + !self::isAllowedByUser($item, $toplevel_parent['uid']) + ) { + return []; + } + return $toplevel_parent; } @@ -3955,4 +3945,41 @@ class Item return array_merge($item, $shared_item); } + + /** + * Check a prospective item array against user-level permissions + * + * @param array $item Expected keys: uri, gravity, and + * author-link if is author-id is set, + * owner-link if is owner-id is set, + * causer-link if is causer-id is set. + * @param int $user_id Local user ID + * @return bool + * @throws \Exception + */ + protected static function isAllowedByUser(array $item, int $user_id) + { + if (!empty($item['author-id']) && Contact\User::isBlocked($item['author-id'], $user_id)) { + Logger::notice('Author is blocked by user', ['author-link' => $item['author-link'], 'uid' => $user_id, 'item-uri' => $item['uri']]); + return false; + } + + if (!empty($item['owner-id']) && Contact\User::isBlocked($item['owner-id'], $user_id)) { + Logger::notice('Owner is blocked by user', ['owner-link' => $item['owner-link'], 'uid' => $user_id, 'item-uri' => $item['uri']]); + return false; + } + + // The causer is set during a thread completion, for example because of a reshare. It countains the responsible actor. + if (!empty($item['causer-id']) && Contact\User::isBlocked($item['causer-id'], $user_id)) { + Logger::notice('Causer is blocked by user', ['causer-link' => $item['causer-link'], 'uid' => $user_id, 'item-uri' => $item['uri']]); + return false; + } + + if (!empty($item['causer-id']) && ($item['gravity'] === GRAVITY_PARENT) && Contact\User::isIgnored($item['causer-id'], $user_id)) { + Logger::notice('Causer is ignored by user', ['causer-link' => $item['causer-link'], 'uid' => $user_id, 'item-uri' => $item['uri']]); + return false; + } + + return true; + } }