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;
|
||||
/** @var IUserManager */
|
||||
private $ncUserManager;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
|
||||
public function __construct(
|
||||
Connection $connection,
|
||||
|
@ -113,6 +115,7 @@ class Access extends LDAPUtility {
|
|||
$this->helper = $helper;
|
||||
$this->config = $config;
|
||||
$this->ncUserManager = $ncUserManager;
|
||||
$this->logger = \OC::$server->getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,27 +261,18 @@ class Access extends LDAPUtility {
|
|||
* @param string $attribute
|
||||
* @param string $filter
|
||||
* @param int $maxResults
|
||||
* @return array|bool false if there was any error, true if an exists check
|
||||
* was performed and the requested DN found, array with the
|
||||
* returned data on a successful usual operation
|
||||
* @return array|bool false if there was any error
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
public function executeRead($cr, $dn, $attribute, $filter, $maxResults) {
|
||||
$this->initPagedSearch($filter, array($dn), array($attribute), $maxResults, 0);
|
||||
public function executeRead($cr, string $dn, string $attribute, string $filter, int $maxResults) {
|
||||
$this->initPagedSearch($filter, $dn, [$attribute], $maxResults, 0);
|
||||
$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 ($attribute !== '') {
|
||||
//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
|
||||
$this->logger->debug('readAttribute failed for DN {dn}', ['app' => 'user_ldap', 'dn' => $dn]);
|
||||
|
||||
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);
|
||||
if (!$this->ldap->isResource($er)) {
|
||||
//did not match the filter, return false
|
||||
|
@ -291,6 +285,25 @@ class Access extends LDAPUtility {
|
|||
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
|
||||
* data if present.
|
||||
|
@ -474,11 +487,9 @@ class Access extends LDAPUtility {
|
|||
* filter by doing read operations against the group entries. Returns an
|
||||
* array of DNs that match the filter.
|
||||
*
|
||||
* @param string[] $groupDNs
|
||||
* @return string[]
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
public function groupsMatchFilter($groupDNs) {
|
||||
public function groupsMatchFilter(array $groupDNs): array {
|
||||
$validGroupDNs = [];
|
||||
foreach($groupDNs as $dn) {
|
||||
$cacheKey = 'groupsMatchFilter-'.$dn;
|
||||
|
@ -497,8 +508,7 @@ class Access extends LDAPUtility {
|
|||
continue;
|
||||
}
|
||||
|
||||
$result = $this->readAttribute($dn, '', $this->connection->ldapGroupFilter);
|
||||
if(is_array($result)) {
|
||||
if($this->isRecordOnLDAP($dn, $this->connection->ldapGroupFilter)) {
|
||||
$this->connection->writeToCache($cacheKey, true);
|
||||
$validGroupDNs[] = $dn;
|
||||
} else {
|
||||
|
@ -966,18 +976,18 @@ class Access extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* executes an LDAP search, optimized for Users
|
||||
*
|
||||
* @param string $filter the LDAP filter for the search
|
||||
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
||||
* @param integer $limit
|
||||
* @param integer $offset
|
||||
* @return array with the search result
|
||||
*
|
||||
* Executes an LDAP search
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
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 = [];
|
||||
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;
|
||||
}
|
||||
|
@ -987,12 +997,13 @@ class Access extends LDAPUtility {
|
|||
* @param string|string[] $attr
|
||||
* @param int $limit
|
||||
* @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;
|
||||
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;
|
||||
}
|
||||
return $result;
|
||||
|
@ -1000,6 +1011,7 @@ class Access extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* executes an LDAP search, optimized for Groups
|
||||
*
|
||||
* @param string $filter the LDAP filter for the search
|
||||
* @param string|string[] $attr optional, when a certain attribute shall be filtered out
|
||||
* @param integer $limit
|
||||
|
@ -1007,27 +1019,26 @@ class Access extends LDAPUtility {
|
|||
* @return array with the search result
|
||||
*
|
||||
* 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 = [];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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;
|
||||
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;
|
||||
}
|
||||
return $result;
|
||||
|
@ -1036,14 +1047,14 @@ class Access extends LDAPUtility {
|
|||
/**
|
||||
* returns the number of available objects on the base DN
|
||||
*
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return int|bool
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
public function countObjects($limit = null, $offset = null) {
|
||||
public function countObjects(int $limit = null, int $offset = null) {
|
||||
$result = false;
|
||||
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;
|
||||
}
|
||||
return $result;
|
||||
|
@ -1073,27 +1084,26 @@ class Access extends LDAPUtility {
|
|||
if ($command == 'controlPagedResultResponse') {
|
||||
throw new \InvalidArgumentException('Invoker does not support controlPagedResultResponse, call LDAP Wrapper directly instead.');
|
||||
} else {
|
||||
return call_user_func_array(array($this->ldap, $command), $arguments);
|
||||
return call_user_func_array([$this->ldap, $command], $arguments);
|
||||
}
|
||||
};
|
||||
try {
|
||||
$ret = $doMethod();
|
||||
} catch (ServerNotAvailableException $e) {
|
||||
} /** @noinspection PhpRedundantCatchClauseInspection */
|
||||
catch (ServerNotAvailableException $e) {
|
||||
/* Server connection lost, attempt to reestablish it
|
||||
* Maybe implement exponential backoff?
|
||||
* 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();
|
||||
$cr = $this->connection->getConnectionResource();
|
||||
|
||||
if(!$this->ldap->isResource($cr)) {
|
||||
// Seems like we didn't find any resource.
|
||||
\OCP\Util::writeLog('user_ldap', "Could not $command, because resource is missing.", ILogger::DEBUG);
|
||||
$this->logger->debug('Could not {command}, because resource is missing', ['app' => 'user_ldap', 'command' => $command]);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$arguments[0] = array_pad([], count($arguments[0]), $cr);
|
||||
$ret = $doMethod();
|
||||
}
|
||||
return $ret;
|
||||
|
@ -1102,8 +1112,8 @@ class Access extends LDAPUtility {
|
|||
/**
|
||||
* retrieved. Results will according to the order in the array.
|
||||
*
|
||||
* @param $filter
|
||||
* @param $base
|
||||
* @param string $filter
|
||||
* @param string $base
|
||||
* @param string[]|string|null $attr
|
||||
* @param int $limit optional, maximum results to be counted
|
||||
* @param int $offset optional, a starting point
|
||||
|
@ -1111,9 +1121,9 @@ class Access extends LDAPUtility {
|
|||
* second | false if not successful
|
||||
* @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)) {
|
||||
$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
|
||||
|
@ -1121,30 +1131,30 @@ class Access extends LDAPUtility {
|
|||
if(!$this->ldap->isResource($cr)) {
|
||||
// Seems like we didn't find any resource.
|
||||
// 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;
|
||||
}
|
||||
|
||||
//check whether paged search should be attempted
|
||||
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, (int)$limit, $offset);
|
||||
|
||||
$linkResources = array_pad(array(), count($base), $cr);
|
||||
$sr = $this->invokeLDAPMethod('search', $linkResources, $base, $filter, $attr);
|
||||
$sr = $this->invokeLDAPMethod('search', $cr, $base, $filter, $attr);
|
||||
// cannot use $cr anymore, might have changed in the previous call!
|
||||
$error = $this->ldap->errno($this->connection->getConnectionResource());
|
||||
if(!is_array($sr) || $error !== 0) {
|
||||
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), ILogger::ERROR);
|
||||
if(!$this->ldap->isResource($sr) || $error !== 0) {
|
||||
$this->logger->debug('Attempt for Paging? {status}', ['app' => 'user_ldap', 'status' => $pagedSearchOK]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return array($sr, $pagedSearchOK);
|
||||
return [$sr, $pagedSearchOK];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 $limit maximum results to be counted
|
||||
* @param int $offset a starting point
|
||||
|
@ -1152,15 +1162,14 @@ class Access extends LDAPUtility {
|
|||
* @param bool $skipHandling required for paged search when cookies to
|
||||
* prior results need to be gained
|
||||
* @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;
|
||||
if($pagedSearchOK) {
|
||||
$cr = $this->connection->getConnectionResource();
|
||||
foreach($sr as $key => $res) {
|
||||
if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) {
|
||||
$this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
|
||||
}
|
||||
if($this->ldap->controlPagedResultResponse($cr, $sr, $cookie)) {
|
||||
$this->setPagedResultCookie($base, $filter, $limit, $offset, $cookie);
|
||||
}
|
||||
|
||||
//browsing through prior pages to get the cookie for the new one
|
||||
|
@ -1175,10 +1184,7 @@ class Access extends LDAPUtility {
|
|||
}
|
||||
} else {
|
||||
if(!is_null($limit) && (int)$this->connection->ldapPagingSize !== 0) {
|
||||
\OC::$server->getLogger()->debug(
|
||||
'Paged search was not available',
|
||||
[ 'app' => 'user_ldap' ]
|
||||
);
|
||||
$this->logger->debug('Paged search was not available', ['app' => 'user_ldap']);
|
||||
}
|
||||
}
|
||||
/* ++ 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
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
|
||||
\OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), ILogger::DEBUG);
|
||||
private function count(string $filter, string $base, $attr = null, int $limit = null, int $offset = null, bool $skipHandling = false) {
|
||||
$this->logger->debug('Count filter: {filter}', ['app' => 'user_ldap', 'filter' => $filter]);
|
||||
|
||||
$limitPerPage = (int)$this->connection->ldapPagingSize;
|
||||
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
||||
|
@ -1268,7 +1274,7 @@ class Access extends LDAPUtility {
|
|||
* @return array with the search result
|
||||
* @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;
|
||||
if(!is_null($limit) && $limit < $limitPerPage && $limit > 0) {
|
||||
$limitPerPage = $limit;
|
||||
|
@ -1281,7 +1287,7 @@ class Access extends LDAPUtility {
|
|||
* $findings['count'] < $limit
|
||||
*/
|
||||
$findings = [];
|
||||
$savedoffset = $offset;
|
||||
$savedOffset = $offset;
|
||||
do {
|
||||
$search = $this->executeSearch($filter, $base, $attr, $limitPerPage, $offset);
|
||||
if($search === false) {
|
||||
|
@ -1297,7 +1303,7 @@ class Access extends LDAPUtility {
|
|||
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limitPerPage,
|
||||
$offset, $pagedSearchOK,
|
||||
$skipHandling);
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
$iFoundItems = 0;
|
||||
|
@ -1312,13 +1318,13 @@ class Access extends LDAPUtility {
|
|||
$skipHandling);
|
||||
$offset += $limitPerPage;
|
||||
} while ($continue && $pagedSearchOK && ($limit === null || count($findings) < $limit));
|
||||
// reseting offset
|
||||
$offset = $savedoffset;
|
||||
// resetting offset
|
||||
$offset = $savedOffset;
|
||||
|
||||
// if we're here, probably no connection resource is returned.
|
||||
// to make Nextcloud behave nicely, we simply give back an empty array.
|
||||
if(is_null($findings)) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
if(!is_null($attr)) {
|
||||
|
@ -1951,14 +1957,8 @@ class Access extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* 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
|
||||
if(!empty($cookie) || $cookie === '0') {
|
||||
$cacheKey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . (int)$limit . '-' . (int)$offset;
|
||||
|
@ -1979,55 +1979,55 @@ class Access extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* @param string[] $attr optional, when a certain attribute shall be filtered outside
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return bool|true
|
||||
*
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
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;
|
||||
if ($limit !== 0) {
|
||||
$offset = (int)$offset; //can be null
|
||||
\OCP\Util::writeLog('user_ldap',
|
||||
'initializing paged search for Filter '.$filter.' base '.print_r($bases, true)
|
||||
.' attr '.print_r($attr, true). ' limit ' .$limit.' offset '.$offset,
|
||||
ILogger::DEBUG);
|
||||
$this->logger->debug(
|
||||
'initializing paged search for Filter {filter} base {base} attr {attr} limit {limit} offset {offset}',
|
||||
[
|
||||
'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
|
||||
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);
|
||||
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, 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;
|
||||
}
|
||||
//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 ++
|
||||
* We coudn't get paged searches working with our RHDS for login ($limit = 0),
|
||||
* due to pages with zero results.
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace OCA\User_LDAP;
|
|||
/**
|
||||
* @property int ldapPagingSize holds an integer
|
||||
* @property string ldapUserAvatarRule
|
||||
* @property string ldapEmailAttribute
|
||||
* @property string ldapUserDisplayName
|
||||
* @property string ldapUserFilter
|
||||
* @property string ldapGroupFilter
|
||||
* @property string[] ldapBase
|
||||
*/
|
||||
class Configuration {
|
||||
const AVATAR_PREFIX_DEFAULT = 'default';
|
||||
|
|
|
@ -45,12 +45,18 @@ use OCP\ILogger;
|
|||
*
|
||||
* @property string ldapHost
|
||||
* @property string ldapPort holds the port number
|
||||
* @property string ldapLoginFilter
|
||||
* @property string ldapUserFilter
|
||||
* @property string ldapUserDisplayName
|
||||
* @property string ldapUserDisplayName2
|
||||
* @property string ldapUserAvatarRule
|
||||
* @property string ldapGroupFilter
|
||||
* @property string ldapGidNumber
|
||||
* @property string ldapDynamicGroupMemberURL
|
||||
* @property boolean turnOnPasswordChange
|
||||
* @property string[] ldapBase
|
||||
* @property string[] ldapBaseUsers
|
||||
* @property string[] ldapBaseGroups
|
||||
* @property int|null ldapPagingSize holds an integer
|
||||
* @property bool|mixed|void ldapGroupMemberAssocAttr
|
||||
* @property string ldapUuidUserAttribute
|
||||
|
@ -60,6 +66,7 @@ use OCP\ILogger;
|
|||
* @property string ldapQuotaAttribute
|
||||
* @property string ldapQuotaDefault
|
||||
* @property string ldapEmailAttribute
|
||||
* @property string ldapDefaultPPolicyDN
|
||||
*/
|
||||
class Connection extends LDAPUtility {
|
||||
private $ldapConnectionRes = null;
|
||||
|
|
|
@ -45,7 +45,7 @@ use OC\Cache\CappedMemoryCache;
|
|||
use OCP\GroupInterface;
|
||||
use OCP\ILogger;
|
||||
|
||||
class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLDAP {
|
||||
class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP {
|
||||
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
|
||||
* 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);
|
||||
|
||||
if (empty($dynamicGroupMemberURL)) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
$dynamicMembers = array();
|
||||
$dynamicMembers = [];
|
||||
$memberURLs = $this->access->readAttribute(
|
||||
$dnGroup,
|
||||
$dynamicGroupMemberURL,
|
||||
|
@ -186,6 +184,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
);
|
||||
if ($memberURLs !== false) {
|
||||
// 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 2: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(&(o=HeadOffice)(uidNumber>=500))
|
||||
$pos = strpos($memberURLs[0], '(');
|
||||
|
@ -197,8 +196,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
$dynamicMembers[$value['dn'][0]] = 1;
|
||||
}
|
||||
} else {
|
||||
\OCP\Util::writeLog('user_ldap', 'No search filter found on member url '.
|
||||
'of group ' . $dnGroup, ILogger::DEBUG);
|
||||
\OC::$server->getLogger()->debug(
|
||||
'No search filter found on member url of group {dn}',
|
||||
['app' => 'user_ldap', 'dn' => $dnGroup]
|
||||
);
|
||||
}
|
||||
}
|
||||
return $dynamicMembers;
|
||||
|
@ -279,11 +280,13 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
|
||||
/**
|
||||
* translates a gidNumber into an ownCloud internal name
|
||||
*
|
||||
* @param string $gid as given by gidNumber on POSIX LDAP
|
||||
* @param string $dn a DN that belongs to the same domain as the group
|
||||
* @return string|bool
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function gidNumber2Name($gid, $dn) {
|
||||
public function gidNumber2Name(string $gid, string $dn) {
|
||||
$cacheKey = 'gidNumberToName' . $gid;
|
||||
$groupName = $this->access->connection->getFromCache($cacheKey);
|
||||
if(!is_null($groupName) && isset($groupName)) {
|
||||
|
@ -296,7 +299,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
'objectClass=posixGroup',
|
||||
$this->access->connection->ldapGidNumber . '=' . $gid
|
||||
]);
|
||||
$result = $this->access->searchGroups($filter, array('dn'), 1);
|
||||
$result = $this->access->searchGroups($filter, ['dn'], 1);
|
||||
if(empty($result)) {
|
||||
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
|
||||
*
|
||||
* @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 {
|
||||
$filter = $this->prepareFilterForUsersHasGidNumber($groupDN, $search);
|
||||
$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
|
||||
*
|
||||
* @param string $gid as given by primaryGroupID on AD
|
||||
* @param string $dn a DN that belongs to the same domain as the group
|
||||
* @return string|bool
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function primaryGroupID2Name($gid, $dn) {
|
||||
public function primaryGroupID2Name(string $gid, string $dn) {
|
||||
$cacheKey = 'primaryGroupIDtoName';
|
||||
$groupNames = $this->access->connection->getFromCache($cacheKey);
|
||||
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
|
||||
$filter = $this->access->combineFilterWithAnd(array(
|
||||
/** @noinspection SpellCheckingInspection */
|
||||
$filter = $this->access->combineFilterWithAnd([
|
||||
$this->access->connection->ldapGroupFilter,
|
||||
'objectsid=' . $domainObjectSid . '-' . $gid
|
||||
));
|
||||
$result = $this->access->searchGroups($filter, array('dn'), 1);
|
||||
]);
|
||||
$result = $this->access->searchGroups($filter, ['dn'], 1);
|
||||
if(empty($result)) {
|
||||
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
|
||||
*
|
||||
* @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 {
|
||||
$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;
|
||||
} catch (\Exception $e) {
|
||||
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
|
||||
*
|
||||
* @param string $gid the internal group name
|
||||
* @param string $search optional, a search string
|
||||
* @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)) {
|
||||
return $this->groupPluginManager->countUsersInGroup($gid, $search);
|
||||
}
|
||||
|
@ -900,6 +897,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
return $groupUsers;
|
||||
}
|
||||
$search = $this->access->escapeFilterPart($search, true);
|
||||
/** @noinspection SpellCheckingInspection */
|
||||
$isMemberUid =
|
||||
(strtolower($this->access->connection->ldapGroupMemberAssocAttr)
|
||||
=== 'memberuid');
|
||||
|
@ -912,14 +910,14 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
// and let it count.
|
||||
//For now this is not important, because the only use of this method
|
||||
//does not supply a search string
|
||||
$groupUsers = array();
|
||||
$groupUsers = [];
|
||||
foreach($members as $member) {
|
||||
if($isMemberUid) {
|
||||
//we got uids, need to get their DNs to 'translate' them to user names
|
||||
$filter = $this->access->combineFilterWithAnd(array(
|
||||
//we got UIDs, need to get their DNs to 'translate' them to user names
|
||||
$filter = $this->access->combineFilterWithAnd([
|
||||
str_replace('%uid', $member, $this->access->connection->ldapLoginFilter),
|
||||
$this->access->getFilterPartForUserSearch($search)
|
||||
));
|
||||
]);
|
||||
$ldap_users = $this->access->fetchListOfUsers($filter, 'dn', 1);
|
||||
if(count($ldap_users) < 1) {
|
||||
continue;
|
||||
|
@ -933,8 +931,8 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
continue;
|
||||
}
|
||||
// dn2username will also check if the users belong to the allowed base
|
||||
if($ocname = $this->access->dn2username($member)) {
|
||||
$groupUsers[] = $ocname;
|
||||
if($ncName = $this->access->dn2username($member)) {
|
||||
$groupUsers[] = $ncName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1044,8 +1042,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
|
||||
/**
|
||||
* check if a group exists
|
||||
*
|
||||
* @param string $gid
|
||||
* @return bool
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function groupExists($gid) {
|
||||
$groupExists = $this->access->connection->getFromCache('groupExists'.$gid);
|
||||
|
@ -1061,8 +1061,8 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
|
|||
return false;
|
||||
}
|
||||
|
||||
//if group really still exists, we will be able to read its objectclass
|
||||
if(!is_array($this->access->readAttribute($dn, ''))) {
|
||||
//if group really still exists, we will be able to read its objectClass
|
||||
if(!$this->access->isRecordOnLDAP($dn)) {
|
||||
$this->access->connection->writeToCache('groupExists'.$gid, false);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -620,8 +620,11 @@ class User {
|
|||
* called by a post_login hook to handle password expiry
|
||||
*
|
||||
* @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;
|
||||
if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
|
||||
return;//password expiry handling disabled
|
||||
|
@ -629,8 +632,8 @@ class User {
|
|||
$uid = $params['uid'];
|
||||
if(isset($uid) && $uid === $this->getUsername()) {
|
||||
//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])) {
|
||||
$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
|
||||
if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
|
||||
|
@ -646,7 +649,7 @@ class User {
|
|||
$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
|
||||
$result = $this->connection->getFromCache($cacheKey);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -662,10 +665,10 @@ class User {
|
|||
&&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
|
||||
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
||||
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
|
||||
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||
'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
|
||||
'user_ldap.renewPassword.showLoginFormInvalidPassword', ['user' => $uid]));
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
@ -673,7 +676,7 @@ class User {
|
|||
if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
|
||||
$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
|
||||
header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
|
||||
'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
|
||||
'user_ldap.renewPassword.showRenewPasswordForm', ['user' => $uid]));
|
||||
exit();
|
||||
}
|
||||
//handle password expiry warning
|
||||
|
|
|
@ -309,7 +309,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
|||
* @throws \Exception
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
*/
|
||||
public function userExistsOnLDAP($user) {
|
||||
public function userExistsOnLDAP($user): bool {
|
||||
if(is_string($user)) {
|
||||
$user = $this->access->userManager->get($user);
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
|||
|
||||
$dn = $user->getDN();
|
||||
//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 {
|
||||
$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
|
||||
if (!$uuid) {
|
||||
|
@ -327,7 +327,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
|||
}
|
||||
$newDn = $this->access->getUserDnByUuid($uuid);
|
||||
//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;
|
||||
}
|
||||
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
|
||||
|
|
|
@ -131,11 +131,15 @@ class Wizard extends LDAPUtility {
|
|||
return (string)$count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|WizardResult
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function countGroups() {
|
||||
$filter = $this->configuration->ldapGroupFilter;
|
||||
|
||||
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);
|
||||
return $this->result;
|
||||
}
|
||||
|
@ -195,27 +199,28 @@ class Wizard extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* counts users with a specified attribute
|
||||
* @param string $attr
|
||||
* @param bool $existsCheck
|
||||
*
|
||||
* @return int|bool
|
||||
* @throws ServerNotAvailableException
|
||||
*/
|
||||
public function countUsersWithAttribute($attr, $existsCheck = false) {
|
||||
if(!$this->checkRequirements(array('ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
))) {
|
||||
public function countUsersWithAttribute(string $attr, bool $existsCheck = false) {
|
||||
if(!$this->checkRequirements([
|
||||
'ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filter = $this->access->combineFilterWithAnd(array(
|
||||
$filter = $this->access->combineFilterWithAnd([
|
||||
$this->configuration->ldapUserFilter,
|
||||
$attr . '=*'
|
||||
));
|
||||
]);
|
||||
|
||||
$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
|
||||
*/
|
||||
public function detectUserDisplayNameAttribute() {
|
||||
if(!$this->checkRequirements(array('ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
))) {
|
||||
if(!$this->checkRequirements([
|
||||
'ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -247,7 +253,8 @@ class Wizard extends LDAPUtility {
|
|||
}
|
||||
|
||||
// first attribute that has at least one result wins
|
||||
$displayNameAttrs = array('displayname', 'cn');
|
||||
/** @noinspection SpellCheckingInspection */
|
||||
$displayNameAttrs = ['displayname', 'cn'];
|
||||
foreach ($displayNameAttrs as $attr) {
|
||||
$count = (int)$this->countUsersWithAttribute($attr, true);
|
||||
|
||||
|
@ -267,26 +274,26 @@ class Wizard extends LDAPUtility {
|
|||
* @return WizardResult|bool
|
||||
*/
|
||||
public function detectEmailAttribute() {
|
||||
if(!$this->checkRequirements(array('ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
))) {
|
||||
if(!$this->checkRequirements([
|
||||
'ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapUserFilter',
|
||||
])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$attr = $this->configuration->ldapEmailAttribute;
|
||||
$writeLog = false;
|
||||
if ($attr !== '') {
|
||||
$count = (int)$this->countUsersWithAttribute($attr, true);
|
||||
if($count > 0) {
|
||||
return false;
|
||||
}
|
||||
$writeLog = true;
|
||||
} else {
|
||||
$writeLog = false;
|
||||
}
|
||||
|
||||
$emailAttributes = array('mail', 'mailPrimaryAddress');
|
||||
$emailAttributes = ['mail', 'mailPrimaryAddress'];
|
||||
$winner = '';
|
||||
$maxUsers = 0;
|
||||
foreach($emailAttributes as $attr) {
|
||||
|
@ -300,9 +307,10 @@ class Wizard extends LDAPUtility {
|
|||
if($winner !== '') {
|
||||
$this->applyFind('ldap_email_attr', $winner);
|
||||
if($writeLog) {
|
||||
\OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
|
||||
'automatically been reset, because the original value ' .
|
||||
'did not return any results.', ILogger::INFO);
|
||||
\OC::$server->getLogger()->info(
|
||||
'The mail attribute has automatically been reset, because the original value did not return any results',
|
||||
['app' => 'user_ldap']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,15 +635,14 @@ class Wizard extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* @return bool|WizardResult
|
||||
* @param string $loginName
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testLoginName($loginName) {
|
||||
if(!$this->checkRequirements(array('ldapHost',
|
||||
public function testLoginName(string $loginName) {
|
||||
if(!$this->checkRequirements(['ldapHost',
|
||||
'ldapPort',
|
||||
'ldapBase',
|
||||
'ldapLoginFilter',
|
||||
))) {
|
||||
])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -654,6 +661,7 @@ class Wizard extends LDAPUtility {
|
|||
throw new \Exception($this->ldap->error($cr));
|
||||
}
|
||||
$filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
|
||||
/** @noinspection SpellCheckingInspection */
|
||||
$this->result->addChange('ldap_test_loginname', $users);
|
||||
$this->result->addChange('ldap_test_effective_filter', $filter);
|
||||
return $this->result;
|
||||
|
@ -832,11 +840,9 @@ class Wizard extends LDAPUtility {
|
|||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private function testBaseDN($base) {
|
||||
private function testBaseDN(string $base): bool {
|
||||
$cr = $this->getConnection();
|
||||
if(!$cr) {
|
||||
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
|
||||
//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)) {
|
||||
$errorNo = $this->ldap->errno($cr);
|
||||
$errorMsg = $this->ldap->error($cr);
|
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
|
||||
' Error '.$errorNo.': '.$errorMsg, ILogger::INFO);
|
||||
\OC::$server->getLogger()->info(
|
||||
'Wiz: Could not search base {base}, Error {errno}: {error}',
|
||||
['app' => 'user_ldap', 'base' => $base, 'errno' => $errorNo, 'error' => $errorMsg]
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$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
|
||||
* memberOf does work.
|
||||
*
|
||||
* @return bool true if it does, false otherwise
|
||||
* @throws ServerNotAvailableException
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function testMemberOf() {
|
||||
private function testMemberOf(): bool {
|
||||
$cr = $this->getConnection();
|
||||
if(!$cr) {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1131,9 +1139,9 @@ class Wizard extends LDAPUtility {
|
|||
* yields most result entries
|
||||
* @return array|false an array with the values on success, false otherwise
|
||||
*/
|
||||
public function cumulativeSearchOnAttribute($filters, $attr, $dnReadLimit = 3, &$maxF = null) {
|
||||
$dnRead = array();
|
||||
$foundItems = array();
|
||||
public function cumulativeSearchOnAttribute(array $filters, string $attr, int $dnReadLimit = 3, string &$maxF = null) {
|
||||
$dnRead = [];
|
||||
$foundItems = [];
|
||||
$maxEntries = 0;
|
||||
if(!is_array($this->configuration->ldapBase)
|
||||
|| !isset($this->configuration->ldapBase[0])) {
|
||||
|
@ -1154,7 +1162,7 @@ class Wizard extends LDAPUtility {
|
|||
continue;
|
||||
}
|
||||
// 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)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1178,7 +1186,7 @@ class Wizard extends LDAPUtility {
|
|||
if($dn === false || in_array($dn, $dnRead)) {
|
||||
continue;
|
||||
}
|
||||
$newItems = array();
|
||||
$newItems = [];
|
||||
$state = $this->getAttributeValuesFromEntry($attributes,
|
||||
$attr,
|
||||
$newItems);
|
||||
|
@ -1249,15 +1257,7 @@ class Wizard extends LDAPUtility {
|
|||
return $availableFeatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
private function getAttributeValuesFromEntry(array $result, string $attribute, array &$known): int {
|
||||
if(!is_array($result)
|
||||
|| !isset($result['count'])
|
||||
|| !$result['count'] > 0) {
|
||||
|
|
|
@ -559,7 +559,7 @@ class AccessTest extends TestCase {
|
|||
->method('search')
|
||||
->willReturn([$fakeSearchResultResource]);
|
||||
$this->ldap
|
||||
->expects($this->exactly(count($base)))
|
||||
->expects($this->exactly(1))
|
||||
->method('getEntries')
|
||||
->willReturn($fakeLdapEntries);
|
||||
|
||||
|
@ -571,7 +571,7 @@ class AccessTest extends TestCase {
|
|||
public function testSearchNoPagedSearch() {
|
||||
// scenario: no pages search, 1 search base
|
||||
$filter = 'objectClass=nextcloudUser';
|
||||
$base = ['ou=zombies,dc=foobar,dc=nextcloud,dc=com'];
|
||||
$base = 'ou=zombies,dc=foobar,dc=nextcloud,dc=com';
|
||||
|
||||
$fakeConnection = new \stdClass();
|
||||
$fakeSearchResultResource = new \stdClass();
|
||||
|
|
|
@ -105,9 +105,13 @@ class Group_LDAPTest extends TestCase {
|
|||
->method('groupname2dn')
|
||||
->will($this->returnValue('cn=group,dc=foo,dc=bar'));
|
||||
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->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
|
||||
$access->expects($this->once())
|
||||
|
@ -132,9 +136,9 @@ class Group_LDAPTest extends TestCase {
|
|||
|
||||
$access->expects($this->any())
|
||||
->method('fetchListOfUsers')
|
||||
->will($this->returnValue(array()));
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($name) {
|
||||
//the search operation will call readAttribute, thus we need
|
||||
|
@ -145,14 +149,21 @@ class Group_LDAPTest extends TestCase {
|
|||
if(strpos($name, 'u') === 0) {
|
||||
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())
|
||||
->method('dn2username')
|
||||
->will($this->returnCallback(function() {
|
||||
return 'foobar' . \OC::$server->getSecureRandom()->generate(7);
|
||||
}));
|
||||
$access->expects($this->any())
|
||||
->method('escapeFilterPart')
|
||||
->willReturnArgument(0);
|
||||
|
||||
$groupBackend = new GroupLDAP($access,$pluginManager);
|
||||
$users = $groupBackend->countUsersInGroup('group', '3');
|
||||
|
@ -262,10 +273,10 @@ class Group_LDAPTest extends TestCase {
|
|||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||
$attr = 'gidNumber';
|
||||
|
||||
$access->expects($this->once())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->with($dn, $attr)
|
||||
->will($this->returnValue(array('3117')));
|
||||
->will($this->returnValue(['3117']));
|
||||
|
||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||
|
||||
|
@ -283,7 +294,7 @@ class Group_LDAPTest extends TestCase {
|
|||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||
$attr = 'gidNumber';
|
||||
|
||||
$access->expects($this->once())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->with($dn, $attr)
|
||||
->will($this->returnValue(false));
|
||||
|
@ -416,10 +427,10 @@ class Group_LDAPTest extends TestCase {
|
|||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||
$attr = 'primaryGroupToken';
|
||||
|
||||
$access->expects($this->once())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->with($dn, $attr)
|
||||
->will($this->returnValue(array('3117')));
|
||||
->will($this->returnValue(['3117']));
|
||||
|
||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||
|
||||
|
@ -439,7 +450,7 @@ class Group_LDAPTest extends TestCase {
|
|||
$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
|
||||
$attr = 'primaryGroupToken';
|
||||
|
||||
$access->expects($this->once())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->with($dn, $attr)
|
||||
->will($this->returnValue(false));
|
||||
|
@ -506,16 +517,20 @@ class Group_LDAPTest extends TestCase {
|
|||
$access->connection->expects($this->any())
|
||||
->method('getFromCache')
|
||||
->will($this->returnValue(null));
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
if($attr === 'primaryGroupToken') {
|
||||
return array(1337);
|
||||
return [1337];
|
||||
} else if($attr === 'gidNumber') {
|
||||
return [4211];
|
||||
}
|
||||
return array();
|
||||
return [];
|
||||
}));
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->with($this->anything())
|
||||
->willReturn(true);
|
||||
$access->expects($this->any())
|
||||
->method('groupname2dn')
|
||||
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
||||
|
@ -543,20 +558,24 @@ class Group_LDAPTest extends TestCase {
|
|||
$access->connection->expects($this->any())
|
||||
->method('getFromCache')
|
||||
->will($this->returnValue(null));
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
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())
|
||||
->method('groupname2dn')
|
||||
->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
|
||||
$access->expects($this->once())
|
||||
->method('nextcloudUserNames')
|
||||
->will($this->returnValue(array('lisa', 'bart', 'kira', 'brad')));
|
||||
->will($this->returnValue(['lisa', 'bart', 'kira', 'brad']));
|
||||
$access->userManager = $this->createMock(Manager::class);
|
||||
|
||||
$groupBackend = new GroupLDAP($access, $pluginManager);
|
||||
|
@ -579,15 +598,20 @@ class Group_LDAPTest extends TestCase {
|
|||
->method('getFromCache')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
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())
|
||||
->method('groupname2dn')
|
||||
->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) {
|
||||
$access = $this->getAccessMock();
|
||||
$access->expects($this->any())
|
||||
$access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->willReturnCallback(function($group) use ($groupDN, $expectedMembers, $groupsInfo) {
|
||||
if(isset($groupsInfo[$group])) {
|
||||
|
|
|
@ -545,7 +545,7 @@ class UserTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testUpdateAvatarThumbnailPhotoProvided() {
|
||||
$this->access->expects($this->any())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->willReturnCallback(function($dn, $attr) {
|
||||
if($dn === $this->dn
|
||||
|
@ -599,7 +599,7 @@ class UserTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testUpdateAvatarCorruptPhotoProvided() {
|
||||
$this->access->expects($this->any())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->willReturnCallback(function($dn, $attr) {
|
||||
if($dn === $this->dn
|
||||
|
@ -645,7 +645,7 @@ class UserTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testUpdateAvatarUnsupportedThumbnailPhotoProvided() {
|
||||
$this->access->expects($this->any())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->willReturnCallback(function($dn, $attr) {
|
||||
if($dn === $this->dn
|
||||
|
@ -700,7 +700,7 @@ class UserTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testUpdateAvatarNotProvided() {
|
||||
$this->access->expects($this->any())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->willReturnCallback(function($dn, $attr) {
|
||||
if($dn === $this->dn
|
||||
|
@ -962,7 +962,7 @@ class UserTest extends \Test\TestCase {
|
|||
->with($this->equalTo('homeFolderNamingRule'))
|
||||
->will($this->returnValue('attr:foobar'));
|
||||
|
||||
$this->access->expects($this->once())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
|
@ -984,7 +984,7 @@ class UserTest extends \Test\TestCase {
|
|||
->with($this->equalTo('homeFolderNamingRule'))
|
||||
->will($this->returnValue('attr:foobar'));
|
||||
|
||||
$this->access->expects($this->once())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
|
@ -1066,7 +1066,7 @@ class UserTest extends \Test\TestCase {
|
|||
$this->access->expects($this->any())
|
||||
->method('search')
|
||||
->will($this->returnCallback(function($filter, $base) {
|
||||
if($base === [$this->dn]) {
|
||||
if($base === $this->dn) {
|
||||
return [
|
||||
[
|
||||
'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 [
|
||||
[
|
||||
'pwdmaxage' => ['2592000'],
|
||||
|
@ -1129,7 +1129,7 @@ class UserTest extends \Test\TestCase {
|
|||
$this->access->expects($this->any())
|
||||
->method('search')
|
||||
->will($this->returnCallback(function($filter, $base) {
|
||||
if($base === [$this->dn]) {
|
||||
if($base === $this->dn) {
|
||||
return [
|
||||
[
|
||||
'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 [
|
||||
[
|
||||
'pwdmaxage' => ['2592000'],
|
||||
|
|
|
@ -494,14 +494,11 @@ class User_LDAPTest extends TestCase {
|
|||
->method('getDN')
|
||||
->willReturn('dnOfRoland,dc=test');
|
||||
|
||||
$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->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->with('dnOfRoland,dc=test')
|
||||
->willReturn(true);
|
||||
|
||||
$this->userManager->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn($user);
|
||||
|
@ -509,6 +506,15 @@ class User_LDAPTest extends TestCase {
|
|||
->method('getUserMapper')
|
||||
->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
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$result = $backend->userExists('gunslinger');
|
||||
|
@ -525,14 +531,6 @@ class User_LDAPTest extends TestCase {
|
|||
->with('dnOfFormerUser,dc=test')
|
||||
->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())
|
||||
->method('getUserMapper')
|
||||
->willReturn($mapper);
|
||||
|
@ -549,6 +547,16 @@ class User_LDAPTest extends TestCase {
|
|||
->method('get')
|
||||
->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
|
||||
$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);
|
||||
$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
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$result = $backend->userExists('mallory');
|
||||
|
@ -582,14 +581,11 @@ class User_LDAPTest extends TestCase {
|
|||
->method('getDN')
|
||||
->willReturn('dnOfRoland,dc=test');
|
||||
|
||||
$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->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->with('dnOfRoland,dc=test')
|
||||
->willReturn(true);
|
||||
|
||||
$this->userManager->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->willReturn($user);
|
||||
|
@ -597,6 +593,16 @@ class User_LDAPTest extends TestCase {
|
|||
->method('getUserMapper')
|
||||
->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
|
||||
$result = \OC::$server->getUserManager()->userExists('gunslinger');
|
||||
$this->assertTrue($result);
|
||||
|
@ -613,14 +619,6 @@ class User_LDAPTest extends TestCase {
|
|||
->with('dnOfFormerUser,dc=test')
|
||||
->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())
|
||||
->method('getUserMapper')
|
||||
->willReturn($mapper);
|
||||
|
@ -637,6 +635,16 @@ class User_LDAPTest extends TestCase {
|
|||
->method('get')
|
||||
->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
|
||||
$this->assertFalse(\OC::$server->getUserManager()->userExists('formerUser'));
|
||||
}
|
||||
|
@ -646,15 +654,6 @@ class User_LDAPTest extends TestCase {
|
|||
$this->prepareMockForUserExists();
|
||||
\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
|
||||
$result = \OC::$server->getUserManager()->userExists('mallory');
|
||||
$this->assertFalse($result);
|
||||
|
@ -677,24 +676,16 @@ class User_LDAPTest extends TestCase {
|
|||
->will($this->returnCallback(function($name) {
|
||||
if($name === 'homeFolderNamingRule') {
|
||||
return 'attr:testAttribute';
|
||||
} elseif ($name === 'ldapUserFilter') {
|
||||
return 'objectclass=inetorgperson';
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
|
||||
$this->access->expects($this->any())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
switch ($dn) {
|
||||
case 'dnOfRoland,dc=test':
|
||||
if($attr === 'testAttribute') {
|
||||
return array('/tmp/rolandshome/');
|
||||
}
|
||||
return array();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->with('dnOfRoland,dc=test')
|
||||
->willReturn(true);
|
||||
|
||||
$user = $this->createMock(User::class);
|
||||
$user->expects($this->any())
|
||||
|
@ -729,24 +720,16 @@ class User_LDAPTest extends TestCase {
|
|||
->will($this->returnCallback(function($name) {
|
||||
if($name === 'homeFolderNamingRule') {
|
||||
return 'attr:testAttribute';
|
||||
} else if ($name === 'ldapUserFilter') {
|
||||
return 'objectclass=inetorgperson';
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
|
||||
$this->access->expects($this->any())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
switch ($dn) {
|
||||
case 'dnOfLadyOfShadows,dc=test':
|
||||
if($attr === 'testAttribute') {
|
||||
return array('susannah/');
|
||||
}
|
||||
return array();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->with('dnOfLadyOfShadows,dc=test')
|
||||
->willReturn(true);
|
||||
|
||||
$user = $this->createMock(User::class);
|
||||
$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);
|
||||
$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())
|
||||
->method('getFromCache')
|
||||
->willReturnCallback(function($key) {
|
||||
|
@ -835,10 +802,6 @@ class User_LDAPTest extends TestCase {
|
|||
return null;
|
||||
}));
|
||||
|
||||
$this->access->expects($this->any())
|
||||
->method('readAttribute')
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$userMapper = $this->createMock(UserMapping::class);
|
||||
|
||||
$this->access->expects($this->any())
|
||||
|
@ -886,11 +849,13 @@ class User_LDAPTest extends TestCase {
|
|||
->will($this->returnCallback(function($name) {
|
||||
if($name === 'ldapUserDisplayName') {
|
||||
return 'displayname';
|
||||
} elseif ($name === 'ldapUserFilter') {
|
||||
return 'objectclass=inetorgperson';
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
|
||||
$this->access->expects($this->any())
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('readAttribute')
|
||||
->will($this->returnCallback(function($dn, $attr) {
|
||||
switch ($dn) {
|
||||
|
@ -957,6 +922,10 @@ class User_LDAPTest extends TestCase {
|
|||
->method('getUserDnByUuid')
|
||||
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
||||
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->willReturn(true);
|
||||
|
||||
//with displayName
|
||||
$result = $backend->getDisplayName('gunslinger');
|
||||
$this->assertEquals('Roland Deschain', $result);
|
||||
|
@ -996,6 +965,14 @@ class User_LDAPTest extends TestCase {
|
|||
->will($this->returnCallback(function() {
|
||||
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);
|
||||
|
||||
|
@ -1035,6 +1012,9 @@ class User_LDAPTest extends TestCase {
|
|||
$this->access->expects($this->any())
|
||||
->method('getUserDnByUuid')
|
||||
->willReturnCallback(function($uuid) { return $uuid . '1'; });
|
||||
$this->access->expects($this->atLeastOnce())
|
||||
->method('isRecordOnLDAP')
|
||||
->willReturn(true);
|
||||
|
||||
//with displayName
|
||||
$result = \OC::$server->getUserManager()->get('gunslinger')->getDisplayName();
|
||||
|
|
Loading…
Reference in New Issue