rework delivery permissions to allow sender, owner, and mentions

This commit is contained in:
Mike Macgirvin 2024-06-16 08:55:21 +10:00
parent adb0bc1b9d
commit e001c86b4a
3 changed files with 51 additions and 17 deletions

View file

@ -125,7 +125,7 @@ function collect_recipients($item, &$private_envelope) {
// This is a somewhat expensive operation but important.
// Don't send this item to anybody who doesn't have the deliver_stream permission
$recipients = check_deliver_permissions($item['uid'],$recipients);
$recipients = check_deliver_permissions($item,$recipients);
// Add both the author and owner (if different).

View file

@ -515,9 +515,11 @@ function check_list_permissions($uid, $arr, $perm)
return($result);
}
function check_deliver_permissions($uid, $arr)
function check_deliver_permissions($item, $arr)
{
$result = [];
$uid = $item['uid'] ?? 0;
$terms = ((isset($item['term'])) ? get_terms_oftype($item['term'], [TERM_MENTION, TERM_GROUP]) : false);
// Find actors we are not delivering to.
$r = q("select * from abconfig where chan = %d and cat = 'system' and k = 'my_perms' and v not like '%%deliver_stream%%'",
intval($uid)
@ -533,27 +535,59 @@ function check_deliver_permissions($uid, $arr)
// Filter the recipient list accordingly.
if ($arr) {
foreach ($arr as $x) {
foreach ($arr as $recipient) {
$accepting = $deliverable = false;
if (in_array($x, $theyAccept)) {
if (in_array($recipient, $theyAccept)) {
$accepting = true;
}
if (!in_array($x,$willNotSend)) {
if (!in_array($recipient,$willNotSend)) {
$deliverable = true;
}
if ($deliverable && !$accepting) {
if (in_array($recipient, [$item['author_xchan'], $item['owner_xchan']])) {
$deliverable = $accepting = true;
}
if (!$deliverable || !$accepting) {
// Groups don't generally provide send_stream permission as they aren't really following you,
// but they do allow you to send them group targeted posts.
$r = q("select xchan_hash from xchan where xchan_hash = '%s' and xchan_type = %d ",
dbesc($x),
intval(XCHAN_TYPE_GROUP)
);
if ($r) {
$result[] = $x;
if ($deliverable) {
$r = q("select xchan_hash from xchan where xchan_hash = '%s' and xchan_type = %d",
dbesc($recipient),
intval(XCHAN_TYPE_GROUP)
);
if ($r) {
if ($r && !in_array($recipient, $result)) {
$result[] = $recipient;
continue;
}
}
}
// Send mentions even if you have no permission to do so. They might allow it.
if ($terms) {
foreach ($terms as $term) {
if (in_array($term['url'], $result)) {
continue;
}
// activitypub is easy because $x will match directly on the mention url
if ($recipient === $term['url'] && (!in_array($recipient, $result))) {
$result[] = $recipient;
break;
}
// zot/nomad is harder because we will need to match the portable_id to the mention url
// and won't be able to perform duplicate detection
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_id_url = '%s' and hubloc_deleted = 0",
dbesc($recipient),
dbesc($term['url'])
);
if ($r && !in_array($recipient, $result)) {
$result[] = $recipient;
break;
}
}
}
}
if ($deliverable && $accepting) {
$result[] = $x;
if ($deliverable && $accepting && !in_array($recipient, $result)) {
$result[] = $recipient;
}
}
}

View file

@ -444,7 +444,7 @@ class Notifier implements DaemonInterface
else {
$sendto = array_merge($sendto, self::getConversationAudience($parent_item));
}
self::$recipients = check_deliver_permissions($target_item['uid'], $sendto);
self::$recipients = check_deliver_permissions($target_item, $sendto);
logger('followup relay (upstream delivery)', LOGGER_DEBUG);
logger('replyto: upstream recipients ' . print_r(self::$recipients, true), LOGGER_DEBUG);
@ -497,7 +497,7 @@ class Notifier implements DaemonInterface
foreach ($r as $rv) {
self::$recipients[] = $rv['abook_xchan'];
}
self::$recipients = check_deliver_permissions($target_item['uid'], self::$recipients);
self::$recipients = check_deliver_permissions($target_item, self::$recipients);
}
}
elseif (($audience & AUDIENCE_SENDER) || ($audience & AUDIENCE_FOLLOWERS)
@ -524,7 +524,7 @@ class Notifier implements DaemonInterface
}
}
}
self::$recipients = check_deliver_permissions($target_item['uid'], $sendto);
self::$recipients = check_deliver_permissions($target_item, $sendto);
}
else {
self::$private = false;