take out support for parallel search
* it is undocumented in PHP documentation
* since it does not work with paged search, we do not take advantage of it
as of c868892d2d
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
21671d5cb5
commit
f5cd138768
|
@ -97,6 +97,8 @@ class Access extends LDAPUtility {
|
||||||
private $config;
|
private $config;
|
||||||
/** @var IUserManager */
|
/** @var IUserManager */
|
||||||
private $ncUserManager;
|
private $ncUserManager;
|
||||||
|
/** @var ILogger */
|
||||||
|
private $logger;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Connection $connection,
|
Connection $connection,
|
||||||
|
@ -113,6 +115,7 @@ class Access extends LDAPUtility {
|
||||||
$this->helper = $helper;
|
$this->helper = $helper;
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->ncUserManager = $ncUserManager;
|
$this->ncUserManager = $ncUserManager;
|
||||||
|
$this->logger = \OC::$server->getLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,27 +261,18 @@ class Access extends LDAPUtility {
|
||||||
* @param string $attribute
|
* @param string $attribute
|
||||||
* @param string $filter
|
* @param string $filter
|
||||||
* @param int $maxResults
|
* @param int $maxResults
|
||||||
* @return array|bool false if there was any error, true if an exists check
|
* @return array|bool false if there was any error
|
||||||
* was performed and the requested DN found, array with the
|
|
||||||
* returned data on a successful usual operation
|
|
||||||
* @throws ServerNotAvailableException
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function executeRead($cr, $dn, $attribute, $filter, $maxResults) {
|
public function executeRead($cr, string $dn, string $attribute, string $filter, int $maxResults) {
|
||||||
$this->initPagedSearch($filter, array($dn), array($attribute), $maxResults, 0);
|
$this->initPagedSearch($filter, $dn, [$attribute], $maxResults, 0);
|
||||||
$dn = $this->helper->DNasBaseParameter($dn);
|
$dn = $this->helper->DNasBaseParameter($dn);
|
||||||
$rr = @$this->invokeLDAPMethod('read', $cr, $dn, $filter, array($attribute));
|
$rr = @$this->invokeLDAPMethod('read', $cr, $dn, $filter, [$attribute]);
|
||||||
if (!$this->ldap->isResource($rr)) {
|
if (!$this->ldap->isResource($rr)) {
|
||||||
if ($attribute !== '') {
|
$this->logger->debug('readAttribute failed for DN {dn}', ['app' => 'user_ldap', 'dn' => $dn]);
|
||||||
//do not throw this message on userExists check, irritates
|
|
||||||
\OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN ' . $dn, ILogger::DEBUG);
|
|
||||||
}
|
|
||||||
//in case an error occurs , e.g. object does not exist
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($attribute === '' && ($filter === 'objectclass=*' || $this->invokeLDAPMethod('countEntries', $cr, $rr) === 1)) {
|
|
||||||
\OCP\Util::writeLog('user_ldap', 'readAttribute: ' . $dn . ' found', ILogger::DEBUG);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$er = $this->invokeLDAPMethod('firstEntry', $cr, $rr);
|
$er = $this->invokeLDAPMethod('firstEntry', $cr, $rr);
|
||||||
if (!$this->ldap->isResource($er)) {
|
if (!$this->ldap->isResource($er)) {
|
||||||
//did not match the filter, return false
|
//did not match the filter, return false
|
||||||
|
@ -291,6 +285,25 @@ class Access extends LDAPUtility {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks whether a record identified by a DN is present on LDAP
|
||||||
|
*
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
|
*/
|
||||||
|
public function isRecordOnLDAP(string $dn, string $filter = 'objectclass=*'): bool {
|
||||||
|
$this->abandonPagedSearch();
|
||||||
|
$attribute = ['']; // best suited for existence checks
|
||||||
|
$this->initPagedSearch($filter, $dn, $attribute, 1, 0);
|
||||||
|
$dn = $this->helper->DNasBaseParameter($dn);
|
||||||
|
$rr = @$this->invokeLDAPMethod('read', $this->connection->getConnectionResource(), $dn, $filter, $attribute);
|
||||||
|
$isAvailable = $this->ldap->isResource($rr);
|
||||||
|
$this->logger->debug(
|
||||||
|
'existence check for DN {dn} resulted in {result}',
|
||||||
|
['app' => 'user_ldap', 'dn' => $dn, 'result' => $isAvailable]
|
||||||
|
);
|
||||||
|
return $isAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes a result grom getAttributes(), i.e. handles DNs and binary
|
* Normalizes a result grom getAttributes(), i.e. handles DNs and binary
|
||||||
* data if present.
|
* data if present.
|
||||||
|
@ -474,11 +487,9 @@ class Access extends LDAPUtility {
|
||||||
* filter by doing read operations against the group entries. Returns an
|
* filter by doing read operations against the group entries. Returns an
|
||||||
* array of DNs that match the filter.
|
* array of DNs that match the filter.
|
||||||
*
|
*
|
||||||
* @param string[] $groupDNs
|
|
||||||
* @return string[]
|
|
||||||
* @throws ServerNotAvailableException
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function groupsMatchFilter($groupDNs) {
|
public function groupsMatchFilter(array $groupDNs): array {
|
||||||
$validGroupDNs = [];
|
$validGroupDNs = [];
|
||||||
foreach($groupDNs as $dn) {
|
foreach($groupDNs as $dn) {
|
||||||
$cacheKey = 'groupsMatchFilter-'.$dn;
|
$cacheKey = 'groupsMatchFilter-'.$dn;
|
||||||
|
@ -497,8 +508,7 @@ class Access extends LDAPUtility {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->readAttribute($dn, '', $this->connection->ldapGroupFilter);
|
if($this->isRecordOnLDAP($dn, $this->connection->ldapGroupFilter)) {
|
||||||
if(is_array($result)) {
|
|
||||||
$this->connection->writeToCache($cacheKey, true);
|
$this->connection->writeToCache($cacheKey, true);
|
||||||
$validGroupDNs[] = $dn;
|
$validGroupDNs[] = $dn;
|
||||||
} else {
|
} else {
|
||||||
|
@ -966,18 +976,18 @@ class Access extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* executes an LDAP search, optimized for Users
|
* executes an LDAP search, optimized for Users
|
||||||
|
*
|
||||||
* @param string $filter the LDAP filter for the search
|
* @param string $filter the LDAP filter for the search
|
||||||
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
||||||
* @param integer $limit
|
* @param integer $limit
|
||||||
* @param integer $offset
|
* @param integer $offset
|
||||||
* @return array with the search result
|
* @return array with the search result
|
||||||
*
|
* @throws ServerNotAvailableException
|
||||||
* Executes an LDAP search
|
|
||||||
*/
|
*/
|
||||||
public function searchUsers($filter, $attr = null, $limit = null, $offset = null) {
|
public function searchUsers(string $filter, $attr = null, int $limit = null, int $offset = null): array {
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach($this->connection->ldapBaseUsers as $base) {
|
foreach($this->connection->ldapBaseUsers as $base) {
|
||||||
$result = array_merge($result, $this->search($filter, [$base], $attr, $limit, $offset));
|
$result = array_merge($result, $this->search($filter, $base, $attr, $limit, $offset));
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -987,12 +997,13 @@ class Access extends LDAPUtility {
|
||||||
* @param string|string[] $attr
|
* @param string|string[] $attr
|
||||||
* @param int $limit
|
* @param int $limit
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @return false|int
|
* @return bool|int
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function countUsers($filter, $attr = array('dn'), $limit = null, $offset = null) {
|
public function countUsers(string $filter, $attr = ['dn'], int $limit = null, int $offset = null) {
|
||||||
$result = false;
|
$result = false;
|
||||||
foreach($this->connection->ldapBaseUsers as $base) {
|
foreach($this->connection->ldapBaseUsers as $base) {
|
||||||
$count = $this->count($filter, [$base], $attr, $limit, $offset);
|
$count = $this->count($filter, $base, $attr, $limit, $offset);
|
||||||
$result = is_int($count) ? (int)$result + $count : $result;
|
$result = is_int($count) ? (int)$result + $count : $result;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -1000,6 +1011,7 @@ class Access extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* executes an LDAP search, optimized for Groups
|
* executes an LDAP search, optimized for Groups
|
||||||
|
*
|
||||||
* @param string $filter the LDAP filter for the search
|
* @param string $filter the LDAP filter for the search
|
||||||
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
||||||
* @param integer $limit
|
* @param integer $limit
|
||||||
|
@ -1007,27 +1019,26 @@ class Access extends LDAPUtility {
|
||||||
* @return array with the search result
|
* @return array with the search result
|
||||||
*
|
*
|
||||||
* Executes an LDAP search
|
* Executes an LDAP search
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function searchGroups($filter, $attr = null, $limit = null, $offset = null) {
|
public function searchGroups(string $filter, $attr = null, int $limit = null, int $offset = null): array {
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach($this->connection->ldapBaseGroups as $base) {
|
foreach($this->connection->ldapBaseGroups as $base) {
|
||||||
$result = array_merge($result, $this->search($filter, [$base], $attr, $limit, $offset));
|
$result = array_merge($result, $this->search($filter, $base, $attr, $limit, $offset));
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the number of available groups
|
* returns the number of available groups
|
||||||
* @param string $filter the LDAP search filter
|
*
|
||||||
* @param string[] $attr optional
|
|
||||||
* @param int|null $limit
|
|
||||||
* @param int|null $offset
|
|
||||||
* @return int|bool
|
* @return int|bool
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function countGroups($filter, $attr = array('dn'), $limit = null, $offset = null) {
|
public function countGroups(string $filter, array $attr = ['dn'], int $limit = null, int $offset = null) {
|
||||||
$result = false;
|
$result = false;
|
||||||
foreach($this->connection->ldapBaseGroups as $base) {
|
foreach($this->connection->ldapBaseGroups as $base) {
|
||||||
$count = $this->count($filter, [$base], $attr, $limit, $offset);
|
$count = $this->count($filter, $base, $attr, $limit, $offset);
|
||||||
$result = is_int($count) ? (int)$result + $count : $result;
|
$result = is_int($count) ? (int)$result + $count : $result;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -1036,14 +1047,14 @@ class Access extends LDAPUtility {
|
||||||
/**
|
/**
|
||||||
* returns the number of available objects on the base DN
|
* returns the number of available objects on the base DN
|
||||||
*
|
*
|
||||||
* @param int|null $limit
|
|
||||||
* @param int|null $offset
|
|
||||||
* @return int|bool
|
* @return int|bool
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function countObjects($limit = null, $offset = null) {
|
public function countObjects(int $limit = null, int $offset = null) {
|
||||||
$result = false;
|
$result = false;
|
||||||
foreach($this->connection->ldapBase as $base) {
|
foreach($this->connection->ldapBase as $base) {
|
||||||
$count = $this->count('objectclass=*', [$base], ['dn'], $limit, $offset);
|
/** @noinspection SpellCheckingInspection */
|
||||||
|
$count = $this->count('objectclass=*', $base, ['dn'], $limit, $offset);
|
||||||
$result = is_int($count) ? (int)$result + $count : $result;
|
$result = is_int($count) ? (int)$result + $count : $result;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -1073,27 +1084,26 @@ class Access extends LDAPUtility {
|
||||||
if ($command == 'controlPagedResultResponse') {
|
if ($command == 'controlPagedResultResponse') {
|
||||||
throw new \InvalidArgumentException('Invoker does not support controlPagedResultResponse, call LDAP Wrapper directly instead.');
|
throw new \InvalidArgumentException('Invoker does not support controlPagedResultResponse, call LDAP Wrapper directly instead.');
|
||||||
} else {
|
} else {
|
||||||
return call_user_func_array(array($this->ldap, $command), $arguments);
|
return call_user_func_array([$this->ldap, $command], $arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
$ret = $doMethod();
|
$ret = $doMethod();
|
||||||
} catch (ServerNotAvailableException $e) {
|
} /** @noinspection PhpRedundantCatchClauseInspection */
|
||||||
|
catch (ServerNotAvailableException $e) {
|
||||||
/* Server connection lost, attempt to reestablish it
|
/* Server connection lost, attempt to reestablish it
|
||||||
* Maybe implement exponential backoff?
|
* Maybe implement exponential backoff?
|
||||||
* This was enough to get solr indexer working which has large delays between LDAP fetches.
|
* This was enough to get solr indexer working which has large delays between LDAP fetches.
|
||||||
*/
|
*/
|
||||||
\OCP\Util::writeLog('user_ldap', "Connection lost on $command, attempting to reestablish.", ILogger::DEBUG);
|
$this->logger->debug('Connection lost on {command}, , attempting to reestablish', ['app' => 'user_ldap', 'command' => $command]);
|
||||||
$this->connection->resetConnectionResource();
|
$this->connection->resetConnectionResource();
|
||||||
$cr = $this->connection->getConnectionResource();
|
$cr = $this->connection->getConnectionResource();
|
||||||
|
|
||||||
if(!$this->ldap->isResource($cr)) {
|
if(!$this->ldap->isResource($cr)) {
|
||||||
// Seems like we didn't find any resource.
|
$this->logger->debug('Could not {command}, because resource is missing', ['app' => 'user_ldap', 'command' => $command]);
|
||||||
\OCP\Util::writeLog('user_ldap', "Could not $command, because resource is missing.", ILogger::DEBUG);
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
$arguments[0] = array_pad([], count($arguments[0]), $cr);
|
|
||||||
$ret = $doMethod();
|
$ret = $doMethod();
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
|
@ -1102,8 +1112,8 @@ class Access extends LDAPUtility {
|
||||||
/**
|
/**
|
||||||
* retrieved. Results will according to the order in the array.
|
* retrieved. Results will according to the order in the array.
|
||||||
*
|
*
|
||||||
* @param $filter
|
* @param string $filter
|
||||||
* @param $base
|
* @param string $base
|
||||||
* @param string[]|string|null $attr
|
* @param string[]|string|null $attr
|
||||||
* @param int $limit optional, maximum results to be counted
|
* @param int $limit optional, maximum results to be counted
|
||||||
* @param int $offset optional, a starting point
|
* @param int $offset optional, a starting point
|
||||||
|
@ -1111,9 +1121,9 @@ class Access extends LDAPUtility {
|
||||||
* second | false if not successful
|
* second | false if not successful
|
||||||
* @throws ServerNotAvailableException
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
private function executeSearch($filter, $base, &$attr = null, $limit = null, $offset = null) {
|
private function executeSearch(string $filter, string $base, &$attr = null, int $limit = null, int $offset = null) {
|
||||||
if(!is_null($attr) && !is_array($attr)) {
|
if(!is_null($attr) && !is_array($attr)) {
|
||||||
$attr = array(mb_strtolower($attr, 'UTF-8'));
|
$attr = [mb_strtolower($attr, 'UTF-8')];
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we have a resource, in case not cancel with message
|
// See if we have a resource, in case not cancel with message
|
||||||
|
@ -1121,30 +1131,30 @@ class Access extends LDAPUtility {
|
||||||
if(!$this->ldap->isResource($cr)) {
|
if(!$this->ldap->isResource($cr)) {
|
||||||
// Seems like we didn't find any resource.
|
// Seems like we didn't find any resource.
|
||||||
// Return an empty array just like before.
|
// Return an empty array just like before.
|
||||||
\OCP\Util::writeLog('user_ldap', 'Could not search, because resource is missing.', ILogger::DEBUG);
|
$this->logger->debug('Could not search, because resource is missing', ['app' => 'user_ldap']);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check whether paged search should be attempted
|
//check whether paged search should be attempted
|
||||||
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, (int)$limit, $offset);
|
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, (int)$limit, $offset);
|
||||||
|
|
||||||
$linkResources = array_pad(array(), count($base), $cr);
|
$sr = $this->invokeLDAPMethod('search', $cr, $base, $filter, $attr);
|
||||||
$sr = $this->invokeLDAPMethod('search', $linkResources, $base, $filter, $attr);
|
|
||||||
// cannot use $cr anymore, might have changed in the previous call!
|
// cannot use $cr anymore, might have changed in the previous call!
|
||||||
$error = $this->ldap->errno($this->connection->getConnectionResource());
|
$error = $this->ldap->errno($this->connection->getConnectionResource());
|
||||||
if(!is_array($sr) || $error !== 0) {
|
if(!$this->ldap->isResource($sr) || $error !== 0) {
|
||||||
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), ILogger::ERROR);
|
$this->logger->debug('Attempt for Paging? {status}', ['app' => 'user_ldap', 'status' => $pagedSearchOK]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($sr, $pagedSearchOK);
|
return [$sr, $pagedSearchOK];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* processes an LDAP paged search operation
|
* processes an LDAP paged search operation
|
||||||
* @param array $sr the array containing the LDAP search resources
|
*
|
||||||
|
* @param resource $sr the array containing the LDAP search resources
|
||||||
* @param string $filter the LDAP filter for the search
|
* @param string $filter the LDAP filter for the search
|
||||||
* @param array $base an array containing the LDAP subtree(s) that shall be searched
|
* @param string $base an array containing the LDAP subtree(s) that shall be searched
|
||||||
* @param int $iFoundItems number of results in the single search operation
|
* @param int $iFoundItems number of results in the single search operation
|
||||||
* @param int $limit maximum results to be counted
|
* @param int $limit maximum results to be counted
|
||||||
* @param int $offset a starting point
|
* @param int $offset a starting point
|
||||||
|
@ -1152,15 +1162,14 @@ class Access extends LDAPUtility {
|
||||||
* @param bool $skipHandling required for paged search when cookies to
|
* @param bool $skipHandling required for paged search when cookies to
|
||||||
* prior results need to be gained
|
* prior results need to be gained
|
||||||
* @return bool cookie validity, true if we have more pages, false otherwise.
|
* @return bool cookie validity, true if we have more pages, false otherwise.
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
private function processPagedSearchStatus($sr, $filter, $base, $iFoundItems, $limit, $offset, $pagedSearchOK, $skipHandling) {
|
private function processPagedSearchStatus($sr, string $filter, string $base, int $iFoundItems, int $limit, $offset, bool $pagedSearchOK, bool $skipHandling): bool {
|
||||||
$cookie = null;
|
$cookie = null;
|
||||||
if($pagedSearchOK) {
|
if($pagedSearchOK) {
|
||||||
$cr = $this->connection->getConnectionResource();
|
$cr = $this->connection->getConnectionResource();
|
||||||
foreach($sr as $key => $res) {
|
if($this->ldap->controlPagedResultResponse($cr, $sr, $cookie)) {
|
||||||
if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) {
|
$this->setPagedResultCookie($base, $filter, $limit, $offset, $cookie);
|
||||||
$this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//browsing through prior pages to get the cookie for the new one
|
//browsing through prior pages to get the cookie for the new one
|
||||||
|
@ -1175,10 +1184,7 @@ class Access extends LDAPUtility {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!is_null($limit) && (int)$this->connection->ldapPagingSize !== 0) {
|
if(!is_null($limit) && (int)$this->connection->ldapPagingSize !== 0) {
|
||||||
\OC::$server->getLogger()->debug(
|
$this->logger->debug('Paged search was not available', ['app' => 'user_ldap']);
|
||||||
'Paged search was not available',
|
|
||||||
[ 'app' => 'user_ldap' ]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ++ Fixing RHDS searches with pages with zero results ++
|
/* ++ Fixing RHDS searches with pages with zero results ++
|
||||||
|
@ -1203,8 +1209,8 @@ class Access extends LDAPUtility {
|
||||||
* @return int|false Integer or false if the search could not be initialized
|
* @return int|false Integer or false if the search could not be initialized
|
||||||
* @throws ServerNotAvailableException
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
|
private function count(string $filter, string $base, $attr = null, int $limit = null, int $offset = null, bool $skipHandling = false) {
|
||||||
\OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), ILogger::DEBUG);
|
$this->logger->debug('Count filter: {filter}', ['app' => 'user_ldap', 'filter' => $filter]);
|
||||||
|
|
||||||
$limitPerPage = (int)$this->connection->ldapPagingSize;
|
$limitPerPage = (int)$this->connection->ldapPagingSize;
|
||||||
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
||||||
|
@ -1268,7 +1274,7 @@ class Access extends LDAPUtility {
|
||||||
* @return array with the search result
|
* @return array with the search result
|
||||||
* @throws ServerNotAvailableException
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function search($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
|
public function search(string $filter, string $base, $attr = null, int $limit = null, int $offset = null, bool $skipHandling = false): array {
|
||||||
$limitPerPage = (int)$this->connection->ldapPagingSize;
|
$limitPerPage = (int)$this->connection->ldapPagingSize;
|
||||||
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
||||||
$limitPerPage = $limit;
|
$limitPerPage = $limit;
|
||||||
|
@ -1281,7 +1287,7 @@ class Access extends LDAPUtility {
|
||||||
* $findings['count'] < $limit
|
* $findings['count'] < $limit
|
||||||
*/
|
*/
|
||||||
$findings = [];
|
$findings = [];
|
||||||
$savedoffset = $offset;
|
$savedOffset = $offset;
|
||||||
do {
|
do {
|
||||||
$search = $this->executeSearch($filter, $base, $attr, $limitPerPage, $offset);
|
$search = $this->executeSearch($filter, $base, $attr, $limitPerPage, $offset);
|
||||||
if($search === false) {
|
if($search === false) {
|
||||||
|
@ -1297,7 +1303,7 @@ class Access extends LDAPUtility {
|
||||||
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limitPerPage,
|
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limitPerPage,
|
||||||
$offset, $pagedSearchOK,
|
$offset, $pagedSearchOK,
|
||||||
$skipHandling);
|
$skipHandling);
|
||||||
return array();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$iFoundItems = 0;
|
$iFoundItems = 0;
|
||||||
|
@ -1312,13 +1318,13 @@ class Access extends LDAPUtility {
|
||||||
$skipHandling);
|
$skipHandling);
|
||||||
$offset += $limitPerPage;
|
$offset += $limitPerPage;
|
||||||
} while ($continue && $pagedSearchOK && ($limit === null || count($findings) < $limit));
|
} while ($continue && $pagedSearchOK && ($limit === null || count($findings) < $limit));
|
||||||
// reseting offset
|
// resetting offset
|
||||||
$offset = $savedoffset;
|
$offset = $savedOffset;
|
||||||
|
|
||||||
// if we're here, probably no connection resource is returned.
|
// if we're here, probably no connection resource is returned.
|
||||||
// to make Nextcloud behave nicely, we simply give back an empty array.
|
// to make Nextcloud behave nicely, we simply give back an empty array.
|
||||||
if(is_null($findings)) {
|
if(is_null($findings)) {
|
||||||
return array();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!is_null($attr)) {
|
if(!is_null($attr)) {
|
||||||
|
@ -1951,14 +1957,8 @@ class Access extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set a cookie for LDAP paged search run
|
* set a cookie for LDAP paged search run
|
||||||
* @param string $base a string with the base DN for the search
|
|
||||||
* @param string $filter the search filter to identify the correct search
|
|
||||||
* @param int $limit the limit (or 'pageSize'), to identify the correct search well
|
|
||||||
* @param int $offset the offset for the run search to identify the correct search really good
|
|
||||||
* @param string $cookie string containing the cookie returned by ldap_control_paged_result_response
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
private function setPagedResultCookie($base, $filter, $limit, $offset, $cookie) {
|
private function setPagedResultCookie(string $base, string $filter, int $limit, int $offset, string $cookie): void {
|
||||||
// allow '0' for 389ds
|
// allow '0' for 389ds
|
||||||
if(!empty($cookie) || $cookie === '0') {
|
if(!empty($cookie) || $cookie === '0') {
|
||||||
$cacheKey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . (int)$limit . '-' . (int)$offset;
|
$cacheKey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . (int)$limit . '-' . (int)$offset;
|
||||||
|
@ -1979,55 +1979,55 @@ class Access extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares a paged search, if possible
|
* Prepares a paged search, if possible
|
||||||
* @param string $filter the LDAP filter for the search
|
*
|
||||||
* @param string[] $bases an array containing the LDAP subtree(s) that shall be searched
|
* @throws ServerNotAvailableException
|
||||||
* @param string[] $attr optional, when a certain attribute shall be filtered outside
|
|
||||||
* @param int $limit
|
|
||||||
* @param int $offset
|
|
||||||
* @return bool|true
|
|
||||||
*/
|
*/
|
||||||
private function initPagedSearch($filter, $bases, $attr, $limit, $offset) {
|
private function initPagedSearch(string $filter, string $base, array $attr = null, int $limit = null, int $offset = null): bool {
|
||||||
$pagedSearchOK = false;
|
$pagedSearchOK = false;
|
||||||
if ($limit !== 0) {
|
if ($limit !== 0) {
|
||||||
$offset = (int)$offset; //can be null
|
$offset = (int)$offset; //can be null
|
||||||
\OCP\Util::writeLog('user_ldap',
|
$this->logger->debug(
|
||||||
'initializing paged search for Filter '.$filter.' base '.print_r($bases, true)
|
'initializing paged search for Filter {filter} base {base} attr {attr} limit {limit} offset {offset}',
|
||||||
.' attr '.print_r($attr, true). ' limit ' .$limit.' offset '.$offset,
|
[
|
||||||
ILogger::DEBUG);
|
'app' => 'user_ldap',
|
||||||
|
'filter' => $filter,
|
||||||
|
'base' => $base,
|
||||||
|
'attr' => $attr,
|
||||||
|
'limit' => $limit,
|
||||||
|
'offset' => $offset,
|
||||||
|
]
|
||||||
|
);
|
||||||
//get the cookie from the search for the previous search, required by LDAP
|
//get the cookie from the search for the previous search, required by LDAP
|
||||||
foreach($bases as $base) {
|
$cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset);
|
||||||
|
if(empty($cookie) && $cookie !== "0" && ($offset > 0)) {
|
||||||
|
// no cookie known from a potential previous search. We need
|
||||||
|
// to start from 0 to come to the desired page. cookie value
|
||||||
|
// of '0' is valid, because 389ds
|
||||||
|
$reOffset = ($offset - $limit) < 0 ? 0 : $offset - $limit;
|
||||||
|
$this->search($filter, $base, $attr, $limit, $reOffset, true);
|
||||||
$cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset);
|
$cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset);
|
||||||
if(empty($cookie) && $cookie !== "0" && ($offset > 0)) {
|
//still no cookie? obviously, the server does not like us. Let's skip paging efforts.
|
||||||
// no cookie known from a potential previous search. We need
|
// '0' is valid, because 389ds
|
||||||
// to start from 0 to come to the desired page. cookie value
|
//TODO: remember this, probably does not change in the next request...
|
||||||
// of '0' is valid, because 389ds
|
if(empty($cookie) && $cookie !== '0') {
|
||||||
$reOffset = ($offset - $limit) < 0 ? 0 : $offset - $limit;
|
$cookie = null;
|
||||||
$this->search($filter, array($base), $attr, $limit, $reOffset, true);
|
|
||||||
$cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset);
|
|
||||||
//still no cookie? obviously, the server does not like us. Let's skip paging efforts.
|
|
||||||
// '0' is valid, because 389ds
|
|
||||||
//TODO: remember this, probably does not change in the next request...
|
|
||||||
if(empty($cookie) && $cookie !== '0') {
|
|
||||||
$cookie = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(!is_null($cookie)) {
|
|
||||||
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
|
|
||||||
$this->abandonPagedSearch();
|
|
||||||
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult',
|
|
||||||
$this->connection->getConnectionResource(), $limit,
|
|
||||||
false, $cookie);
|
|
||||||
if(!$pagedSearchOK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
\OCP\Util::writeLog('user_ldap', 'Ready for a paged search', ILogger::DEBUG);
|
|
||||||
} else {
|
|
||||||
$e = new \Exception('No paged search possible, Limit '.$limit.' Offset '.$offset);
|
|
||||||
\OC::$server->getLogger()->logException($e, ['level' => ILogger::DEBUG]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if(!is_null($cookie)) {
|
||||||
|
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
|
||||||
|
$this->abandonPagedSearch();
|
||||||
|
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult',
|
||||||
|
$this->connection->getConnectionResource(), $limit,
|
||||||
|
false, $cookie);
|
||||||
|
if(!$pagedSearchOK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->logger->debug('Ready for a paged search', ['app' => 'user_ldap']);
|
||||||
|
} else {
|
||||||
|
$e = new \Exception('No paged search possible, Limit '.$limit.' Offset '.$offset);
|
||||||
|
$this->logger->logException($e, ['app' => 'user_ldap', 'level' => ILogger::DEBUG]);
|
||||||
|
}
|
||||||
|
|
||||||
/* ++ Fixing RHDS searches with pages with zero results ++
|
/* ++ Fixing RHDS searches with pages with zero results ++
|
||||||
* We coudn't get paged searches working with our RHDS for login ($limit = 0),
|
* We coudn't get paged searches working with our RHDS for login ($limit = 0),
|
||||||
* due to pages with zero results.
|
* due to pages with zero results.
|
||||||
|
|
|
@ -36,6 +36,11 @@ namespace OCA\User_LDAP;
|
||||||
/**
|
/**
|
||||||
* @property int ldapPagingSize holds an integer
|
* @property int ldapPagingSize holds an integer
|
||||||
* @property string ldapUserAvatarRule
|
* @property string ldapUserAvatarRule
|
||||||
|
* @property string ldapEmailAttribute
|
||||||
|
* @property string ldapUserDisplayName
|
||||||
|
* @property string ldapUserFilter
|
||||||
|
* @property string ldapGroupFilter
|
||||||
|
* @property string[] ldapBase
|
||||||
*/
|
*/
|
||||||
class Configuration {
|
class Configuration {
|
||||||
const AVATAR_PREFIX_DEFAULT = 'default';
|
const AVATAR_PREFIX_DEFAULT = 'default';
|
||||||
|
|
|
@ -45,12 +45,18 @@ use OCP\ILogger;
|
||||||
*
|
*
|
||||||
* @property string ldapHost
|
* @property string ldapHost
|
||||||
* @property string ldapPort holds the port number
|
* @property string ldapPort holds the port number
|
||||||
|
* @property string ldapLoginFilter
|
||||||
* @property string ldapUserFilter
|
* @property string ldapUserFilter
|
||||||
* @property string ldapUserDisplayName
|
* @property string ldapUserDisplayName
|
||||||
* @property string ldapUserDisplayName2
|
* @property string ldapUserDisplayName2
|
||||||
* @property string ldapUserAvatarRule
|
* @property string ldapUserAvatarRule
|
||||||
|
* @property string ldapGroupFilter
|
||||||
|
* @property string ldapGidNumber
|
||||||
|
* @property string ldapDynamicGroupMemberURL
|
||||||
* @property boolean turnOnPasswordChange
|
* @property boolean turnOnPasswordChange
|
||||||
|
* @property string[] ldapBase
|
||||||
* @property string[] ldapBaseUsers
|
* @property string[] ldapBaseUsers
|
||||||
|
* @property string[] ldapBaseGroups
|
||||||
* @property int|null ldapPagingSize holds an integer
|
* @property int|null ldapPagingSize holds an integer
|
||||||
* @property bool|mixed|void ldapGroupMemberAssocAttr
|
* @property bool|mixed|void ldapGroupMemberAssocAttr
|
||||||
* @property string ldapUuidUserAttribute
|
* @property string ldapUuidUserAttribute
|
||||||
|
@ -60,6 +66,7 @@ use OCP\ILogger;
|
||||||
* @property string ldapQuotaAttribute
|
* @property string ldapQuotaAttribute
|
||||||
* @property string ldapQuotaDefault
|
* @property string ldapQuotaDefault
|
||||||
* @property string ldapEmailAttribute
|
* @property string ldapEmailAttribute
|
||||||
|
* @property string ldapDefaultPPolicyDN
|
||||||
*/
|
*/
|
||||||
class Connection extends LDAPUtility {
|
class Connection extends LDAPUtility {
|
||||||
private $ldapConnectionRes = null;
|
private $ldapConnectionRes = null;
|
||||||
|
|
|
@ -45,7 +45,7 @@ use OC\Cache\CappedMemoryCache;
|
||||||
use OCP\GroupInterface;
|
use OCP\GroupInterface;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
|
|
||||||
class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLDAP {
|
class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP {
|
||||||
protected $enabled = false;
|
protected $enabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,20 +165,18 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $dnGroup
|
|
||||||
* @return array
|
|
||||||
*
|
|
||||||
* For a group that has user membership defined by an LDAP search url attribute returns the users
|
* For a group that has user membership defined by an LDAP search url attribute returns the users
|
||||||
* that match the search url otherwise returns an empty array.
|
* that match the search url otherwise returns an empty array.
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function getDynamicGroupMembers($dnGroup) {
|
public function getDynamicGroupMembers(string $dnGroup): array {
|
||||||
$dynamicGroupMemberURL = strtolower($this->access->connection->ldapDynamicGroupMemberURL);
|
$dynamicGroupMemberURL = strtolower($this->access->connection->ldapDynamicGroupMemberURL);
|
||||||
|
|
||||||
if (empty($dynamicGroupMemberURL)) {
|
if (empty($dynamicGroupMemberURL)) {
|
||||||
return array();
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$dynamicMembers = array();
|
$dynamicMembers = [];
|
||||||
$memberURLs = $this->access->readAttribute(
|
$memberURLs = $this->access->readAttribute(
|
||||||
$dnGroup,
|
$dnGroup,
|
||||||
$dynamicGroupMemberURL,
|
$dynamicGroupMemberURL,
|
||||||
|
@ -186,6 +184,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
);
|
);
|
||||||
if ($memberURLs !== false) {
|
if ($memberURLs !== false) {
|
||||||
// this group has the 'memberURL' attribute so this is a dynamic group
|
// this group has the 'memberURL' attribute so this is a dynamic group
|
||||||
|
/** @noinspection SpellCheckingInspection */
|
||||||
// example 1: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(o=HeadOffice)
|
// example 1: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(o=HeadOffice)
|
||||||
// example 2: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(&(o=HeadOffice)(uidNumber>=500))
|
// example 2: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(&(o=HeadOffice)(uidNumber>=500))
|
||||||
$pos = strpos($memberURLs[0], '(');
|
$pos = strpos($memberURLs[0], '(');
|
||||||
|
@ -197,8 +196,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
$dynamicMembers[$value['dn'][0]] = 1;
|
$dynamicMembers[$value['dn'][0]] = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
\OCP\Util::writeLog('user_ldap', 'No search filter found on member url '.
|
\OC::$server->getLogger()->debug(
|
||||||
'of group ' . $dnGroup, ILogger::DEBUG);
|
'No search filter found on member url of group {dn}',
|
||||||
|
['app' => 'user_ldap', 'dn' => $dnGroup]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $dynamicMembers;
|
return $dynamicMembers;
|
||||||
|
@ -279,11 +280,13 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* translates a gidNumber into an ownCloud internal name
|
* translates a gidNumber into an ownCloud internal name
|
||||||
|
*
|
||||||
* @param string $gid as given by gidNumber on POSIX LDAP
|
* @param string $gid as given by gidNumber on POSIX LDAP
|
||||||
* @param string $dn a DN that belongs to the same domain as the group
|
* @param string $dn a DN that belongs to the same domain as the group
|
||||||
* @return string|bool
|
* @return string|bool
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function gidNumber2Name($gid, $dn) {
|
public function gidNumber2Name(string $gid, string $dn) {
|
||||||
$cacheKey = 'gidNumberToName' . $gid;
|
$cacheKey = 'gidNumberToName' . $gid;
|
||||||
$groupName = $this->access->connection->getFromCache($cacheKey);
|
$groupName = $this->access->connection->getFromCache($cacheKey);
|
||||||
if(!is_null($groupName) && isset($groupName)) {
|
if(!is_null($groupName) && isset($groupName)) {
|
||||||
|
@ -296,7 +299,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
'objectClass=posixGroup',
|
'objectClass=posixGroup',
|
||||||
$this->access->connection->ldapGidNumber . '=' . $gid
|
$this->access->connection->ldapGidNumber . '=' . $gid
|
||||||
]);
|
]);
|
||||||
$result = $this->access->searchGroups($filter, array('dn'), 1);
|
$result = $this->access->searchGroups($filter, ['dn'], 1);
|
||||||
if(empty($result)) {
|
if(empty($result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -401,14 +404,8 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the number of users that have the given group as gid number
|
* returns the number of users that have the given group as gid number
|
||||||
*
|
|
||||||
* @param string $groupDN
|
|
||||||
* @param string $search
|
|
||||||
* @param int $limit
|
|
||||||
* @param int $offset
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function countUsersInGidNumber($groupDN, $search = '', $limit = -1, $offset = 0) {
|
public function countUsersInGidNumber(string $groupDN, string $search = '', int $limit = -1, int $offset = 0): int {
|
||||||
try {
|
try {
|
||||||
$filter = $this->prepareFilterForUsersHasGidNumber($groupDN, $search);
|
$filter = $this->prepareFilterForUsersHasGidNumber($groupDN, $search);
|
||||||
$users = $this->access->countUsers($filter, ['dn'], $limit, $offset);
|
$users = $this->access->countUsers($filter, ['dn'], $limit, $offset);
|
||||||
|
@ -437,11 +434,13 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* translates a primary group ID into an Nextcloud internal name
|
* translates a primary group ID into an Nextcloud internal name
|
||||||
|
*
|
||||||
* @param string $gid as given by primaryGroupID on AD
|
* @param string $gid as given by primaryGroupID on AD
|
||||||
* @param string $dn a DN that belongs to the same domain as the group
|
* @param string $dn a DN that belongs to the same domain as the group
|
||||||
* @return string|bool
|
* @return string|bool
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function primaryGroupID2Name($gid, $dn) {
|
public function primaryGroupID2Name(string $gid, string $dn) {
|
||||||
$cacheKey = 'primaryGroupIDtoName';
|
$cacheKey = 'primaryGroupIDtoName';
|
||||||
$groupNames = $this->access->connection->getFromCache($cacheKey);
|
$groupNames = $this->access->connection->getFromCache($cacheKey);
|
||||||
if(!is_null($groupNames) && isset($groupNames[$gid])) {
|
if(!is_null($groupNames) && isset($groupNames[$gid])) {
|
||||||
|
@ -454,11 +453,12 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
}
|
}
|
||||||
|
|
||||||
//we need to get the DN from LDAP
|
//we need to get the DN from LDAP
|
||||||
$filter = $this->access->combineFilterWithAnd(array(
|
/** @noinspection SpellCheckingInspection */
|
||||||
|
$filter = $this->access->combineFilterWithAnd([
|
||||||
$this->access->connection->ldapGroupFilter,
|
$this->access->connection->ldapGroupFilter,
|
||||||
'objectsid=' . $domainObjectSid . '-' . $gid
|
'objectsid=' . $domainObjectSid . '-' . $gid
|
||||||
));
|
]);
|
||||||
$result = $this->access->searchGroups($filter, array('dn'), 1);
|
$result = $this->access->searchGroups($filter, ['dn'], 1);
|
||||||
if(empty($result)) {
|
if(empty($result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -563,17 +563,11 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the number of users that have the given group as primary group
|
* returns the number of users that have the given group as primary group
|
||||||
*
|
|
||||||
* @param string $groupDN
|
|
||||||
* @param string $search
|
|
||||||
* @param int $limit
|
|
||||||
* @param int $offset
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function countUsersInPrimaryGroup($groupDN, $search = '', $limit = -1, $offset = 0) {
|
public function countUsersInPrimaryGroup(string $groupDN, string $search = '', int $limit = -1, int $offset = 0): int {
|
||||||
try {
|
try {
|
||||||
$filter = $this->prepareFilterForUsersInPrimaryGroup($groupDN, $search);
|
$filter = $this->prepareFilterForUsersInPrimaryGroup($groupDN, $search);
|
||||||
$users = $this->access->countUsers($filter, array('dn'), $limit, $offset);
|
$users = $this->access->countUsers($filter, ['dn'], $limit, $offset);
|
||||||
return (int)$users;
|
return (int)$users;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -861,11 +855,14 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the number of users in a group, who match the search term
|
* returns the number of users in a group, who match the search term
|
||||||
|
*
|
||||||
* @param string $gid the internal group name
|
* @param string $gid the internal group name
|
||||||
* @param string $search optional, a search string
|
* @param string $search optional, a search string
|
||||||
* @return int|bool
|
* @return int|bool
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function countUsersInGroup($gid, $search = '') {
|
public function countUsersInGroup(string $gid, string $search = '') {
|
||||||
if ($this->groupPluginManager->implementsActions(GroupInterface::COUNT_USERS)) {
|
if ($this->groupPluginManager->implementsActions(GroupInterface::COUNT_USERS)) {
|
||||||
return $this->groupPluginManager->countUsersInGroup($gid, $search);
|
return $this->groupPluginManager->countUsersInGroup($gid, $search);
|
||||||
}
|
}
|
||||||
|
@ -900,6 +897,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
return $groupUsers;
|
return $groupUsers;
|
||||||
}
|
}
|
||||||
$search = $this->access->escapeFilterPart($search, true);
|
$search = $this->access->escapeFilterPart($search, true);
|
||||||
|
/** @noinspection SpellCheckingInspection */
|
||||||
$isMemberUid =
|
$isMemberUid =
|
||||||
(strtolower($this->access->connection->ldapGroupMemberAssocAttr)
|
(strtolower($this->access->connection->ldapGroupMemberAssocAttr)
|
||||||
=== 'memberuid');
|
=== 'memberuid');
|
||||||
|
@ -912,14 +910,14 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
// and let it count.
|
// and let it count.
|
||||||
//For now this is not important, because the only use of this method
|
//For now this is not important, because the only use of this method
|
||||||
//does not supply a search string
|
//does not supply a search string
|
||||||
$groupUsers = array();
|
$groupUsers = [];
|
||||||
foreach($members as $member) {
|
foreach($members as $member) {
|
||||||
if($isMemberUid) {
|
if($isMemberUid) {
|
||||||
//we got uids, need to get their DNs to 'translate' them to user names
|
//we got UIDs, need to get their DNs to 'translate' them to user names
|
||||||
$filter = $this->access->combineFilterWithAnd(array(
|
$filter = $this->access->combineFilterWithAnd([
|
||||||
str_replace('%uid', $member, $this->access->connection->ldapLoginFilter),
|
str_replace('%uid', $member, $this->access->connection->ldapLoginFilter),
|
||||||
$this->access->getFilterPartForUserSearch($search)
|
$this->access->getFilterPartForUserSearch($search)
|
||||||
));
|
]);
|
||||||
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn', 1);
|
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn', 1);
|
||||||
if(count($ldap_users) < 1) {
|
if(count($ldap_users) < 1) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -933,8 +931,8 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// dn2username will also check if the users belong to the allowed base
|
// dn2username will also check if the users belong to the allowed base
|
||||||
if($ocname = $this->access->dn2username($member)) {
|
if($ncName = $this->access->dn2username($member)) {
|
||||||
$groupUsers[] = $ocname;
|
$groupUsers[] = $ncName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1044,8 +1042,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if a group exists
|
* check if a group exists
|
||||||
|
*
|
||||||
* @param string $gid
|
* @param string $gid
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function groupExists($gid) {
|
public function groupExists($gid) {
|
||||||
$groupExists = $this->access->connection->getFromCache('groupExists'.$gid);
|
$groupExists = $this->access->connection->getFromCache('groupExists'.$gid);
|
||||||
|
@ -1061,8 +1061,8 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if group really still exists, we will be able to read its objectclass
|
//if group really still exists, we will be able to read its objectClass
|
||||||
if(!is_array($this->access->readAttribute($dn, ''))) {
|
if(!$this->access->isRecordOnLDAP($dn)) {
|
||||||
$this->access->connection->writeToCache('groupExists'.$gid, false);
|
$this->access->connection->writeToCache('groupExists'.$gid, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -620,8 +620,11 @@ class User {
|
||||||
* called by a post_login hook to handle password expiry
|
* called by a post_login hook to handle password expiry
|
||||||
*
|
*
|
||||||
* @param array $params
|
* @param array $params
|
||||||
|
* @throws \OC\ServerNotAvailableException
|
||||||
|
* @throws \OCP\PreConditionNotMetException
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function handlePasswordExpiry($params) {
|
public function handlePasswordExpiry(array $params): void {
|
||||||
$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
|
$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
|
||||||
if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
|
if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
|
||||||
return;//password expiry handling disabled
|
return;//password expiry handling disabled
|
||||||
|
@ -629,8 +632,8 @@ class User {
|
||||||
$uid = $params['uid'];
|
$uid = $params['uid'];
|
||||||
if(isset($uid) && $uid === $this->getUsername()) {
|
if(isset($uid) && $uid === $this->getUsername()) {
|
||||||
//retrieve relevant user attributes
|
//retrieve relevant user attributes
|
||||||
$result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
|
$result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
|
||||||
|
|
||||||
if(array_key_exists('pwdpolicysubentry', $result[0])) {
|
if(array_key_exists('pwdpolicysubentry', $result[0])) {
|
||||||
$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
|
$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
|
||||||
if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
|
if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
|
||||||
|
@ -646,7 +649,7 @@ class User {
|
||||||
$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
|
$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
|
||||||
$result = $this->connection->getFromCache($cacheKey);
|
$result = $this->connection->getFromCache($cacheKey);
|
||||||
if(is_null($result)) {
|
if(is_null($result)) {
|
||||||
$result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
|
$result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
|
||||||
$this->connection->writeToCache($cacheKey, $result);
|
$this->connection->writeToCache($cacheKey, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,10 +665,10 @@ class User {
|
||||||
&&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
|
&&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
|
||||||
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
||||||
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||||
'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
|
'user_ldap.renewPassword.showRenewPasswordForm', ['user' => $uid]));
|
||||||
} else { //no more grace login available
|
} else { //no more grace login available
|
||||||
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||||
'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
|
'user_ldap.renewPassword.showLoginFormInvalidPassword', ['user' => $uid]));
|
||||||
}
|
}
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
@ -673,7 +676,7 @@ class User {
|
||||||
if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
|
if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
|
||||||
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
||||||
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||||
'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
|
'user_ldap.renewPassword.showRenewPasswordForm', ['user' => $uid]));
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
//handle password expiry warning
|
//handle password expiry warning
|
||||||
|
|
|
@ -309,7 +309,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
* @throws \OC\ServerNotAvailableException
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function userExistsOnLDAP($user) {
|
public function userExistsOnLDAP($user): bool {
|
||||||
if(is_string($user)) {
|
if(is_string($user)) {
|
||||||
$user = $this->access->userManager->get($user);
|
$user = $this->access->userManager->get($user);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
||||||
|
|
||||||
$dn = $user->getDN();
|
$dn = $user->getDN();
|
||||||
//check if user really still exists by reading its entry
|
//check if user really still exists by reading its entry
|
||||||
if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
|
if(!$this->access->isRecordOnLDAP($dn, $this->access->connection->ldapUserFilter)) {
|
||||||
try {
|
try {
|
||||||
$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
|
$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
|
||||||
if (!$uuid) {
|
if (!$uuid) {
|
||||||
|
@ -327,7 +327,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
||||||
}
|
}
|
||||||
$newDn = $this->access->getUserDnByUuid($uuid);
|
$newDn = $this->access->getUserDnByUuid($uuid);
|
||||||
//check if renamed user is still valid by reapplying the ldap filter
|
//check if renamed user is still valid by reapplying the ldap filter
|
||||||
if ($newDn === $dn || !is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
|
if ($newDn === $dn || !$this->access->isRecordOnLDAP($newDn, $this->access->connection->ldapUserFilter)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
|
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
|
||||||
|
|
|
@ -131,11 +131,15 @@ class Wizard extends LDAPUtility {
|
||||||
return (string)$count;
|
return (string)$count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|WizardResult
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
public function countGroups() {
|
public function countGroups() {
|
||||||
$filter = $this->configuration->ldapGroupFilter;
|
$filter = $this->configuration->ldapGroupFilter;
|
||||||
|
|
||||||
if(empty($filter)) {
|
if(empty($filter)) {
|
||||||
$output = self::$l->n('%s group found', '%s groups found', 0, array(0));
|
$output = self::$l->n('%s group found', '%s groups found', 0, [0]);
|
||||||
$this->result->addChange('ldap_group_count', $output);
|
$this->result->addChange('ldap_group_count', $output);
|
||||||
return $this->result;
|
return $this->result;
|
||||||
}
|
}
|
||||||
|
@ -195,27 +199,28 @@ class Wizard extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* counts users with a specified attribute
|
* counts users with a specified attribute
|
||||||
* @param string $attr
|
*
|
||||||
* @param bool $existsCheck
|
|
||||||
* @return int|bool
|
* @return int|bool
|
||||||
|
* @throws ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function countUsersWithAttribute($attr, $existsCheck = false) {
|
public function countUsersWithAttribute(string $attr, bool $existsCheck = false) {
|
||||||
if(!$this->checkRequirements(array('ldapHost',
|
if(!$this->checkRequirements([
|
||||||
'ldapPort',
|
'ldapHost',
|
||||||
'ldapBase',
|
'ldapPort',
|
||||||
'ldapUserFilter',
|
'ldapBase',
|
||||||
))) {
|
'ldapUserFilter',
|
||||||
|
])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filter = $this->access->combineFilterWithAnd(array(
|
$filter = $this->access->combineFilterWithAnd([
|
||||||
$this->configuration->ldapUserFilter,
|
$this->configuration->ldapUserFilter,
|
||||||
$attr . '=*'
|
$attr . '=*'
|
||||||
));
|
]);
|
||||||
|
|
||||||
$limit = ($existsCheck === false) ? null : 1;
|
$limit = ($existsCheck === false) ? null : 1;
|
||||||
|
|
||||||
return $this->access->countUsers($filter, array('dn'), $limit);
|
return $this->access->countUsers($filter, ['dn'], $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,11 +230,12 @@ class Wizard extends LDAPUtility {
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function detectUserDisplayNameAttribute() {
|
public function detectUserDisplayNameAttribute() {
|
||||||
if(!$this->checkRequirements(array('ldapHost',
|
if(!$this->checkRequirements([
|
||||||
'ldapPort',
|
'ldapHost',
|
||||||
'ldapBase',
|
'ldapPort',
|
||||||
'ldapUserFilter',
|
'ldapBase',
|
||||||
))) {
|
'ldapUserFilter',
|
||||||
|
])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +253,8 @@ class Wizard extends LDAPUtility {
|
||||||
}
|
}
|
||||||
|
|
||||||
// first attribute that has at least one result wins
|
// first attribute that has at least one result wins
|
||||||
$displayNameAttrs = array('displayname', 'cn');
|
/** @noinspection SpellCheckingInspection */
|
||||||
|
$displayNameAttrs = ['displayname', 'cn'];
|
||||||
foreach ($displayNameAttrs as $attr) {
|
foreach ($displayNameAttrs as $attr) {
|
||||||
$count = (int)$this->countUsersWithAttribute($attr, true);
|
$count = (int)$this->countUsersWithAttribute($attr, true);
|
||||||
|
|
||||||
|
@ -267,26 +274,26 @@ class Wizard extends LDAPUtility {
|
||||||
* @return WizardResult|bool
|
* @return WizardResult|bool
|
||||||
*/
|
*/
|
||||||
public function detectEmailAttribute() {
|
public function detectEmailAttribute() {
|
||||||
if(!$this->checkRequirements(array('ldapHost',
|
if(!$this->checkRequirements([
|
||||||
'ldapPort',
|
'ldapHost',
|
||||||
'ldapBase',
|
'ldapPort',
|
||||||
'ldapUserFilter',
|
'ldapBase',
|
||||||
))) {
|
'ldapUserFilter',
|
||||||
|
])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$attr = $this->configuration->ldapEmailAttribute;
|
$attr = $this->configuration->ldapEmailAttribute;
|
||||||
|
$writeLog = false;
|
||||||
if ($attr !== '') {
|
if ($attr !== '') {
|
||||||
$count = (int)$this->countUsersWithAttribute($attr, true);
|
$count = (int)$this->countUsersWithAttribute($attr, true);
|
||||||
if($count > 0) {
|
if($count > 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$writeLog = true;
|
$writeLog = true;
|
||||||
} else {
|
|
||||||
$writeLog = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$emailAttributes = array('mail', 'mailPrimaryAddress');
|
$emailAttributes = ['mail', 'mailPrimaryAddress'];
|
||||||
$winner = '';
|
$winner = '';
|
||||||
$maxUsers = 0;
|
$maxUsers = 0;
|
||||||
foreach($emailAttributes as $attr) {
|
foreach($emailAttributes as $attr) {
|
||||||
|
@ -300,9 +307,10 @@ class Wizard extends LDAPUtility {
|
||||||
if($winner !== '') {
|
if($winner !== '') {
|
||||||
$this->applyFind('ldap_email_attr', $winner);
|
$this->applyFind('ldap_email_attr', $winner);
|
||||||
if($writeLog) {
|
if($writeLog) {
|
||||||
\OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
|
\OC::$server->getLogger()->info(
|
||||||
'automatically been reset, because the original value ' .
|
'The mail attribute has automatically been reset, because the original value did not return any results',
|
||||||
'did not return any results.', ILogger::INFO);
|
['app' => 'user_ldap']
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,15 +635,14 @@ class Wizard extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool|WizardResult
|
* @return bool|WizardResult
|
||||||
* @param string $loginName
|
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function testLoginName($loginName) {
|
public function testLoginName(string $loginName) {
|
||||||
if(!$this->checkRequirements(array('ldapHost',
|
if(!$this->checkRequirements(['ldapHost',
|
||||||
'ldapPort',
|
'ldapPort',
|
||||||
'ldapBase',
|
'ldapBase',
|
||||||
'ldapLoginFilter',
|
'ldapLoginFilter',
|
||||||
))) {
|
])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,6 +661,7 @@ class Wizard extends LDAPUtility {
|
||||||
throw new \Exception($this->ldap->error($cr));
|
throw new \Exception($this->ldap->error($cr));
|
||||||
}
|
}
|
||||||
$filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
|
$filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
|
||||||
|
/** @noinspection SpellCheckingInspection */
|
||||||
$this->result->addChange('ldap_test_loginname', $users);
|
$this->result->addChange('ldap_test_loginname', $users);
|
||||||
$this->result->addChange('ldap_test_effective_filter', $filter);
|
$this->result->addChange('ldap_test_effective_filter', $filter);
|
||||||
return $this->result;
|
return $this->result;
|
||||||
|
@ -832,11 +840,9 @@ class Wizard extends LDAPUtility {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether for a given BaseDN results will be returned
|
* Checks whether for a given BaseDN results will be returned
|
||||||
* @param string $base the BaseDN to test
|
|
||||||
* @return bool true on success, false otherwise
|
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function testBaseDN($base) {
|
private function testBaseDN(string $base): bool {
|
||||||
$cr = $this->getConnection();
|
$cr = $this->getConnection();
|
||||||
if(!$cr) {
|
if(!$cr) {
|
||||||
throw new \Exception('Could not connect to LDAP');
|
throw new \Exception('Could not connect to LDAP');
|
||||||
|
@ -844,12 +850,14 @@ class Wizard extends LDAPUtility {
|
||||||
|
|
||||||
//base is there, let's validate it. If we search for anything, we should
|
//base is there, let's validate it. If we search for anything, we should
|
||||||
//get a result set > 0 on a proper base
|
//get a result set > 0 on a proper base
|
||||||
$rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
|
$rr = $this->ldap->search($cr, $base, 'objectClass=*', ['dn'], 0, 1);
|
||||||
if(!$this->ldap->isResource($rr)) {
|
if(!$this->ldap->isResource($rr)) {
|
||||||
$errorNo = $this->ldap->errno($cr);
|
$errorNo = $this->ldap->errno($cr);
|
||||||
$errorMsg = $this->ldap->error($cr);
|
$errorMsg = $this->ldap->error($cr);
|
||||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
|
\OC::$server->getLogger()->info(
|
||||||
' Error '.$errorNo.': '.$errorMsg, ILogger::INFO);
|
'Wiz: Could not search base {base}, Error {errno}: {error}',
|
||||||
|
['app' => 'user_ldap', 'base' => $base, 'errno' => $errorNo, 'error' => $errorMsg]
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$entries = $this->ldap->countEntries($cr, $rr);
|
$entries = $this->ldap->countEntries($cr, $rr);
|
||||||
|
@ -862,15 +870,15 @@ class Wizard extends LDAPUtility {
|
||||||
* a configured objectClass. I.e. not necessarily for all available groups
|
* a configured objectClass. I.e. not necessarily for all available groups
|
||||||
* memberOf does work.
|
* memberOf does work.
|
||||||
*
|
*
|
||||||
* @return bool true if it does, false otherwise
|
* @throws ServerNotAvailableException
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function testMemberOf() {
|
private function testMemberOf(): bool {
|
||||||
$cr = $this->getConnection();
|
$cr = $this->getConnection();
|
||||||
if(!$cr) {
|
if(!$cr) {
|
||||||
throw new \Exception('Could not connect to LDAP');
|
throw new \Exception('Could not connect to LDAP');
|
||||||
}
|
}
|
||||||
$result = $this->access->countUsers('memberOf=*', array('memberOf'), 1);
|
$result = $this->access->countUsers('memberOf=*', ['memberOf'], 1);
|
||||||
if(is_int($result) && $result > 0) {
|
if(is_int($result) && $result > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1131,9 +1139,9 @@ class Wizard extends LDAPUtility {
|
||||||
* yields most result entries
|
* yields most result entries
|
||||||
* @return array|false an array with the values on success, false otherwise
|
* @return array|false an array with the values on success, false otherwise
|
||||||
*/
|
*/
|
||||||
public function cumulativeSearchOnAttribute($filters, $attr, $dnReadLimit = 3, &$maxF = null) {
|
public function cumulativeSearchOnAttribute(array $filters, string $attr, int $dnReadLimit = 3, string &$maxF = null) {
|
||||||
$dnRead = array();
|
$dnRead = [];
|
||||||
$foundItems = array();
|
$foundItems = [];
|
||||||
$maxEntries = 0;
|
$maxEntries = 0;
|
||||||
if(!is_array($this->configuration->ldapBase)
|
if(!is_array($this->configuration->ldapBase)
|
||||||
|| !isset($this->configuration->ldapBase[0])) {
|
|| !isset($this->configuration->ldapBase[0])) {
|
||||||
|
@ -1154,7 +1162,7 @@ class Wizard extends LDAPUtility {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 20k limit for performance and reason
|
// 20k limit for performance and reason
|
||||||
$rr = $this->ldap->search($cr, $base, $filter, array($attr), 0, 20000);
|
$rr = $this->ldap->search($cr, $base, $filter, [$attr], 0, 20000);
|
||||||
if(!$this->ldap->isResource($rr)) {
|
if(!$this->ldap->isResource($rr)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1186,7 @@ class Wizard extends LDAPUtility {
|
||||||
if($dn === false || in_array($dn, $dnRead)) {
|
if($dn === false || in_array($dn, $dnRead)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$newItems = array();
|
$newItems = [];
|
||||||
$state = $this->getAttributeValuesFromEntry($attributes,
|
$state = $this->getAttributeValuesFromEntry($attributes,
|
||||||
$attr,
|
$attr,
|
||||||
$newItems);
|
$newItems);
|
||||||
|
@ -1249,15 +1257,7 @@ class Wizard extends LDAPUtility {
|
||||||
return $availableFeatures;
|
return $availableFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getAttributeValuesFromEntry(array $result, string $attribute, array &$known): int {
|
||||||
* appends a list of values fr
|
|
||||||
* @param resource $result the return value from ldap_get_attributes
|
|
||||||
* @param string $attribute the attribute values to look for
|
|
||||||
* @param array &$known new values will be appended here
|
|
||||||
* @return int, state on of the class constants LRESULT_PROCESSED_OK,
|
|
||||||
* LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
|
|
||||||
*/
|
|
||||||
private function getAttributeValuesFromEntry($result, $attribute, &$known) {
|
|
||||||
if(!is_array($result)
|
if(!is_array($result)
|
||||||
|| !isset($result['count'])
|
|| !isset($result['count'])
|
||||||
|| !$result['count'] > 0) {
|
|| !$result['count'] > 0) {
|
||||||
|
|
|
@ -559,7 +559,7 @@ class AccessTest extends TestCase {
|
||||||
->method('search')
|
->method('search')
|
||||||
->willReturn([$fakeSearchResultResource]);
|
->willReturn([$fakeSearchResultResource]);
|
||||||
$this->ldap
|
$this->ldap
|
||||||
->expects($this->exactly(count($base)))
|
->expects($this->exactly(1))
|
||||||
->method('getEntries')
|
->method('getEntries')
|
||||||
->willReturn($fakeLdapEntries);
|
->willReturn($fakeLdapEntries);
|
||||||
|
|
||||||
|
@ -571,7 +571,7 @@ class AccessTest extends TestCase {
|
||||||
public function testSearchNoPagedSearch() {
|
public function testSearchNoPagedSearch() {
|
||||||
// scenario: no pages search, 1 search base
|
// scenario: no pages search, 1 search base
|
||||||
$filter = 'objectClass=nextcloudUser';
|
$filter = 'objectClass=nextcloudUser';
|
||||||
$base = ['ou=zombies,dc=foobar,dc=nextcloud,dc=com'];
|
$base = 'ou=zombies,dc=foobar,dc=nextcloud,dc=com';
|
||||||
|
|
||||||
$fakeConnection = new \stdClass();
|
$fakeConnection = new \stdClass();
|
||||||
$fakeSearchResultResource = new \stdClass();
|
$fakeSearchResultResource = new \stdClass();
|
||||||
|
|
|
@ -105,9 +105,13 @@ class Group_LDAPTest extends TestCase {
|
||||||
->method('groupname2dn')
|
->method('groupname2dn')
|
||||||
->will($this->returnValue('cn=group,dc=foo,dc=bar'));
|
->will($this->returnValue('cn=group,dc=foo,dc=bar'));
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnValue(array('u11', 'u22', 'u33', 'u34')));
|
->will($this->returnValue(['u11', 'u22', 'u33', 'u34']));
|
||||||
|
$access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->with($this->anything())
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
// for primary groups
|
// for primary groups
|
||||||
$access->expects($this->once())
|
$access->expects($this->once())
|
||||||
|
@ -132,9 +136,9 @@ class Group_LDAPTest extends TestCase {
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->any())
|
||||||
->method('fetchListOfUsers')
|
->method('fetchListOfUsers')
|
||||||
->will($this->returnValue(array()));
|
->will($this->returnValue([]));
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnCallback(function($name) {
|
->will($this->returnCallback(function($name) {
|
||||||
//the search operation will call readAttribute, thus we need
|
//the search operation will call readAttribute, thus we need
|
||||||
|
@ -145,14 +149,21 @@ class Group_LDAPTest extends TestCase {
|
||||||
if(strpos($name, 'u') === 0) {
|
if(strpos($name, 'u') === 0) {
|
||||||
return strpos($name, '3');
|
return strpos($name, '3');
|
||||||
}
|
}
|
||||||
return array('u11', 'u22', 'u33', 'u34');
|
return ['u11', 'u22', 'u33', 'u34'];
|
||||||
}));
|
}));
|
||||||
|
$access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->with($this->anything())
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->any())
|
||||||
->method('dn2username')
|
->method('dn2username')
|
||||||
->will($this->returnCallback(function() {
|
->will($this->returnCallback(function() {
|
||||||
return 'foobar' . \OC::$server->getSecureRandom()->generate(7);
|
return 'foobar' . \OC::$server->getSecureRandom()->generate(7);
|
||||||
}));
|
}));
|
||||||
|
$access->expects($this->any())
|
||||||
|
->method('escapeFilterPart')
|
||||||
|
->willReturnArgument(0);
|
||||||
|
|
||||||
$groupBackend = new GroupLDAP($access,$pluginManager);
|
$groupBackend = new GroupLDAP($access,$pluginManager);
|
||||||
$users = $groupBackend->countUsersInGroup('group', '3');
|
$users = $groupBackend->countUsersInGroup('group', '3');
|
||||||
|
@ -262,10 +273,10 @@ class Group_LDAPTest extends TestCase {
|
||||||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||||
$attr = 'gidNumber';
|
$attr = 'gidNumber';
|
||||||
|
|
||||||
$access->expects($this->once())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->with($dn, $attr)
|
->with($dn, $attr)
|
||||||
->will($this->returnValue(array('3117')));
|
->will($this->returnValue(['3117']));
|
||||||
|
|
||||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||||
|
|
||||||
|
@ -283,7 +294,7 @@ class Group_LDAPTest extends TestCase {
|
||||||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||||
$attr = 'gidNumber';
|
$attr = 'gidNumber';
|
||||||
|
|
||||||
$access->expects($this->once())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->with($dn, $attr)
|
->with($dn, $attr)
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
|
@ -416,10 +427,10 @@ class Group_LDAPTest extends TestCase {
|
||||||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||||
$attr = 'primaryGroupToken';
|
$attr = 'primaryGroupToken';
|
||||||
|
|
||||||
$access->expects($this->once())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->with($dn, $attr)
|
->with($dn, $attr)
|
||||||
->will($this->returnValue(array('3117')));
|
->will($this->returnValue(['3117']));
|
||||||
|
|
||||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||||
|
|
||||||
|
@ -439,7 +450,7 @@ class Group_LDAPTest extends TestCase {
|
||||||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||||
$attr = 'primaryGroupToken';
|
$attr = 'primaryGroupToken';
|
||||||
|
|
||||||
$access->expects($this->once())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->with($dn, $attr)
|
->with($dn, $attr)
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
|
@ -506,16 +517,20 @@ class Group_LDAPTest extends TestCase {
|
||||||
$access->connection->expects($this->any())
|
$access->connection->expects($this->any())
|
||||||
->method('getFromCache')
|
->method('getFromCache')
|
||||||
->will($this->returnValue(null));
|
->will($this->returnValue(null));
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->will($this->returnCallback(function($dn, $attr) {
|
||||||
if($attr === 'primaryGroupToken') {
|
if($attr === 'primaryGroupToken') {
|
||||||
return array(1337);
|
return [1337];
|
||||||
} else if($attr === 'gidNumber') {
|
} else if($attr === 'gidNumber') {
|
||||||
return [4211];
|
return [4211];
|
||||||
}
|
}
|
||||||
return array();
|
return [];
|
||||||
}));
|
}));
|
||||||
|
$access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->with($this->anything())
|
||||||
|
->willReturn(true);
|
||||||
$access->expects($this->any())
|
$access->expects($this->any())
|
||||||
->method('groupname2dn')
|
->method('groupname2dn')
|
||||||
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
||||||
|
@ -543,20 +558,24 @@ class Group_LDAPTest extends TestCase {
|
||||||
$access->connection->expects($this->any())
|
$access->connection->expects($this->any())
|
||||||
->method('getFromCache')
|
->method('getFromCache')
|
||||||
->will($this->returnValue(null));
|
->will($this->returnValue(null));
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->will($this->returnCallback(function($dn, $attr) {
|
||||||
if($attr === 'primaryGroupToken') {
|
if($attr === 'primaryGroupToken') {
|
||||||
return array(1337);
|
return [1337];
|
||||||
}
|
}
|
||||||
return array();
|
return [];
|
||||||
}));
|
}));
|
||||||
|
$access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->with($this->anything())
|
||||||
|
->willReturn(true);
|
||||||
$access->expects($this->any())
|
$access->expects($this->any())
|
||||||
->method('groupname2dn')
|
->method('groupname2dn')
|
||||||
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
||||||
$access->expects($this->once())
|
$access->expects($this->once())
|
||||||
->method('nextcloudUserNames')
|
->method('nextcloudUserNames')
|
||||||
->will($this->returnValue(array('lisa', 'bart', 'kira', 'brad')));
|
->will($this->returnValue(['lisa', 'bart', 'kira', 'brad']));
|
||||||
$access->userManager = $this->createMock(Manager::class);
|
$access->userManager = $this->createMock(Manager::class);
|
||||||
|
|
||||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||||
|
@ -579,15 +598,20 @@ class Group_LDAPTest extends TestCase {
|
||||||
->method('getFromCache')
|
->method('getFromCache')
|
||||||
->will($this->returnValue(null));
|
->will($this->returnValue(null));
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->will($this->returnCallback(function($dn, $attr) {
|
||||||
if($attr === 'primaryGroupToken') {
|
if($attr === 'primaryGroupToken') {
|
||||||
return array(1337);
|
return [1337];
|
||||||
}
|
}
|
||||||
return array();
|
return [];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
$access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->with($this->anything())
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$access->expects($this->any())
|
$access->expects($this->any())
|
||||||
->method('groupname2dn')
|
->method('groupname2dn')
|
||||||
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
||||||
|
@ -1018,7 +1042,7 @@ class Group_LDAPTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
public function testGroupMembers($groupDN, $expectedMembers, $groupsInfo = null) {
|
public function testGroupMembers($groupDN, $expectedMembers, $groupsInfo = null) {
|
||||||
$access = $this->getAccessMock();
|
$access = $this->getAccessMock();
|
||||||
$access->expects($this->any())
|
$access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->willReturnCallback(function($group) use ($groupDN, $expectedMembers, $groupsInfo) {
|
->willReturnCallback(function($group) use ($groupDN, $expectedMembers, $groupsInfo) {
|
||||||
if(isset($groupsInfo[$group])) {
|
if(isset($groupsInfo[$group])) {
|
||||||
|
|
|
@ -545,7 +545,7 @@ class UserTest extends \Test\TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateAvatarThumbnailPhotoProvided() {
|
public function testUpdateAvatarThumbnailPhotoProvided() {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->willReturnCallback(function($dn, $attr) {
|
->willReturnCallback(function($dn, $attr) {
|
||||||
if($dn === $this->dn
|
if($dn === $this->dn
|
||||||
|
@ -599,7 +599,7 @@ class UserTest extends \Test\TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateAvatarCorruptPhotoProvided() {
|
public function testUpdateAvatarCorruptPhotoProvided() {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->willReturnCallback(function($dn, $attr) {
|
->willReturnCallback(function($dn, $attr) {
|
||||||
if($dn === $this->dn
|
if($dn === $this->dn
|
||||||
|
@ -645,7 +645,7 @@ class UserTest extends \Test\TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateAvatarUnsupportedThumbnailPhotoProvided() {
|
public function testUpdateAvatarUnsupportedThumbnailPhotoProvided() {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->willReturnCallback(function($dn, $attr) {
|
->willReturnCallback(function($dn, $attr) {
|
||||||
if($dn === $this->dn
|
if($dn === $this->dn
|
||||||
|
@ -700,7 +700,7 @@ class UserTest extends \Test\TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateAvatarNotProvided() {
|
public function testUpdateAvatarNotProvided() {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->willReturnCallback(function($dn, $attr) {
|
->willReturnCallback(function($dn, $attr) {
|
||||||
if($dn === $this->dn
|
if($dn === $this->dn
|
||||||
|
@ -962,7 +962,7 @@ class UserTest extends \Test\TestCase {
|
||||||
->with($this->equalTo('homeFolderNamingRule'))
|
->with($this->equalTo('homeFolderNamingRule'))
|
||||||
->will($this->returnValue('attr:foobar'));
|
->will($this->returnValue('attr:foobar'));
|
||||||
|
|
||||||
$this->access->expects($this->once())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
@ -984,7 +984,7 @@ class UserTest extends \Test\TestCase {
|
||||||
->with($this->equalTo('homeFolderNamingRule'))
|
->with($this->equalTo('homeFolderNamingRule'))
|
||||||
->will($this->returnValue('attr:foobar'));
|
->will($this->returnValue('attr:foobar'));
|
||||||
|
|
||||||
$this->access->expects($this->once())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
@ -1066,7 +1066,7 @@ class UserTest extends \Test\TestCase {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
->method('search')
|
->method('search')
|
||||||
->will($this->returnCallback(function($filter, $base) {
|
->will($this->returnCallback(function($filter, $base) {
|
||||||
if($base === [$this->dn]) {
|
if($base === $this->dn) {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'pwdchangedtime' => [(new \DateTime())->sub(new \DateInterval('P28D'))->format('Ymdhis').'Z'],
|
'pwdchangedtime' => [(new \DateTime())->sub(new \DateInterval('P28D'))->format('Ymdhis').'Z'],
|
||||||
|
@ -1074,7 +1074,7 @@ class UserTest extends \Test\TestCase {
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if($base === ['cn=default,ou=policies,dc=foo,dc=bar']) {
|
if($base === 'cn=default,ou=policies,dc=foo,dc=bar') {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'pwdmaxage' => ['2592000'],
|
'pwdmaxage' => ['2592000'],
|
||||||
|
@ -1129,7 +1129,7 @@ class UserTest extends \Test\TestCase {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
->method('search')
|
->method('search')
|
||||||
->will($this->returnCallback(function($filter, $base) {
|
->will($this->returnCallback(function($filter, $base) {
|
||||||
if($base === [$this->dn]) {
|
if($base === $this->dn) {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'pwdpolicysubentry' => ['cn=custom,ou=policies,dc=foo,dc=bar'],
|
'pwdpolicysubentry' => ['cn=custom,ou=policies,dc=foo,dc=bar'],
|
||||||
|
@ -1138,7 +1138,7 @@ class UserTest extends \Test\TestCase {
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if($base === ['cn=custom,ou=policies,dc=foo,dc=bar']) {
|
if($base === 'cn=custom,ou=policies,dc=foo,dc=bar') {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
'pwdmaxage' => ['2592000'],
|
'pwdmaxage' => ['2592000'],
|
||||||
|
|
|
@ -494,14 +494,11 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('getDN')
|
->method('getDN')
|
||||||
->willReturn('dnOfRoland,dc=test');
|
->willReturn('dnOfRoland,dc=test');
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('isRecordOnLDAP')
|
||||||
->will($this->returnCallback(function($dn) {
|
->with('dnOfRoland,dc=test')
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
->willReturn(true);
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
$this->userManager->expects($this->atLeastOnce())
|
$this->userManager->expects($this->atLeastOnce())
|
||||||
->method('get')
|
->method('get')
|
||||||
->willReturn($user);
|
->willReturn($user);
|
||||||
|
@ -509,6 +506,15 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('getUserMapper')
|
->method('getUserMapper')
|
||||||
->willReturn($this->createMock(UserMapping::class));
|
->willReturn($this->createMock(UserMapping::class));
|
||||||
|
|
||||||
|
$this->connection->expects($this->any())
|
||||||
|
->method('__get')
|
||||||
|
->will($this->returnCallback(function($name) {
|
||||||
|
if($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
//test for existing user
|
//test for existing user
|
||||||
/** @noinspection PhpUnhandledExceptionInspection */
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
$result = $backend->userExists('gunslinger');
|
$result = $backend->userExists('gunslinger');
|
||||||
|
@ -525,14 +531,6 @@ class User_LDAPTest extends TestCase {
|
||||||
->with('dnOfFormerUser,dc=test')
|
->with('dnOfFormerUser,dc=test')
|
||||||
->willReturn('45673458748');
|
->willReturn('45673458748');
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnCallback(function($dn) {
|
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
->method('getUserMapper')
|
->method('getUserMapper')
|
||||||
->willReturn($mapper);
|
->willReturn($mapper);
|
||||||
|
@ -549,6 +547,16 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('get')
|
->method('get')
|
||||||
->willReturn($user);
|
->willReturn($user);
|
||||||
|
|
||||||
|
$this->connection->expects($this->any())
|
||||||
|
->method('__get')
|
||||||
|
->will($this->returnCallback(function($name) {
|
||||||
|
if($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
//test for deleted user
|
//test for deleted user
|
||||||
$this->assertFalse($backend->userExists('formerUser'));
|
$this->assertFalse($backend->userExists('formerUser'));
|
||||||
}
|
}
|
||||||
|
@ -557,15 +565,6 @@ class User_LDAPTest extends TestCase {
|
||||||
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
|
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
|
||||||
$this->prepareMockForUserExists();
|
$this->prepareMockForUserExists();
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnCallback(function($dn) {
|
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
//test for never-existing user
|
//test for never-existing user
|
||||||
/** @noinspection PhpUnhandledExceptionInspection */
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
$result = $backend->userExists('mallory');
|
$result = $backend->userExists('mallory');
|
||||||
|
@ -582,14 +581,11 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('getDN')
|
->method('getDN')
|
||||||
->willReturn('dnOfRoland,dc=test');
|
->willReturn('dnOfRoland,dc=test');
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('isRecordOnLDAP')
|
||||||
->will($this->returnCallback(function($dn) {
|
->with('dnOfRoland,dc=test')
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
->willReturn(true);
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
$this->userManager->expects($this->atLeastOnce())
|
$this->userManager->expects($this->atLeastOnce())
|
||||||
->method('get')
|
->method('get')
|
||||||
->willReturn($user);
|
->willReturn($user);
|
||||||
|
@ -597,6 +593,16 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('getUserMapper')
|
->method('getUserMapper')
|
||||||
->willReturn($this->createMock(UserMapping::class));
|
->willReturn($this->createMock(UserMapping::class));
|
||||||
|
|
||||||
|
$this->connection->expects($this->any())
|
||||||
|
->method('__get')
|
||||||
|
->will($this->returnCallback(function($name) {
|
||||||
|
if($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
//test for existing user
|
//test for existing user
|
||||||
$result = \OC::$server->getUserManager()->userExists('gunslinger');
|
$result = \OC::$server->getUserManager()->userExists('gunslinger');
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
|
@ -613,14 +619,6 @@ class User_LDAPTest extends TestCase {
|
||||||
->with('dnOfFormerUser,dc=test')
|
->with('dnOfFormerUser,dc=test')
|
||||||
->willReturn('45673458748');
|
->willReturn('45673458748');
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnCallback(function($dn) {
|
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
->method('getUserMapper')
|
->method('getUserMapper')
|
||||||
->willReturn($mapper);
|
->willReturn($mapper);
|
||||||
|
@ -637,6 +635,16 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('get')
|
->method('get')
|
||||||
->willReturn($user);
|
->willReturn($user);
|
||||||
|
|
||||||
|
$this->connection->expects($this->any())
|
||||||
|
->method('__get')
|
||||||
|
->will($this->returnCallback(function($name) {
|
||||||
|
if($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
//test for deleted user
|
//test for deleted user
|
||||||
$this->assertFalse(\OC::$server->getUserManager()->userExists('formerUser'));
|
$this->assertFalse(\OC::$server->getUserManager()->userExists('formerUser'));
|
||||||
}
|
}
|
||||||
|
@ -646,15 +654,6 @@ class User_LDAPTest extends TestCase {
|
||||||
$this->prepareMockForUserExists();
|
$this->prepareMockForUserExists();
|
||||||
\OC_User::useBackend($backend);
|
\OC_User::useBackend($backend);
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnCallback(function($dn) {
|
|
||||||
if($dn === 'dnOfRoland,dc=test') {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
//test for never-existing user
|
//test for never-existing user
|
||||||
$result = \OC::$server->getUserManager()->userExists('mallory');
|
$result = \OC::$server->getUserManager()->userExists('mallory');
|
||||||
$this->assertFalse($result);
|
$this->assertFalse($result);
|
||||||
|
@ -677,24 +676,16 @@ class User_LDAPTest extends TestCase {
|
||||||
->will($this->returnCallback(function($name) {
|
->will($this->returnCallback(function($name) {
|
||||||
if($name === 'homeFolderNamingRule') {
|
if($name === 'homeFolderNamingRule') {
|
||||||
return 'attr:testAttribute';
|
return 'attr:testAttribute';
|
||||||
|
} elseif ($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('isRecordOnLDAP')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->with('dnOfRoland,dc=test')
|
||||||
switch ($dn) {
|
->willReturn(true);
|
||||||
case 'dnOfRoland,dc=test':
|
|
||||||
if($attr === 'testAttribute') {
|
|
||||||
return array('/tmp/rolandshome/');
|
|
||||||
}
|
|
||||||
return array();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
$user = $this->createMock(User::class);
|
$user = $this->createMock(User::class);
|
||||||
$user->expects($this->any())
|
$user->expects($this->any())
|
||||||
|
@ -729,24 +720,16 @@ class User_LDAPTest extends TestCase {
|
||||||
->will($this->returnCallback(function($name) {
|
->will($this->returnCallback(function($name) {
|
||||||
if($name === 'homeFolderNamingRule') {
|
if($name === 'homeFolderNamingRule') {
|
||||||
return 'attr:testAttribute';
|
return 'attr:testAttribute';
|
||||||
|
} else if ($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('isRecordOnLDAP')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->with('dnOfLadyOfShadows,dc=test')
|
||||||
switch ($dn) {
|
->willReturn(true);
|
||||||
case 'dnOfLadyOfShadows,dc=test':
|
|
||||||
if($attr === 'testAttribute') {
|
|
||||||
return array('susannah/');
|
|
||||||
}
|
|
||||||
return array();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
$user = $this->createMock(User::class);
|
$user = $this->createMock(User::class);
|
||||||
$user->expects($this->any())
|
$user->expects($this->any())
|
||||||
|
@ -775,22 +758,6 @@ class User_LDAPTest extends TestCase {
|
||||||
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
|
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
|
||||||
$this->prepareMockForUserExists();
|
$this->prepareMockForUserExists();
|
||||||
|
|
||||||
$this->connection->expects($this->any())
|
|
||||||
->method('__get')
|
|
||||||
->will($this->returnCallback(function($name) {
|
|
||||||
if($name === 'homeFolderNamingRule') {
|
|
||||||
return 'attr:testAttribute';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
|
||||||
switch ($dn) {
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
$this->access->connection->expects($this->any())
|
$this->access->connection->expects($this->any())
|
||||||
->method('getFromCache')
|
->method('getFromCache')
|
||||||
->willReturnCallback(function($key) {
|
->willReturnCallback(function($key) {
|
||||||
|
@ -835,10 +802,6 @@ class User_LDAPTest extends TestCase {
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
|
||||||
->method('readAttribute')
|
|
||||||
->will($this->returnValue([]));
|
|
||||||
|
|
||||||
$userMapper = $this->createMock(UserMapping::class);
|
$userMapper = $this->createMock(UserMapping::class);
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
|
@ -886,11 +849,13 @@ class User_LDAPTest extends TestCase {
|
||||||
->will($this->returnCallback(function($name) {
|
->will($this->returnCallback(function($name) {
|
||||||
if($name === 'ldapUserDisplayName') {
|
if($name === 'ldapUserDisplayName') {
|
||||||
return 'displayname';
|
return 'displayname';
|
||||||
|
} elseif ($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->atLeastOnce())
|
||||||
->method('readAttribute')
|
->method('readAttribute')
|
||||||
->will($this->returnCallback(function($dn, $attr) {
|
->will($this->returnCallback(function($dn, $attr) {
|
||||||
switch ($dn) {
|
switch ($dn) {
|
||||||
|
@ -957,6 +922,10 @@ class User_LDAPTest extends TestCase {
|
||||||
->method('getUserDnByUuid')
|
->method('getUserDnByUuid')
|
||||||
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
||||||
|
|
||||||
|
$this->access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
//with displayName
|
//with displayName
|
||||||
$result = $backend->getDisplayName('gunslinger');
|
$result = $backend->getDisplayName('gunslinger');
|
||||||
$this->assertEquals('Roland Deschain', $result);
|
$this->assertEquals('Roland Deschain', $result);
|
||||||
|
@ -996,6 +965,14 @@ class User_LDAPTest extends TestCase {
|
||||||
->will($this->returnCallback(function() {
|
->will($this->returnCallback(function() {
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
|
$this->connection->expects($this->any())
|
||||||
|
->method('__get')
|
||||||
|
->will($this->returnCallback(function($name) {
|
||||||
|
if($name === 'ldapUserFilter') {
|
||||||
|
return 'objectclass=inetorgperson';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
\OC_User::useBackend($backend);
|
\OC_User::useBackend($backend);
|
||||||
|
|
||||||
|
@ -1035,6 +1012,9 @@ class User_LDAPTest extends TestCase {
|
||||||
$this->access->expects($this->any())
|
$this->access->expects($this->any())
|
||||||
->method('getUserDnByUuid')
|
->method('getUserDnByUuid')
|
||||||
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
||||||
|
$this->access->expects($this->atLeastOnce())
|
||||||
|
->method('isRecordOnLDAP')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
//with displayName
|
//with displayName
|
||||||
$result = \OC::$server->getUserManager()->get('gunslinger')->getDisplayName();
|
$result = \OC::$server->getUserManager()->get('gunslinger')->getDisplayName();
|
||||||
|
|
Loading…
Reference in New Issue