X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCore%2FACL.php;h=1bf8ef03eee9fdc8f8b1a4f2aa1f2fffd9582b27;hb=d4a5a8051ad34a7be72238967afb3e6b140afdc8;hp=1c32759cfd6c509c17c696b1e48177ba5292871c;hpb=2c56d2f3360c08e312e5c167261af8e5d4b87af4;p=friendica.git diff --git a/src/Core/ACL.php b/src/Core/ACL.php index 1c32759cfd..1bf8ef03ee 100644 --- a/src/Core/ACL.php +++ b/src/Core/ACL.php @@ -1,6 +1,6 @@ \r\n"; - - $stmt = DBA::p("SELECT `id`, `name`, `url`, `network` FROM `contact` - WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND NOT `deleted` AND `notify` != '' - $sql_extra - ORDER BY `name` ASC ", intval(local_user()) - ); - - $contacts = DBA::toArray($stmt); - - $arr = ['contact' => $contacts, 'entry' => $o]; + $page = DI::page(); - // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow' - Hook::callAll(DI::module()->getName() . '_pre_' . $selname, $arr); + $page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); + $page->registerFooterScript(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.js')); + $page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css')); + $page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css')); - $receiverlist = []; + $contacts = self::getValidMessageRecipientsForUser(DI::userSession()->getLocalUserId()); - if (DBA::isResult($contacts)) { - foreach ($contacts as $contact) { - if (in_array($contact['id'], $preselected)) { - $selected = ' selected="selected"'; - } else { - $selected = ''; - } + $tpl = Renderer::getMarkupTemplate('acl/message_recipient.tpl'); + $o = Renderer::replaceMacros($tpl, [ + '$contacts' => $contacts, + '$contacts_json' => json_encode($contacts), + '$selected' => $selected, + ]); - $trimmed = Protocol::formatMention($contact['url'], $contact['name']); + Hook::callAll(DI::args()->getModuleName() . '_post_recipient', $o); - $receiverlist[] = $trimmed; + return $o; + } - $o .= "\r\n"; - } - } + public static function getValidMessageRecipientsForUser(int $uid): array + { + $condition = [ + 'uid' => $uid, + 'self' => false, + 'blocked' => false, + 'pending' => false, + 'archive' => false, + 'deleted' => false, + 'rel' => [Contact::FOLLOWER, Contact::SHARING, Contact::FRIEND], + 'network' => Protocol::SUPPORT_PRIVATE, + ]; - $o .= '' . PHP_EOL; + return Contact::selectToArray( + ['id', 'name', 'addr', 'micro', 'url', 'nick'], + DBA::mergeConditions($condition, ["`notify` != ''"]) + ); + } - if ($preselected) { - $o .= implode(', ', $receiverlist); - } + /** + * Returns a minimal ACL block for self-only permissions + * + * @param int $localUserId + * @param string $explanation + * @return string + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public static function getSelfOnlyHTML(int $localUserId, string $explanation) + { + $selfPublicContactId = Contact::getPublicIdByUserId($localUserId); - Hook::callAll(DI::module()->getName() . '_post_' . $selname, $o); + $tpl = Renderer::getMarkupTemplate('acl/self_only.tpl'); + $o = Renderer::replaceMacros($tpl, [ + '$selfPublicContactId' => $selfPublicContactId, + '$explanation' => $explanation, + ]); return $o; } @@ -146,6 +156,7 @@ class ACL 'archive' => false, 'deleted' => false, 'pending' => false, + 'network' => Protocol::FEDERATED, 'rel' => [Contact::FOLLOWER, Contact::FRIEND] ], $condition), $params @@ -156,12 +167,12 @@ class ACL $acl_contacts[] = $acl_yourself; - $acl_forums = Contact::selectToArray($fields, + $acl_groups = Contact::selectToArray($fields, ['uid' => $user_id, 'self' => false, 'blocked' => false, 'archive' => false, 'deleted' => false, - 'pending' => false, 'contact-type' => Contact::TYPE_COMMUNITY], $params + 'network' => Protocol::FEDERATED, 'pending' => false, 'contact-type' => Contact::TYPE_COMMUNITY], $params ); - $acl_contacts = array_merge($acl_forums, $acl_contacts); + $acl_contacts = array_merge($acl_groups, $acl_contacts); array_walk($acl_contacts, function (&$value) { $value['type'] = 'contact'; @@ -171,55 +182,54 @@ class ACL } /** - * Returns the ACL list of groups (including meta-groups) for a given user id + * Returns the ACL list of circles (including meta-circles) for a given user id * * @param int $user_id * @return array */ - public static function getGroupListByUserId(int $user_id) + public static function getCircleListByUserId(int $user_id) { - $acl_groups = [ + $acl_circles = [ [ - 'id' => Group::FOLLOWERS, + 'id' => Circle::FOLLOWERS, 'name' => DI::l10n()->t('Followers'), 'addr' => '', 'micro' => 'images/twopeople.png', - 'type' => 'group', + 'type' => 'circle', ], [ - 'id' => Group::MUTUALS, + 'id' => Circle::MUTUALS, 'name' => DI::l10n()->t('Mutuals'), 'addr' => '', 'micro' => 'images/twopeople.png', - 'type' => 'group', + 'type' => 'circle', ] ]; - foreach (Group::getByUserId($user_id) as $group) { - $acl_groups[] = [ - 'id' => $group['id'], - 'name' => $group['name'], + foreach (Circle::getByUserId($user_id) as $circle) { + $acl_circles[] = [ + 'id' => $circle['id'], + 'name' => $circle['name'], 'addr' => '', 'micro' => 'images/twopeople.png', - 'type' => 'group', + 'type' => 'circle', ]; } - return $acl_groups; + return $acl_circles; } /** * Return the full jot ACL selector HTML * * @param Page $page - * @param array $user User array + * @param int $uid User ID * @param bool $for_federation * @param array $default_permissions Static defaults permission array: * [ * 'allow_cid' => [], * 'allow_gid' => [], * 'deny_cid' => [], - * 'deny_gid' => [], - * 'hidewall' => true/false + * 'deny_gid' => [] * ] * @param array $condition * @param string $form_prefix @@ -228,18 +238,20 @@ class ACL */ public static function getFullSelectorHTML( Page $page, - array $user = null, + int $uid = null, bool $for_federation = false, array $default_permissions = [], array $condition = [], $form_prefix = '' ) { - if (empty($user['uid'])) { + if (empty($uid)) { return ''; } static $input_group_id = 0; + $user = User::getById($uid); + $input_group_id++; $page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); @@ -257,7 +269,6 @@ class ACL 'allow_gid' => $default_permissions['allow_gid'] ?? [], 'deny_cid' => $default_permissions['deny_cid'] ?? [], 'deny_gid' => $default_permissions['deny_gid'] ?? [], - 'hidewall' => $default_permissions['hidewall'] ?? false, ]; if (count($default_permissions['allow_cid']) @@ -268,80 +279,126 @@ class ACL } else { $visibility = 'public'; // Default permission display for custom panel - $default_permissions['allow_gid'] = [Group::FOLLOWERS]; + $default_permissions['allow_gid'] = [Circle::FOLLOWERS]; } $jotnets_fields = []; if ($for_federation) { - $mail_enabled = false; - $pubmail_enabled = false; - if (function_exists('imap_open') && !DI::config()->get('system', 'imap_disabled')) { $mailacct = DBA::selectFirst('mailacct', ['pubmail'], ['`uid` = ? AND `server` != ""', $user['uid']]); if (DBA::isResult($mailacct)) { - $mail_enabled = true; - $pubmail_enabled = !empty($mailacct['pubmail']); - } - } - - if (!$default_permissions['hidewall']) { - if ($mail_enabled) { $jotnets_fields[] = [ 'type' => 'checkbox', 'field' => [ 'pubmail_enable', DI::l10n()->t('Post to Email'), - $pubmail_enabled + !empty($mailacct['pubmail']) ] ]; - } - Hook::callAll('jot_networks', $jotnets_fields); + } } + Hook::callAll('jot_networks', $jotnets_fields); } $acl_contacts = self::getContactListByUserId($user['uid'], $condition); - $acl_groups = self::getGroupListByUserId($user['uid']); + $acl_circles = self::getCircleListByUserId($user['uid']); - $acl_list = array_merge($acl_groups, $acl_contacts); + $acl_list = array_merge($acl_circles, $acl_contacts); $input_names = [ 'visibility' => $form_prefix ? $form_prefix . '[visibility]' : 'visibility', - 'group_allow' => $form_prefix ? $form_prefix . '[group_allow]' : 'group_allow', + 'circle_allow' => $form_prefix ? $form_prefix . '[circle_allow]' : 'circle_allow', 'contact_allow' => $form_prefix ? $form_prefix . '[contact_allow]' : 'contact_allow', - 'group_deny' => $form_prefix ? $form_prefix . '[group_deny]' : 'group_deny', + 'circle_deny' => $form_prefix ? $form_prefix . '[circle_deny]' : 'circle_deny', 'contact_deny' => $form_prefix ? $form_prefix . '[contact_deny]' : 'contact_deny', 'emailcc' => $form_prefix ? $form_prefix . '[emailcc]' : 'emailcc', ]; - $tpl = Renderer::getMarkupTemplate('acl_selector.tpl'); + $tpl = Renderer::getMarkupTemplate('acl/full_selector.tpl'); $o = Renderer::replaceMacros($tpl, [ '$public_title' => DI::l10n()->t('Public'), '$public_desc' => DI::l10n()->t('This content will be shown to all your followers and can be seen in the community pages and by anyone with its link.'), '$custom_title' => DI::l10n()->t('Limited/Private'), - '$custom_desc' => DI::l10n()->t('This content will be shown only to the people in the first box, to the exception of the people mentioned in the second box. It won\'t appear anywhere public.'), + '$custom_desc' => DI::l10n()->t('This content will be shown only to the people in the first box, to the exception of the people mentioned in the second box. It won\'t appear anywhere public.') . DI::l10n()->t('Start typing the name of a contact or a circle to show a filtered list. You can also mention the special circles "Followers" and "Mutuals".'), '$allow_label' => DI::l10n()->t('Show to:'), '$deny_label' => DI::l10n()->t('Except to:'), '$emailcc' => DI::l10n()->t('CC: email addresses'), '$emtitle' => DI::l10n()->t('Example: bob@example.com, mary@example.com'), '$jotnets_summary' => DI::l10n()->t('Connectors'), - '$jotnets_disabled_label' => DI::l10n()->t('Connectors disabled, since "%s" is enabled.', DI::l10n()->t('Hide your profile details from unknown viewers?')), '$visibility' => $visibility, - '$acl_contacts' => $acl_contacts, - '$acl_groups' => $acl_groups, - '$acl_list' => $acl_list, + '$acl_contacts' => json_encode($acl_contacts), + '$acl_circles' => json_encode($acl_circles), + '$acl_list' => json_encode($acl_list), '$contact_allow' => implode(',', $default_permissions['allow_cid']), - '$group_allow' => implode(',', $default_permissions['allow_gid']), + '$circle_allow' => implode(',', $default_permissions['allow_gid']), '$contact_deny' => implode(',', $default_permissions['deny_cid']), - '$group_deny' => implode(',', $default_permissions['deny_gid']), + '$circle_deny' => implode(',', $default_permissions['deny_gid']), '$for_federation' => $for_federation, '$jotnets_fields' => $jotnets_fields, - '$user_hidewall' => $default_permissions['hidewall'], '$input_names' => $input_names, '$input_group_id' => $input_group_id, ]); return $o; } + + /** + * Checks the validity of the given ACL string + * + * @param string $acl_string + * @param int $uid + * @return bool + * @throws Exception + */ + public static function isValidContact($acl_string, $uid) + { + if (empty($acl_string)) { + return true; + } + + // split into array of cids + preg_match_all('/<[A-Za-z0-9]+>/', $acl_string, $array); + + // check for each cid if the contact is valid for the given user + $cid_array = $array[0]; + foreach ($cid_array as $cid) { + $cid = str_replace(['<', '>'], ['', ''], $cid); + if (!DBA::exists('contact', ['id' => $cid, 'uid' => $uid])) { + return false; + } + } + + return true; + } + + /** + * Checks the validity of the given ACL string + * + * @param string $acl_string + * @param int $uid + * @return bool + * @throws Exception + */ + public static function isValidCircle($acl_string, $uid) + { + if (empty($acl_string)) { + return true; + } + + // split into array of cids + preg_match_all('/<[A-Za-z0-9]+>/', $acl_string, $array); + + // check for each cid if the contact is valid for the given user + $gid_array = $array[0]; + foreach ($gid_array as $gid) { + $gid = str_replace(['<', '>'], ['', ''], $gid); + if (!DBA::exists('circle', ['id' => $gid, 'uid' => $uid, 'deleted' => false])) { + return false; + } + } + + return true; + } }