Search permissions part 2 with the dev doco.

This commit is contained in:
Mike Macgirvin 2023-01-22 12:28:38 +11:00
parent 395ed9b816
commit 94a544d944
5 changed files with 70 additions and 13 deletions

View file

@ -1642,8 +1642,15 @@ class Activity
'oauthAuthorizationEndpoint' => z_root() . '/authorize',
'oauthTokenEndpoint' => z_root() . '/token'
];
$ret['discoverable'] = (bool)((1 - intval($p['xchan_hidden'])));
if ($ret['discoverable'] && !Config::Get('system','block_public_search', 1)
&& perm_is_allowed($c['channel_id'],'', 'view_stream' ) &&
perm_is_allowed($c['channel_id'], '', 'search_stream')) {
$ret['endpoints']['searchContent'] = z_root() . '/search/' . $c['channel_address'] . '/?search={}';
$ret['endpoints']['searchTags'] = z_root() . '/search/' . $c['channel_address'] . '/?tag={}';
}
$ret['publicKey'] = [
'id' => $current_url . '?operation=getkey',
'owner' => $current_url,
@ -1779,6 +1786,11 @@ class Activity
'url' => System::get_site_icon(),
];
if (!Config::Get('system','block_public_search', 1)) {
$ret['endpoints']['searchContent'] = z_root() . '/search' . '?search={}';
$ret['endpoints']['searchTags'] = z_root() . '/search' . '?tag={}';
}
$ret['generator'] = ['type' => 'Application', 'name' => System::get_project_name()];
$ret['url'] = z_root();
@ -4589,7 +4601,9 @@ class Activity
'directMessage' => 'nomad:directMessage',
'Category' => 'nomad:Category',
'replyTo' => 'nomad:replyTo',
'copiedTo' => 'as:copiedTo',
'copiedTo' => 'nomad:copiedTo',
'searchContent' => 'nomad:searchContent',
'searchTags' => 'nomad:searchTags',
];
}

View file

@ -57,6 +57,10 @@ class Channel
$post_mail = array_key_exists('post_mail', $_POST) ? intval($_POST['post_mail']) : PERMS_SPECIFIC;
PermissionLimits::Set(local_channel(), 'post_mail', $post_mail);
$search_stream = array_key_exists('search_stream', $_POST) ? intval($_POST['search_stream']) : PERMS_SPECIFIC;
PermissionLimits::Set(local_channel(), 'search_stream', $search_stream);
$default_view_contacts = ($role === 'social_restricted') ? PERMS_SPECIFIC : PERMS_PUBLIC;
$view_contacts = array_key_exists('view_contacts', $_POST) ? intval($_POST['view_contacts']) : $default_view_contacts;
PermissionLimits::Set(local_channel(), 'view_contacts', $view_contacts);
@ -253,9 +257,9 @@ class Channel
$permiss = [];
$perm_opts = [
[t('Restricted - from connections only'), PERMS_SPECIFIC],
[t('Semi-public - from anybody that can be identified'), PERMS_AUTHED],
[t('Public - from anybody on the internet'), PERMS_PUBLIC]
[t('Restricted - connections only'), PERMS_SPECIFIC],
[t('Semi-public - anybody that can be identified'), PERMS_AUTHED],
[t('Public - anybody on the internet'), PERMS_PUBLIC]
];
$limits = PermissionLimits::Get(local_channel());
@ -263,7 +267,7 @@ class Channel
foreach ($global_perms as $k => $perm) {
$options = [];
$can_be_public = strstr($k, 'view') || ($k === 'post_comments' && $anon_comments);
$can_be_public = strstr($k, 'view') || ($k === 'search_stream') || ($k === 'post_comments' && $anon_comments);
foreach ($perm_opts as $opt) {
if ($opt[1] == PERMS_PUBLIC && (!$can_be_public)) {
continue;
@ -276,6 +280,8 @@ class Channel
$mail_perms = [$k, $perm, $limits[$k], '', $options];
} elseif ($k === 'view_contacts') {
$view_contact_perms = [$k, $perm, $limits[$k], '', $options];
} elseif ($k === 'search_stream') {
$search_perms = [$k, $perm, $limits[$k], '', $options];
} else {
$permiss[] = [$k, $perm, $limits[$k], '', $options];
}
@ -453,6 +459,7 @@ class Channel
'$comment_perms' => $comment_perms,
'$mail_perms' => $mail_perms,
'$view_contact_perms' => $view_contact_perms,
'$search_perms' => $search_perms,
'$noindex' => ['noindex', t('Forbid indexing of your public channel content by search engines'), get_pconfig($channel['channel_id'], 'system', 'noindex'), '', $yes_no],
'$close_comments' => ['close_comments', t('Disable acceptance of comments on your posts after this many days'), ((intval(get_pconfig(local_channel(), 'system', 'close_comments'))) ? intval(get_pconfig(local_channel(), 'system', 'close_comments')) : EMPTY_STR), t('Leave unset or enter 0 to allow comments indefinitely')],
'$blocktags' => ['blocktags', t('Allow others to tag your posts'), 1 - $blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no],

View file

@ -4,7 +4,6 @@ namespace Code\Module;
use App;
use Code\Web\Controller;
use Code\Lib\Libsync;
use Code\Lib\Channel;
use Code\Lib\Addon;
@ -24,10 +23,12 @@ class Wall_attach extends Controller
}
/** @noinspection PhpInconsistentReturnPointsInspection */
public function post()
{
$using_api = false;
$channel = null;
$result = [];
@ -54,7 +55,7 @@ class Wall_attach extends Controller
$partial = false;
if (array_key_exists('HTTP_CONTENT_RANGE', $_SERVER)) {
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/', $_SERVER['HTTP_CONTENT_RANGE'], $matches);
$pm = preg_match('/bytes (\d*)-(\d*)\/(\d*)/', $_SERVER['HTTP_CONTENT_RANGE'], $matches);
if ($pm) {
// logger('Content-Range: ' . print_r($matches,true));
$partial = true;
@ -117,14 +118,13 @@ class Wall_attach extends Controller
$url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
if (strpos($r['data']['filetype'], 'video') === 0) {
if (str_starts_with($r['data']['filetype'], 'video')) {
for ($n = 0; $n < 15; $n++) {
$thumb = Linkinfo::get_video_poster($url);
if ($thumb) {
break;
}
sleep(1);
continue;
}
if ($thumb) {
@ -133,7 +133,7 @@ class Wall_attach extends Controller
$s .= "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n";
}
}
if (strpos($r['data']['filetype'], 'audio') === 0) {
if (str_starts_with($r['data']['filetype'], 'audio')) {
$s .= "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n";
}
if ($r['data']['filetype'] === 'image/svg+xml') {
@ -177,10 +177,8 @@ class Wall_attach extends Controller
}
}
$s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
if ($using_api) {
return $s;
}

View file

@ -0,0 +1,37 @@
Federated Search
================
The federated search feature was added to provide individual control over the
ability to search your stream and personal content.
Previously this was a site security setting made by the site admin.
## Implementation Details
The first part of this epoch was to enable the fetching of search results as an ActivityStreams 'Collection'. This work was completed some time ago.
The second phase is providing a new permission named 'search_stream'. Only viewers possessing both 'view_stream' and 'search_stream' permission can search your channel content going forward. This permission can be assigned individually, or automatically by channel Permission Role and the personal Roles app.
The underlying search module is also to be changed so that the URL may contain a channel name. In the absence of a channel username in the URL the entire site will be searched, but will only provide results from channels which have permitted search to the current viewer. When a channel username is present, the search is restricted to content authored by that channel.
The channel search URL will be provided in the ActivityPub and Nomad actor records in the optional 'endpoints' section. The names used are 'nomad:searchContent' and 'nomad:searchTags'. These endpoints will be essentially a template, containing a bracket pair {} which is then substituted with the desired search text. If evaluated with the nomad: prefix, the URL is guaranteed to provide results for both HTML and ActivityPub/ActivityStreams/Nomad/Zot6 requests. If used with any other namespace prefix, it is only assumed to provide an ActivityPub compliant endpoint.
If a channel has federated search enabled, a new entry will be provided in the author action drop down attached to every post/comment. This will be named 'Search' (or 'Search Content' and 'Search Tags') and will perform an HTML search of the provided endpoint(s). This entry will only be present if the provided endpoints are associated with the 'nomad:' context namespace.
If a channel has opted out of channel discovery (inclusion in federated directories), no search links will be provided; with the exception of the so-called 'system channel' which represents the site. The system channel will provide these links purely based on the system setting of 'block_public_search'.
## Acceptance Criteria and Testing
Validate the existence of the endpoint across all protocols when the discovery criteria have been met.
Validate that a site search does not contain content created by a member which you do not have permission to search.
Validate that a channel search only contains content created by the requested channel and that matching results are found if content exists containing that search text.
Repeat results testing with hashtag search.
Verify the search results contain the same information whether fetched via HTML or via federated protocol and that the returned data objects are valid for the federated protocol used.
## Data Migration
A database migration may be required to set the initial 'search_stream' permission correctly for existing channels based on the channel permissions role.

View file

@ -56,6 +56,7 @@
{{include file="field_input.tpl" field=$close_comments}}
{{include file="field_select.tpl" field=$mail_perms}}
{{include file="field_select.tpl" field=$view_contact_perms}}
{{include file="field_select.tpl" field=$search_perms}}
{{include file="field_checkbox.tpl" field=$permit_all_mentions}}
{{include file="field_input.tpl" field=$unless_mention_count}}
{{include file="field_input.tpl" field=$followed_tags}}