summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2021-03-09 21:48:48 +0100
committerJoas Schilling <coding@schilljs.com>2021-03-10 17:19:55 +0100
commit236aa194e2704454aa0b21228773071e3223a719 (patch)
tree66286ecdfc6577eb3c51fb532de0b53c306160d0 /lib
parentb71268e38b96e69057824e0eeb8f937ad015a927 (diff)
downloadnextcloud-server-236aa194e2704454aa0b21228773071e3223a719.tar.gz
nextcloud-server-236aa194e2704454aa0b21228773071e3223a719.zip
Restrict autocompletion also based on the phonebook known users
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php33
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php29
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php106
-rw-r--r--lib/private/Share20/Manager.php5
-rw-r--r--lib/public/Share/IManager.php8
5 files changed, 126 insertions, 55 deletions
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
index 7bdd29afc4e..7da8cede6aa 100644
--- a/lib/private/Collaboration/Collaborators/MailPlugin.php
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -27,6 +27,7 @@
namespace OC\Collaboration\Collaborators;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
@@ -40,8 +41,14 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class MailPlugin implements ISearchPlugin {
- protected $shareeEnumeration;
+ /* @var bool */
protected $shareWithGroupOnly;
+ /* @var bool */
+ protected $shareeEnumeration;
+ /* @var bool */
+ protected $shareeEnumerationInGroupOnly;
+ /* @var bool */
+ protected $shareeEnumerationPhone;
/** @var IManager */
private $contactsManager;
@@ -52,20 +59,28 @@ class MailPlugin implements ISearchPlugin {
/** @var IGroupManager */
private $groupManager;
-
+ /** @var KnownUserService */
+ private $knownUserService;
/** @var IUserSession */
private $userSession;
- public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IGroupManager $groupManager, IUserSession $userSession) {
+ public function __construct(IManager $contactsManager,
+ ICloudIdManager $cloudIdManager,
+ IConfig $config,
+ IGroupManager $groupManager,
+ KnownUserService $knownUserService,
+ IUserSession $userSession) {
$this->contactsManager = $contactsManager;
$this->cloudIdManager = $cloudIdManager;
$this->config = $config;
$this->groupManager = $groupManager;
+ $this->knownUserService = $knownUserService;
$this->userSession = $userSession;
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
}
/**
@@ -77,6 +92,8 @@ class MailPlugin implements ISearchPlugin {
* @since 13.0.0
*/
public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $currentUserId = $this->userSession->getUser()->getUID();
+
$result = $userResults = ['wide' => [], 'exact' => []];
$userType = new SearchResultType('users');
$emailType = new SearchResultType('emails');
@@ -152,8 +169,12 @@ class MailPlugin implements ISearchPlugin {
continue;
}
- $addToWide = !$this->shareeEnumerationInGroupOnly;
- if ($this->shareeEnumerationInGroupOnly) {
+ $addToWide = !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone);
+ if (!$addToWide && $this->shareeEnumerationPhone && $this->knownUserService->isKnownToUser($currentUserId, $contact['UID'])) {
+ $addToWide = true;
+ }
+
+ if (!$addToWide && $this->shareeEnumerationInGroupOnly) {
$addToWide = false;
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
foreach ($userGroups as $userGroup) {
@@ -181,7 +202,7 @@ class MailPlugin implements ISearchPlugin {
}
if ($exactEmailMatch
- || isset($contact['FN']) && strtolower($contact['FN']) === $lowerSearch) {
+ || (isset($contact['FN']) && strtolower($contact['FN']) === $lowerSearch)) {
if ($exactEmailMatch) {
$searchResult->markExactIdMatch($emailType);
}
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
index d832a42000c..5114ccd8eb5 100644
--- a/lib/private/Collaboration/Collaborators/UserPlugin.php
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -32,6 +32,7 @@
namespace OC\Collaboration\Collaborators;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
@@ -46,8 +47,12 @@ use OCP\UserStatus\IManager as IUserStatusManager;
class UserPlugin implements ISearchPlugin {
/* @var bool */
protected $shareWithGroupOnly;
+ /* @var bool */
protected $shareeEnumeration;
+ /* @var bool */
protected $shareeEnumerationInGroupOnly;
+ /* @var bool */
+ protected $shareeEnumerationPhone;
/** @var IConfig */
private $config;
@@ -57,33 +62,29 @@ class UserPlugin implements ISearchPlugin {
private $userSession;
/** @var IUserManager */
private $userManager;
+ /** @var KnownUserService */
+ private $knownUserService;
/** @var IUserStatusManager */
private $userStatusManager;
- /**
- * UserPlugin constructor.
- *
- * @param IConfig $config
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param IUserSession $userSession
- * @param IUserStatusManager $userStatusManager
- */
public function __construct(IConfig $config,
IUserManager $userManager,
IGroupManager $groupManager,
IUserSession $userSession,
+ KnownUserService $knownUserService,
IUserStatusManager $userStatusManager) {
$this->config = $config;
$this->groupManager = $groupManager;
$this->userSession = $userSession;
$this->userManager = $userManager;
+ $this->knownUserService = $knownUserService;
$this->userStatusManager = $userStatusManager;
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
}
public function search($search, $limit, $offset, ISearchResult $searchResult) {
@@ -91,6 +92,7 @@ class UserPlugin implements ISearchPlugin {
$users = [];
$hasMoreResults = false;
+ $currentUserId = $this->userSession->getUser()->getUID();
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
if ($this->shareWithGroupOnly) {
// Search in all the groups this user is part of
@@ -168,11 +170,16 @@ class UserPlugin implements ISearchPlugin {
];
} else {
$addToWideResults = false;
- if ($this->shareeEnumeration && !$this->shareeEnumerationInGroupOnly) {
+ if ($this->shareeEnumeration &&
+ !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) {
+ $addToWideResults = true;
+ }
+
+ if ($this->shareeEnumerationPhone && $this->knownUserService->isKnownToUser($currentUserId, $user->getUID())) {
$addToWideResults = true;
}
- if ($this->shareeEnumerationInGroupOnly) {
+ if (!$addToWideResults && $this->shareeEnumerationInGroupOnly) {
$commonGroups = array_intersect($currentUserGroups, $this->groupManager->getUserGroupIds($user));
if (!empty($commonGroups)) {
$addToWideResults = true;
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index e2bd7edc63d..852765506c0 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -31,6 +31,7 @@
namespace OC\Contacts\ContactsMenu;
+use OC\KnownUser\KnownUserService;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
@@ -53,20 +54,19 @@ class ContactsStore implements IContactsStore {
/** @var IGroupManager */
private $groupManager;
- /**
- * @param IManager $contactsManager
- * @param IConfig $config
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- */
+ /** @var KnownUserService */
+ private $knownUserService;
+
public function __construct(IManager $contactsManager,
IConfig $config,
IUserManager $userManager,
- IGroupManager $groupManager) {
+ IGroupManager $groupManager,
+ KnownUserService $knownUserService) {
$this->contactsManager = $contactsManager;
$this->config = $config;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
+ $this->knownUserService = $knownUserService;
}
/**
@@ -103,7 +103,7 @@ class ContactsStore implements IContactsStore {
}
/**
- * Filters the contacts. Applies 3 filters:
+ * Filters the contacts. Applied filters:
* 1. filter the current user
* 2. if the `shareapi_allow_share_dialog_user_enumeration` config option is
* enabled it will filter all local users
@@ -122,20 +122,21 @@ class ContactsStore implements IContactsStore {
array $entries,
$filter) {
$disallowEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') !== 'yes';
- $restrictEnumeration = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $restrictEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $restrictEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes';
// whether to filter out local users
$skipLocal = false;
- // whether to filter out all users which doesn't have the same group as the current user
- $ownGroupsOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes' || $restrictEnumeration;
+ // whether to filter out all users which don't have a common group as the current user
+ $ownGroupsOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$selfGroups = $this->groupManager->getUserGroupIds($self);
if ($excludedGroups) {
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$decodedExcludeGroups = json_decode($excludedGroups, true);
- $excludeGroupsList = ($decodedExcludeGroups !== null) ? $decodedExcludeGroups : [];
+ $excludeGroupsList = $decodedExcludeGroups ?? [];
if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) {
// a group of the current user is excluded -> filter all local users
@@ -145,47 +146,76 @@ class ContactsStore implements IContactsStore {
$selfUID = $self->getUID();
- return array_values(array_filter($entries, function (IEntry $entry) use ($self, $skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $filter) {
- if ($skipLocal && $entry->getProperty('isLocalSystemBook') === true) {
+ return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $filter) {
+ if ($entry->getProperty('UID') === $selfUID) {
return false;
}
- // Prevent enumerating local users
- if ($disallowEnumeration && $entry->getProperty('isLocalSystemBook')) {
- $filterUser = true;
+ if ($entry->getProperty('isLocalSystemBook')) {
+ if ($skipLocal) {
+ return false;
+ }
+
+ $checkedCommonGroupAlready = false;
+
+ // Prevent enumerating local users
+ if ($disallowEnumeration) {
+ $filterUser = true;
- $mailAddresses = $entry->getEMailAddresses();
- foreach ($mailAddresses as $mailAddress) {
- if ($mailAddress === $filter) {
+ $mailAddresses = $entry->getEMailAddresses();
+ foreach ($mailAddresses as $mailAddress) {
+ if ($mailAddress === $filter) {
+ $filterUser = false;
+ break;
+ }
+ }
+
+ if ($entry->getProperty('UID') && $entry->getProperty('UID') === $filter) {
$filterUser = false;
- break;
}
- }
- if ($entry->getProperty('UID') && $entry->getProperty('UID') === $filter) {
- $filterUser = false;
- }
+ if ($filterUser) {
+ return false;
+ }
+ } elseif ($restrictEnumerationPhone || $restrictEnumerationGroup) {
+ $canEnumerate = false;
+ if ($restrictEnumerationPhone) {
+ $canEnumerate = $this->knownUserService->isKnownToUser($selfUID, $entry->getProperty('UID'));
+ }
- if ($filterUser) {
- return false;
- }
- }
+ if (!$canEnumerate && $restrictEnumerationGroup) {
+ $user = $this->userManager->get($entry->getProperty('UID'));
- if ($ownGroupsOnly && $entry->getProperty('isLocalSystemBook') === true) {
- $uid = $this->userManager->get($entry->getProperty('UID'));
+ if ($user === null) {
+ return false;
+ }
- if ($uid === null) {
- return false;
+ $contactGroups = $this->groupManager->getUserGroupIds($user);
+ $canEnumerate = !empty(array_intersect($contactGroups, $selfGroups));
+ $checkedCommonGroupAlready = true;
+ }
+
+ if (!$canEnumerate) {
+ return false;
+ }
}
- $contactGroups = $this->groupManager->getUserGroupIds($uid);
- if (count(array_intersect($contactGroups, $selfGroups)) === 0) {
- // no groups in common, so shouldn't see the contact
- return false;
+ if ($ownGroupsOnly && !$checkedCommonGroupAlready) {
+ $user = $this->userManager->get($entry->getProperty('UID'));
+
+ if ($user === null) {
+ return false;
+ }
+
+ $contactGroups = $this->groupManager->getUserGroupIds($user);
+ if (empty(array_intersect($contactGroups, $selfGroups))) {
+ // no groups in common, so shouldn't see the contact
+ return false;
+ }
}
}
- return $entry->getProperty('UID') !== $selfUID;
+ return true;
}));
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 5c8dba5915a..6e072740884 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -1829,6 +1829,11 @@ class Manager implements IManager {
$this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
}
+ public function limitEnumerationToPhone(): bool {
+ return $this->allowEnumeration() &&
+ $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
+ }
+
/**
* Copied from \OC_Util::isSharingDisabledForUser
*
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 635ccc1483d..0c8732b4b15 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -385,6 +385,14 @@ interface IManager {
public function limitEnumerationToGroups(): bool;
/**
+ * Check if user enumeration is limited to the phonebook matches
+ *
+ * @return bool
+ * @since 21.0.1
+ */
+ public function limitEnumerationToPhone(): bool;
+
+ /**
* Check if sharing is disabled for the given user
*
* @param string $userId