summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblizzz <blizzz@arthur-schiwon.de>2016-07-28 10:14:34 +0200
committerGitHub <noreply@github.com>2016-07-28 10:14:34 +0200
commit73311091bf27fc3f0bbc16652c73d1cf7dfb7586 (patch)
tree249e6225b2a234f3940a18af203e312b4de336ce
parentabdf8c2c841832d79914f4e245e9466e6d3dd2c5 (diff)
parentbd65a17203a8eef4efa542c9d72dc3316008d9a6 (diff)
downloadnextcloud-server-73311091bf27fc3f0bbc16652c73d1cf7dfb7586.tar.gz
nextcloud-server-73311091bf27fc3f0bbc16652c73d1cf7dfb7586.zip
Merge pull request #519 from GitHubUser4234/master
New LDAPProvider for user_ldap
-rw-r--r--apps/user_ldap/ajax/wizard.php2
-rw-r--r--apps/user_ldap/appinfo/app.php2
-rw-r--r--apps/user_ldap/appinfo/install.php4
-rw-r--r--apps/user_ldap/appinfo/update.php24
-rw-r--r--apps/user_ldap/lib/Access.php73
-rw-r--r--apps/user_ldap/lib/Connection.php6
-rw-r--r--apps/user_ldap/lib/Helper.php65
-rw-r--r--apps/user_ldap/lib/IUserLDAP.php49
-rw-r--r--apps/user_ldap/lib/Jobs/UpdateGroups.php2
-rw-r--r--apps/user_ldap/lib/LDAPProvider.php188
-rw-r--r--apps/user_ldap/lib/LDAPProviderFactory.php59
-rw-r--r--apps/user_ldap/lib/Proxy.php2
-rw-r--r--apps/user_ldap/lib/User_LDAP.php35
-rw-r--r--apps/user_ldap/lib/User_Proxy.php32
-rw-r--r--apps/user_ldap/tests/AccessTest.php51
-rw-r--r--apps/user_ldap/tests/Group_LDAPTest.php3
-rw-r--r--apps/user_ldap/tests/Integration/AbstractIntegrationTest.php14
-rw-r--r--apps/user_ldap/tests/LDAPProviderTest.php338
-rw-r--r--apps/user_ldap/tests/User/UserTest.php3
-rw-r--r--apps/user_ldap/tests/User_LDAPTest.php4
-rw-r--r--apps/user_ldap/tests/WizardTest.php3
-rw-r--r--lib/private/Server.php19
-rw-r--r--lib/public/LDAP/IDeletionFlagSupport.php45
-rw-r--r--lib/public/LDAP/ILDAPProvider.php105
-rw-r--r--lib/public/LDAP/ILDAPProviderFactory.php53
25 files changed, 1084 insertions, 97 deletions
diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php
index b5eab90af48..654fb70ced5 100644
--- a/apps/user_ldap/ajax/wizard.php
+++ b/apps/user_ldap/ajax/wizard.php
@@ -60,7 +60,7 @@ $userManager = new \OCA\User_LDAP\User\Manager(
\OC::$server->getDatabaseConnection(),
\OC::$server->getUserManager());
-$access = new \OCA\User_LDAP\Access($con, $ldapWrapper, $userManager);
+$access = new \OCA\User_LDAP\Access($con, $ldapWrapper, $userManager, new \OCA\User_LDAP\Helper());
$wizard = new \OCA\User_LDAP\Wizard($configuration, $ldapWrapper, $access);
diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php
index 18987614bdb..10cc003a3f5 100644
--- a/apps/user_ldap/appinfo/app.php
+++ b/apps/user_ldap/appinfo/app.php
@@ -44,7 +44,7 @@ if(count($configPrefixes) === 1) {
\OC::$server->getUserManager()
);
$connector = new OCA\User_LDAP\Connection($ldapWrapper, $configPrefixes[0]);
- $ldapAccess = new OCA\User_LDAP\Access($connector, $ldapWrapper, $userManager);
+ $ldapAccess = new OCA\User_LDAP\Access($connector, $ldapWrapper, $userManager, $helper);
$ldapAccess->setUserMapper(new OCA\User_LDAP\Mapping\UserMapping($dbc));
$ldapAccess->setGroupMapper(new OCA\User_LDAP\Mapping\GroupMapping($dbc));
diff --git a/apps/user_ldap/appinfo/install.php b/apps/user_ldap/appinfo/install.php
index b3c92b0024a..c16a1f4a039 100644
--- a/apps/user_ldap/appinfo/install.php
+++ b/apps/user_ldap/appinfo/install.php
@@ -4,6 +4,7 @@
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christopher Schäpers <kondou@ts.unde.re>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -24,3 +25,6 @@ $state = OCP\Config::getSystemValue('ldapIgnoreNamingRules', 'doSet');
if($state === 'doSet') {
OCP\Config::setSystemValue('ldapIgnoreNamingRules', false);
}
+
+$helper = new \OCA\User_LDAP\Helper();
+$helper->setLDAPProvider();
diff --git a/apps/user_ldap/appinfo/update.php b/apps/user_ldap/appinfo/update.php
new file mode 100644
index 00000000000..3c9745338e6
--- /dev/null
+++ b/apps/user_ldap/appinfo/update.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+$helper = new \OCA\User_LDAP\Helper();
+$helper->setLDAPProvider();
diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php
index dabf243eda1..299ad581644 100644
--- a/apps/user_ldap/lib/Access.php
+++ b/apps/user_ldap/lib/Access.php
@@ -20,6 +20,7 @@
* @author Ralph Krimmel <rkrimme1@gwdg.de>
* @author Renaud Fortier <Renaud.Fortier@fsaa.ulaval.ca>
* @author Robin McCorkell <robin@mccorkell.me.uk>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -77,13 +78,19 @@ class Access extends LDAPUtility implements IUserTools {
* @var AbstractMapping $userMapper
*/
protected $groupMapper;
+
+ /**
+ * @var \OCA\User_LDAP\Helper
+ */
+ private $helper;
public function __construct(Connection $connection, ILDAPWrapper $ldap,
- Manager $userManager) {
+ Manager $userManager, Helper $helper) {
parent::__construct($ldap);
$this->connection = $connection;
$this->userManager = $userManager;
$this->userManager->setLdapAccess($this);
+ $this->helper = $helper;
}
/**
@@ -173,7 +180,7 @@ class Access extends LDAPUtility implements IUserTools {
// (cf. #12306), 500 is default for paging and should work everywhere.
$maxResults = $pagingSize > 20 ? $pagingSize : 500;
$this->initPagedSearch($filter, array($dn), array($attr), $maxResults, 0);
- $dn = $this->DNasBaseParameter($dn);
+ $dn = $this->helper->DNasBaseParameter($dn);
$rr = @$this->ldap->read($cr, $dn, $filter, array($attr));
if(!$this->ldap->isResource($rr)) {
if(!empty($attr)) {
@@ -201,7 +208,7 @@ class Access extends LDAPUtility implements IUserTools {
$values = array();
for($i=0;$i<$result[$attr]['count'];$i++) {
if($this->resemblesDN($attr)) {
- $values[] = $this->sanitizeDN($result[$attr][$i]);
+ $values[] = $this->helper->sanitizeDN($result[$attr][$i]);
} elseif(strtolower($attr) === 'objectguid' || strtolower($attr) === 'guid') {
$values[] = $this->convertObjectGUID2Str($result[$attr][$i]);
} else {
@@ -243,49 +250,6 @@ class Access extends LDAPUtility implements IUserTools {
}
/**
- * sanitizes a DN received from the LDAP server
- * @param array $dn the DN in question
- * @return array the sanitized DN
- */
- private function sanitizeDN($dn) {
- //treating multiple base DNs
- if(is_array($dn)) {
- $result = array();
- foreach($dn as $singleDN) {
- $result[] = $this->sanitizeDN($singleDN);
- }
- return $result;
- }
-
- //OID sometimes gives back DNs with whitespace after the comma
- // a la "uid=foo, cn=bar, dn=..." We need to tackle this!
- $dn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn);
-
- //make comparisons and everything work
- $dn = mb_strtolower($dn, 'UTF-8');
-
- //escape DN values according to RFC 2253 – this is already done by ldap_explode_dn
- //to use the DN in search filters, \ needs to be escaped to \5c additionally
- //to use them in bases, we convert them back to simple backslashes in readAttribute()
- $replacements = array(
- '\,' => '\5c2C',
- '\=' => '\5c3D',
- '\+' => '\5c2B',
- '\<' => '\5c3C',
- '\>' => '\5c3E',
- '\;' => '\5c3B',
- '\"' => '\5c22',
- '\#' => '\5c23',
- '(' => '\28',
- ')' => '\29',
- '*' => '\2A',
- );
- $dn = str_replace(array_keys($replacements), array_values($replacements), $dn);
-
- return $dn;
- }
-
- /**
* returns a DN-string that is cleaned from not domain parts, e.g.
* cn=foo,cn=bar,dc=foobar,dc=server,dc=org
* becomes dc=foobar,dc=server,dc=org
@@ -1071,10 +1035,10 @@ class Access extends LDAPUtility implements IUserTools {
}
if($key !== 'dn') {
$selection[$i][$key] = $this->resemblesDN($key) ?
- $this->sanitizeDN($item[$key])
+ $this->helper->sanitizeDN($item[$key])
: $item[$key];
} else {
- $selection[$i][$key] = [$this->sanitizeDN($item[$key])];
+ $selection[$i][$key] = [$this->helper->sanitizeDN($item[$key])];
}
}
@@ -1298,7 +1262,7 @@ class Access extends LDAPUtility implements IUserTools {
* @return bool
*/
public function areCredentialsValid($name, $password) {
- $name = $this->DNasBaseParameter($name);
+ $name = $this->helper->DNasBaseParameter($name);
$testConnection = clone $this->connection;
$credentials = array(
'ldapAgentName' => $name,
@@ -1570,15 +1534,6 @@ class Access extends LDAPUtility implements IUserTools {
}
/**
- * converts a stored DN so it can be used as base parameter for LDAP queries, internally we store them for usage in LDAP filters
- * @param string $dn the DN
- * @return string
- */
- private function DNasBaseParameter($dn) {
- return str_ireplace('\\5c', '\\', $dn);
- }
-
- /**
* checks if the given DN is part of the given base DN(s)
* @param string $dn the DN
* @param string[] $bases array containing the allowed base DN or DNs
@@ -1586,7 +1541,7 @@ class Access extends LDAPUtility implements IUserTools {
*/
public function isDNPartOfBase($dn, $bases) {
$belongsToBase = false;
- $bases = $this->sanitizeDN($bases);
+ $bases = $this->helper->sanitizeDN($bases);
foreach($bases as $base) {
$belongsToBase = true;
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 7bd5e97e4f4..7fb26526195 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -11,6 +11,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Robin McCorkell <robin@mccorkell.me.uk>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -52,6 +53,8 @@ class Connection extends LDAPUtility {
private $configID;
private $configured = false;
private $hasPagedResultSupport = true;
+ //whether connection should be kept on __destruct
+ private $dontDestruct = false;
/**
* @var bool runtime flag that indicates whether supported primary groups are available
@@ -93,7 +96,7 @@ class Connection extends LDAPUtility {
}
public function __destruct() {
- if($this->ldap->isResource($this->ldapConnectionRes)) {
+ if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
@$this->ldap->unbind($this->ldapConnectionRes);
};
}
@@ -105,6 +108,7 @@ class Connection extends LDAPUtility {
$this->configuration = new Configuration($this->configPrefix,
!is_null($this->configID));
$this->ldapConnectionRes = null;
+ $this->dontDestruct = true;
}
/**
diff --git a/apps/user_ldap/lib/Helper.php b/apps/user_ldap/lib/Helper.php
index ccc1d2c0b44..90807a3c526 100644
--- a/apps/user_ldap/lib/Helper.php
+++ b/apps/user_ldap/lib/Helper.php
@@ -10,6 +10,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -183,6 +184,70 @@ class Helper {
return $domain;
}
+
+ /**
+ *
+ * Set the LDAPProvider in the config
+ *
+ */
+ public function setLDAPProvider() {
+ $current = \OC::$server->getConfig()->getSystemValue('ldapProviderFactory', null);
+ if(is_null($current)) {
+ \OC::$server->getConfig()->setSystemValue('ldapProviderFactory', '\\OCA\\User_LDAP\\LDAPProviderFactory');
+ }
+ }
+
+ /**
+ * sanitizes a DN received from the LDAP server
+ * @param array $dn the DN in question
+ * @return array the sanitized DN
+ */
+ public function sanitizeDN($dn) {
+ //treating multiple base DNs
+ if(is_array($dn)) {
+ $result = array();
+ foreach($dn as $singleDN) {
+ $result[] = $this->sanitizeDN($singleDN);
+ }
+ return $result;
+ }
+
+ //OID sometimes gives back DNs with whitespace after the comma
+ // a la "uid=foo, cn=bar, dn=..." We need to tackle this!
+ $dn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn);
+
+ //make comparisons and everything work
+ $dn = mb_strtolower($dn, 'UTF-8');
+
+ //escape DN values according to RFC 2253 – this is already done by ldap_explode_dn
+ //to use the DN in search filters, \ needs to be escaped to \5c additionally
+ //to use them in bases, we convert them back to simple backslashes in readAttribute()
+ $replacements = array(
+ '\,' => '\5c2C',
+ '\=' => '\5c3D',
+ '\+' => '\5c2B',
+ '\<' => '\5c3C',
+ '\>' => '\5c3E',
+ '\;' => '\5c3B',
+ '\"' => '\5c22',
+ '\#' => '\5c23',
+ '(' => '\28',
+ ')' => '\29',
+ '*' => '\2A',
+ );
+ $dn = str_replace(array_keys($replacements), array_values($replacements), $dn);
+
+ return $dn;
+ }
+
+ /**
+ * converts a stored DN so it can be used as base parameter for LDAP queries, internally we store them for usage in LDAP filters
+ * @param string $dn the DN
+ * @return string
+ */
+ public function DNasBaseParameter($dn) {
+ return str_ireplace('\\5c', '\\', $dn);
+ }
/**
* listens to a hook thrown by server2server sharing and replaces the given
diff --git a/apps/user_ldap/lib/IUserLDAP.php b/apps/user_ldap/lib/IUserLDAP.php
new file mode 100644
index 00000000000..cb7d0138892
--- /dev/null
+++ b/apps/user_ldap/lib/IUserLDAP.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\User_LDAP;
+
+interface IUserLDAP {
+
+ //Functions used by LDAPProvider
+
+ /**
+ * Return access for LDAP interaction.
+ * @param string $uid
+ * @return Access instance of Access for LDAP interaction
+ */
+ public function getLDAPAccess($uid);
+
+ /**
+ * Return a new LDAP connection for the specified user.
+ * @param string $uid
+ * @return resource of the LDAP connection
+ */
+ public function getNewLDAPConnection($uid);
+
+ /**
+ * Return the username for the given LDAP DN, if available.
+ * @param string $dn
+ * @return string|false with the username
+ */
+ public function dn2UserName($dn);
+}
diff --git a/apps/user_ldap/lib/Jobs/UpdateGroups.php b/apps/user_ldap/lib/Jobs/UpdateGroups.php
index 91d40d58742..047b95a6d9b 100644
--- a/apps/user_ldap/lib/Jobs/UpdateGroups.php
+++ b/apps/user_ldap/lib/Jobs/UpdateGroups.php
@@ -188,7 +188,7 @@ class UpdateGroups extends \OC\BackgroundJob\TimedJob {
$dbc,
\OC::$server->getUserManager());
$connector = new Connection($ldapWrapper, $configPrefixes[0]);
- $ldapAccess = new Access($connector, $ldapWrapper, $userManager);
+ $ldapAccess = new Access($connector, $ldapWrapper, $userManager, $helper);
$groupMapper = new GroupMapping($dbc);
$userMapper = new UserMapping($dbc);
$ldapAccess->setGroupMapper($groupMapper);
diff --git a/apps/user_ldap/lib/LDAPProvider.php b/apps/user_ldap/lib/LDAPProvider.php
new file mode 100644
index 00000000000..5bd6a0fd08c
--- /dev/null
+++ b/apps/user_ldap/lib/LDAPProvider.php
@@ -0,0 +1,188 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\User_LDAP;
+
+use OCP\IUserBackend;
+use OCP\LDAP\ILDAPProvider;
+use OCP\LDAP\IDeletionFlagSupport;
+use OCP\IServerContainer;
+use OCA\User_LDAP\User\DeletedUsersIndex;
+use OCA\User_LDAP\Mapping\UserMapping;
+
+/**
+ * LDAP provider for pulic access to the LDAP backend.
+ */
+class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport {
+
+ private $backend;
+ private $logger;
+ private $helper;
+ private $deletedUsersIndex;
+
+ /**
+ * Create new LDAPProvider
+ * @param \OCP\IServerContainer $serverContainer
+ * @throws \Exception if user_ldap app was not enabled
+ */
+ public function __construct(IServerContainer $serverContainer, Helper $helper, DeletedUsersIndex $deletedUsersIndex) {
+ $this->logger = $serverContainer->getLogger();
+ $this->helper = $helper;
+ $this->deletedUsersIndex = $deletedUsersIndex;
+ foreach ($serverContainer->getUserManager()->getBackends() as $backend){
+ $this->logger->debug('instance '.get_class($backend).' backend.', ['app' => 'user_ldap']);
+ if ($backend instanceof IUserLDAP) {
+ $this->backend = $backend;
+ return;
+ }
+ }
+ throw new \Exception('To use the LDAPProvider, user_ldap app must be enabled');
+ }
+
+ /**
+ * Translate an user id to LDAP DN
+ * @param string $uid user id
+ * @return string with the LDAP DN
+ * @throws \Exception if translation was unsuccessful
+ */
+ public function getUserDN($uid) {
+ if(!$this->backend->userExists($uid)){
+ throw new \Exception('User id not found in LDAP');
+ }
+ $result = $this->backend->getLDAPAccess($uid)->username2dn($uid);
+ if(!$result){
+ throw new \Exception('Translation to LDAP DN unsuccessful');
+ }
+ return $result;
+ }
+
+ /**
+ * Translate a LDAP DN to an internal user name. If there is no mapping between
+ * the DN and the user name, a new one will be created.
+ * @param string $dn LDAP DN
+ * @return string with the internal user name
+ * @throws \Exception if translation was unsuccessful
+ */
+ public function getUserName($dn) {
+ $result = $this->backend->dn2UserName($dn);
+ if(!$result){
+ throw new \Exception('Translation to internal user name unsuccessful');
+ }
+ return $result;
+ }
+
+ /**
+ * Convert a stored DN so it can be used as base parameter for LDAP queries.
+ * @param string $dn the DN in question
+ * @return string
+ */
+ public function DNasBaseParameter($dn) {
+ return $this->helper->DNasBaseParameter($dn);
+ }
+
+ /**
+ * Sanitize a DN received from the LDAP server.
+ * @param array $dn the DN in question
+ * @return array the sanitized DN
+ */
+ public function sanitizeDN($dn) {
+ return $this->helper->sanitizeDN($dn);
+ }
+
+ /**
+ * Return a new LDAP connection resource for the specified user.
+ * The connection must be closed manually.
+ * @param string $uid user id
+ * @return resource of the LDAP connection
+ * @throws \Exception if user id was not found in LDAP
+ */
+ public function getLDAPConnection($uid) {
+ if(!$this->backend->userExists($uid)){
+ throw new \Exception('User id not found in LDAP');
+ }
+ return $this->backend->getNewLDAPConnection($uid);
+ }
+
+ /**
+ * Get the LDAP base for users.
+ * @param string $uid user id
+ * @return string the base for users
+ * @throws \Exception if user id was not found in LDAP
+ */
+ public function getLDAPBaseUsers($uid) {
+ if(!$this->backend->userExists($uid)){
+ throw new \Exception('User id not found in LDAP');
+ }
+ return $this->backend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_users'];
+ }
+
+ /**
+ * Get the LDAP base for groups.
+ * @param string $uid user id
+ * @return string the base for groups
+ * @throws \Exception if user id was not found in LDAP
+ */
+ public function getLDAPBaseGroups($uid) {
+ if(!$this->backend->userExists($uid)){
+ throw new \Exception('User id not found in LDAP');
+ }
+ return $this->backend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_groups'];
+ }
+
+ /**
+ * Clear the cache if a cache is used, otherwise do nothing.
+ * @param string $uid user id
+ * @throws \Exception if user id was not found in LDAP
+ */
+ public function clearCache($uid) {
+ if(!$this->backend->userExists($uid)){
+ throw new \Exception('User id not found in LDAP');
+ }
+ $this->backend->getLDAPAccess($uid)->getConnection()->clearCache();
+ }
+
+ /**
+ * Check whether a LDAP DN exists
+ * @param string $dn LDAP DN
+ * @return bool whether the DN exists
+ */
+ public function dnExists($dn) {
+ $result = $this->backend->dn2UserName($dn);
+ return !$result ? false : true;
+ }
+
+ /**
+ * Flag record for deletion.
+ * @param string $uid user id
+ */
+ public function flagRecord($uid) {
+ $this->deletedUsersIndex->markUser($uid);
+ }
+
+ /**
+ * Unflag record for deletion.
+ * @param string $uid user id
+ */
+ public function unflagRecord($uid) {
+ //do nothing
+ }
+}
diff --git a/apps/user_ldap/lib/LDAPProviderFactory.php b/apps/user_ldap/lib/LDAPProviderFactory.php
new file mode 100644
index 00000000000..528af001037
--- /dev/null
+++ b/apps/user_ldap/lib/LDAPProviderFactory.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\User_LDAP;
+
+use OCP\LDAP\ILDAPProviderFactory;
+use OCP\IServerContainer;
+use OCA\User_LDAP\User\DeletedUsersIndex;
+use OCA\User_LDAP\Mapping\UserMapping;
+
+class LDAPProviderFactory implements ILDAPProviderFactory {
+ /**
+ * Server container
+ *
+ * @var IServerContainer
+ */
+ private $serverContainer;
+
+ /**
+ * Constructor for the LDAP provider factory
+ *
+ * @param IServerContainer $serverContainer server container
+ */
+ public function __construct(IServerContainer $serverContainer) {
+ $this->serverContainer = $serverContainer;
+ }
+
+ /**
+ * creates and returns an instance of the ILDAPProvider
+ *
+ * @return OCP\LDAP\ILDAPProvider
+ */
+ public function getLDAPProvider() {
+ $dbConnection = $this->serverContainer->getDatabaseConnection();
+ $userMapping = new UserMapping($dbConnection);
+ return new LDAPProvider($this->serverContainer, new Helper(),
+ new DeletedUsersIndex($this->serverContainer->getConfig(),
+ $dbConnection, $userMapping));
+ }
+}
diff --git a/apps/user_ldap/lib/Proxy.php b/apps/user_ldap/lib/Proxy.php
index 07cc1ea0e8c..db1c761656f 100644
--- a/apps/user_ldap/lib/Proxy.php
+++ b/apps/user_ldap/lib/Proxy.php
@@ -77,7 +77,7 @@ abstract class Proxy {
$userManager =
new Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db, $coreUserManager);
$connector = new Connection($this->ldap, $configPrefix);
- $access = new Access($connector, $this->ldap, $userManager);
+ $access = new Access($connector, $this->ldap, $userManager, new Helper());
$access->setUserMapper($userMap);
$access->setGroupMapper($groupMap);
self::$accesses[$configPrefix] = $access;
diff --git a/apps/user_ldap/lib/User_LDAP.php b/apps/user_ldap/lib/User_LDAP.php
index a2a65bb8406..7e5968e9003 100644
--- a/apps/user_ldap/lib/User_LDAP.php
+++ b/apps/user_ldap/lib/User_LDAP.php
@@ -15,6 +15,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Tom Needham <tom@owncloud.com>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -39,7 +40,7 @@ use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
use OCP\IConfig;
-class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface {
+class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP {
/** @var string[] $homesToKill */
protected $homesToKill = array();
@@ -90,6 +91,16 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return false;
}
}
+
+ /**
+ * returns the username for the given LDAP DN, if available
+ *
+ * @param string $dn
+ * @return string|false with the username
+ */
+ public function dn2UserName($dn) {
+ return $this->access->dn2username($dn);
+ }
/**
* returns an LDAP record based on a given login name
@@ -462,5 +473,25 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
public function getBackendName(){
return 'LDAP';
}
-
+
+ /**
+ * Return access for LDAP interaction.
+ * @param string $uid
+ * @return Access instance of Access for LDAP interaction
+ */
+ public function getLDAPAccess($uid) {
+ return $this->access;
+ }
+
+ /**
+ * Return LDAP connection resource from a cloned connection.
+ * The cloned connection needs to be closed manually.
+ * of the current access.
+ * @param string $uid
+ * @return resource of the LDAP connection
+ */
+ public function getNewLDAPConnection($uid) {
+ $connection = clone $this->access->getConnection();
+ return $connection->getConnectionResource();
+ }
}
diff --git a/apps/user_ldap/lib/User_Proxy.php b/apps/user_ldap/lib/User_Proxy.php
index c86d4f29ec4..cced469a7ae 100644
--- a/apps/user_ldap/lib/User_Proxy.php
+++ b/apps/user_ldap/lib/User_Proxy.php
@@ -9,6 +9,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -31,7 +32,7 @@ namespace OCA\User_LDAP;
use OCA\User_LDAP\User\User;
use OCP\IConfig;
-class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface {
+class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP {
private $backends = array();
private $refBackend = null;
@@ -193,6 +194,17 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface
$id = 'LOGINNAME,' . $loginName;
return $this->handleRequest($id, 'loginName2UserName', array($loginName));
}
+
+ /**
+ * returns the username for the given LDAP DN, if available
+ *
+ * @param string $dn
+ * @return string|false with the username
+ */
+ public function dn2UserName($dn) {
+ $id = 'DN,' . $dn;
+ return $this->handleRequest($id, 'dn2UserName', array($dn));
+ }
/**
* get the user's home directory
@@ -273,4 +285,22 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface
return $users;
}
+ /**
+ * Return access for LDAP interaction.
+ * @param string $uid
+ * @return Access instance of Access for LDAP interaction
+ */
+ public function getLDAPAccess($uid) {
+ return $this->handleRequest($uid, 'getLDAPAccess', array($uid));
+ }
+
+ /**
+ * Return a new LDAP connection for the specified user.
+ * The connection needs to be closed manually.
+ * @param string $uid
+ * @return resource of the LDAP connection
+ */
+ public function getNewLDAPConnection($uid) {
+ return $this->handleRequest($uid, 'getNewLDAPConnection', array($uid));
+ }
}
diff --git a/apps/user_ldap/tests/AccessTest.php b/apps/user_ldap/tests/AccessTest.php
index f96813ba711..2fddafa214b 100644
--- a/apps/user_ldap/tests/AccessTest.php
+++ b/apps/user_ldap/tests/AccessTest.php
@@ -60,21 +60,22 @@ class AccessTest extends \Test\TestCase {
$this->getMock('\OCP\Image'),
$this->getMock('\OCP\IDBConnection'),
$this->getMock('\OCP\IUserManager')));
+ $helper = new \OCA\User_LDAP\Helper();
- return array($lw, $connector, $um);
+ return array($lw, $connector, $um, $helper);
}
public function testEscapeFilterPartValidChars() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$input = 'okay';
$this->assertTrue($input === $access->escapeFilterPart($input));
}
public function testEscapeFilterPartEscapeWildcard() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$input = '*';
$expected = '\\\\*';
@@ -82,8 +83,8 @@ class AccessTest extends \Test\TestCase {
}
public function testEscapeFilterPartEscapeWildcard2() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$input = 'foo*bar';
$expected = 'foo\\\\*bar';
@@ -92,8 +93,8 @@ class AccessTest extends \Test\TestCase {
/** @dataProvider convertSID2StrSuccessData */
public function testConvertSID2StrSuccess(array $sidArray, $sidExpected) {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$sidBinary = implode('', $sidArray);
$this->assertSame($sidExpected, $access->convertSID2Str($sidBinary));
@@ -127,8 +128,8 @@ class AccessTest extends \Test\TestCase {
}
public function testConvertSID2StrInputError() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$sidIllegal = 'foobar';
$sidExpected = '';
@@ -137,8 +138,8 @@ class AccessTest extends \Test\TestCase {
}
public function testGetDomainDNFromDNSuccess() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$inputDN = 'uid=zaphod,cn=foobar,dc=my,dc=server,dc=com';
$domainDN = 'dc=my,dc=server,dc=com';
@@ -152,8 +153,8 @@ class AccessTest extends \Test\TestCase {
}
public function testGetDomainDNFromDNError() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$inputDN = 'foobar';
$expected = '';
@@ -187,8 +188,8 @@ class AccessTest extends \Test\TestCase {
}
public function testStringResemblesDN() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$cases = $this->getResemblesDNInputData();
@@ -208,9 +209,9 @@ class AccessTest extends \Test\TestCase {
}
public function testStringResemblesDNLDAPmod() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
$lw = new \OCA\User_LDAP\LDAP();
- $access = new Access($con, $lw, $um);
+ $access = new Access($con, $lw, $um, $helper);
if(!function_exists('ldap_explode_dn')) {
$this->markTestSkipped('LDAP Module not available');
@@ -224,8 +225,8 @@ class AccessTest extends \Test\TestCase {
}
public function testCacheUserHome() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$con->expects($this->once())
->method('writeToCache');
@@ -234,8 +235,8 @@ class AccessTest extends \Test\TestCase {
}
public function testBatchApplyUserAttributes() {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
- $access = new Access($con, $lw, $um);
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
+ $access = new Access($con, $lw, $um, $helper);
$mapperMock = $this->getMockBuilder('\OCA\User_LDAP\Mapping\UserMapping')
->disableOriginalConstructor()
->getMock();
@@ -294,7 +295,7 @@ class AccessTest extends \Test\TestCase {
* @dataProvider dNAttributeProvider
*/
public function testSanitizeDN($attribute) {
- list($lw, $con, $um) = $this->getConnectorAndLdapMock();
+ list($lw, $con, $um, $helper) = $this->getConnectorAndLdapMock();
$dnFromServer = 'cn=Mixed Cases,ou=Are Sufficient To,ou=Test,dc=example,dc=org';
@@ -309,7 +310,7 @@ class AccessTest extends \Test\TestCase {
$attribute => array('count' => 1, $dnFromServer)
)));
- $access = new Access($con, $lw, $um);
+ $access = new Access($con, $lw, $um, $helper);
$values = $access->readAttribute('uid=whoever,dc=example,dc=org', $attribute);
$this->assertSame($values[0], strtolower($dnFromServer));
}
diff --git a/apps/user_ldap/tests/Group_LDAPTest.php b/apps/user_ldap/tests/Group_LDAPTest.php
index 71120bdb838..83ec2dedf22 100644
--- a/apps/user_ldap/tests/Group_LDAPTest.php
+++ b/apps/user_ldap/tests/Group_LDAPTest.php
@@ -55,9 +55,10 @@ class Group_LDAPTest extends \Test\TestCase {
$um = $this->getMockBuilder('\OCA\User_LDAP\User\Manager')
->disableOriginalConstructor()
->getMock();
+ $helper = new \OCA\User_LDAP\Helper();
$access = $this->getMock('\OCA\User_LDAP\Access',
$accMethods,
- array($connector, $lw, $um));
+ array($connector, $lw, $um, $helper));
$access->expects($this->any())
->method('getConnection')
diff --git a/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php b/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php
index 4ec36617c14..bd56494eac0 100644
--- a/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php
+++ b/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php
@@ -26,6 +26,7 @@ namespace OCA\User_LDAP\Tests\Integration;
use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\LDAP;
+use OCA\User_LDAP\Helper;
use OCA\User_LDAP\User\Manager;
abstract class AbstractIntegrationTest {
@@ -40,6 +41,9 @@ abstract class AbstractIntegrationTest {
/** @var Manager */
protected $userManager;
+
+ /** @var Helper */
+ protected $helper;
/** @var string */
protected $base;
@@ -65,6 +69,7 @@ abstract class AbstractIntegrationTest {
$this->initLDAPWrapper();
$this->initConnection();
$this->initUserManager();
+ $this->initHelper();
$this->initAccess();
}
@@ -103,12 +108,19 @@ abstract class AbstractIntegrationTest {
protected function initUserManager() {
$this->userManager = new FakeManager();
}
+
+ /**
+ * initializes the test Helper
+ */
+ protected function initHelper() {
+ $this->helper = new Helper();
+ }
/**
* initializes the Access test instance
*/
protected function initAccess() {
- $this->access = new Access($this->connection, $this->ldap, $this->userManager);
+ $this->access = new Access($this->connection, $this->ldap, $this->userManager, $this->helper);
}
/**
diff --git a/apps/user_ldap/tests/LDAPProviderTest.php b/apps/user_ldap/tests/LDAPProviderTest.php
new file mode 100644
index 00000000000..22dfb61e5fb
--- /dev/null
+++ b/apps/user_ldap/tests/LDAPProviderTest.php
@@ -0,0 +1,338 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\User_LDAP\Tests;
+
+use OCP\IServerContainer;
+use OCA\User_LDAP\IUserLDAP;
+
+/**
+ * Class LDAPProviderTest
+ *
+ * @group DB
+ *
+ * @package OCA\User_LDAP\Tests
+ */
+class LDAPProviderTest extends \Test\TestCase {
+
+ protected function setUp() {
+ parent::setUp();
+ }
+
+ private function getServerMock(IUserLDAP $backend) {
+ $server = $this->getMockBuilder('OC\Server')
+ ->setMethods(['getUserManager', 'getBackends'])
+ ->setConstructorArgs(['', new \OC\Config(\OC::$configDir)])
+ ->getMock();
+ $server->expects($this->at(1))
+ ->method('getBackends')
+ ->willReturn([$backend]);
+ $server->expects($this->any())
+ ->method($this->anything())
+ ->willReturnSelf();
+
+ return $server;
+ }
+
+ private function getLDAPProvider(IServerContainer $serverContainer) {
+ $factory = new \OCA\User_LDAP\LDAPProviderFactory($serverContainer);
+ return $factory->getLDAPProvider();
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User id not found in LDAP
+ */
+ public function testGetUserDNUserIDNotFound() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())->method('userExists')->willReturn(false);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->getUserDN('nonexisting_user');
+ }
+
+ public function testGetUserDN() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists', 'getLDAPAccess', 'username2dn'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->at(0))
+ ->method('userExists')
+ ->willReturn(true);
+ $backend->expects($this->at(2))
+ ->method('username2dn')
+ ->willReturn('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org');
+ $backend->expects($this->any())
+ ->method($this->anything())
+ ->willReturnSelf();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org',
+ $ldapProvider->getUserDN('existing_user'));
+ }
+
+ public function testGetUserName() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['dn2UserName'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())
+ ->method('dn2UserName')
+ ->willReturn('existing_user');
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals('existing_user',
+ $ldapProvider->getUserName('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'));
+ }
+
+ public function testDNasBaseParameter() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods([])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $server = $this->getServerMock($backend);
+
+ $helper = new \OCA\User_LDAP\Helper();
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals(
+ $helper->DNasBaseParameter('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'),
+ $ldapProvider->DNasBaseParameter('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'));
+ }
+
+ public function testSanitizeDN() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods([])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $server = $this->getServerMock($backend);
+
+ $helper = new \OCA\User_LDAP\Helper();
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals(
+ $helper->sanitizeDN('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'),
+ $ldapProvider->sanitizeDN('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User id not found in LDAP
+ */
+ public function testGetLDAPConnectionUserIDNotFound() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())->method('userExists')->willReturn(false);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->getLDAPConnection('nonexisting_user');
+ }
+
+ public function testGetLDAPConnection() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists', 'getNewLDAPConnection'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())
+ ->method('userExists')
+ ->willReturn(true);
+ $backend->expects($this->any())
+ ->method('getNewLDAPConnection')
+ ->willReturn(true);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertTrue($ldapProvider->getLDAPConnection('existing_user'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User id not found in LDAP
+ */
+ public function testGetLDAPBaseUsersUserIDNotFound() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())->method('userExists')->willReturn(false);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->getLDAPBaseUsers('nonexisting_user');
+ }
+
+ public function testGetLDAPBaseUsers() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->at(0))
+ ->method('userExists')
+ ->willReturn(true);
+ $backend->expects($this->at(3))
+ ->method('getConfiguration')
+ ->willReturn(array('ldap_base_users'=>'ou=users,dc=example,dc=org'));
+ $backend->expects($this->any())
+ ->method($this->anything())
+ ->willReturnSelf();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals('ou=users,dc=example,dc=org', $ldapProvider->getLDAPBaseUsers('existing_user'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User id not found in LDAP
+ */
+ public function testGetLDAPBaseGroupsUserIDNotFound() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())->method('userExists')->willReturn(false);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->getLDAPBaseGroups('nonexisting_user');
+ }
+
+ public function testGetLDAPBaseGroups() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->at(0))
+ ->method('userExists')
+ ->willReturn(true);
+ $backend->expects($this->at(3))
+ ->method('getConfiguration')
+ ->willReturn(array('ldap_base_groups'=>'ou=groups,dc=example,dc=org'));
+ $backend->expects($this->any())
+ ->method($this->anything())
+ ->willReturnSelf();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertEquals('ou=groups,dc=example,dc=org', $ldapProvider->getLDAPBaseGroups('existing_user'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User id not found in LDAP
+ */
+ public function testClearCacheUserIDNotFound() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())->method('userExists')->willReturn(false);
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->clearCache('nonexisting_user');
+ }
+
+ public function testClearCache() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'clearCache'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->at(0))
+ ->method('userExists')
+ ->willReturn(true);
+ $backend->expects($this->at(3))
+ ->method('clearCache')
+ ->willReturn(true);
+ $backend->expects($this->any())
+ ->method($this->anything())
+ ->willReturnSelf();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->clearCache('existing_user');
+ $this->assertTrue(TRUE);
+ }
+
+ public function testDnExists() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods(['dn2UserName'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $backend->expects($this->any())
+ ->method('dn2UserName')
+ ->willReturn('existing_user');
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $this->assertTrue($ldapProvider->dnExists('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'));
+ }
+
+ public function testFlagRecord() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods([])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->flagRecord('existing_user');
+ $this->assertTrue(TRUE);
+ }
+
+ public function testUnflagRecord() {
+ $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP')
+ ->setMethods([])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $server = $this->getServerMock($backend);
+
+ $ldapProvider = $this->getLDAPProvider($server);
+ $ldapProvider->unflagRecord('existing_user');
+ $this->assertTrue(TRUE);
+ }
+}
diff --git a/apps/user_ldap/tests/User/UserTest.php b/apps/user_ldap/tests/User/UserTest.php
index cf1514009d8..d9e43dee047 100644
--- a/apps/user_ldap/tests/User/UserTest.php
+++ b/apps/user_ldap/tests/User/UserTest.php
@@ -71,8 +71,9 @@ class UserTest extends \Test\TestCase {
$umMethods, array($cfMock, $fsMock, $logMock, $avaMgr, $im, $dbc, $userMgr));
$connector = $this->getMock('\OCA\User_LDAP\Connection',
$conMethods, array($lw, null, null));
+ $helper = new \OCA\User_LDAP\Helper();
$access = $this->getMock('\OCA\User_LDAP\Access',
- $accMethods, array($connector, $lw, $um));
+ $accMethods, array($connector, $lw, $um, $helper));
return array($access, $connector);
}
diff --git a/apps/user_ldap/tests/User_LDAPTest.php b/apps/user_ldap/tests/User_LDAPTest.php
index ae86e3cf3a2..47e789142e5 100644
--- a/apps/user_ldap/tests/User_LDAPTest.php
+++ b/apps/user_ldap/tests/User_LDAPTest.php
@@ -93,9 +93,11 @@ class User_LDAPTest extends \Test\TestCase {
->method('getDeletedUser')
->will($this->returnValue($offlineUser));
+ $helper = new \OCA\User_LDAP\Helper();
+
$access = $this->getMock('\OCA\User_LDAP\Access',
$accMethods,
- array($connector, $lw, $um));
+ array($connector, $lw, $um, $helper));
$um->setLdapAccess($access);
diff --git a/apps/user_ldap/tests/WizardTest.php b/apps/user_ldap/tests/WizardTest.php
index cc110c6ee0d..e82cbcfc82a 100644
--- a/apps/user_ldap/tests/WizardTest.php
+++ b/apps/user_ldap/tests/WizardTest.php
@@ -69,8 +69,9 @@ class WizardTest extends \Test\TestCase {
$um = $this->getMockBuilder('\OCA\User_LDAP\User\Manager')
->disableOriginalConstructor()
->getMock();
+ $helper = new \OCA\User_LDAP\Helper();
$access = $this->getMock('\OCA\User_LDAP\Access',
- $accMethods, array($connector, $lw, $um));
+ $accMethods, array($connector, $lw, $um, $helper));
return array(new Wizard($conf, $lw, $access), $conf, $lw, $access);
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 41092ceae6e..fd6ecdc297e 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -21,6 +21,7 @@
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Thomas Tanghus <thomas@tanghus.net>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author Roger Szabo <roger.szabo@web.de>
*
* @license AGPL-3.0
*
@@ -584,6 +585,16 @@ class Server extends ServerContainer implements IServerContainer {
$this->getLogger()
);
});
+ $this->registerService('LDAPProvider', function(Server $c) {
+ $config = $c->getConfig();
+ $factoryClass = $config->getSystemValue('ldapProviderFactory', null);
+ if(is_null($factoryClass)) {
+ throw new \Exception('ldapProviderFactory not set');
+ }
+ /** @var \OCP\LDAP\ILDAPProviderFactory $factory */
+ $factory = new $factoryClass($this);
+ return $factory->getLDAPProvider();
+ });
$this->registerService('LockingProvider', function (Server $c) {
$ini = $c->getIniWrapper();
$config = $c->getConfig();
@@ -1406,4 +1417,12 @@ class Server extends ServerContainer implements IServerContainer {
return $this->query('ShareManager');
}
+ /**
+ * Returns the LDAP Provider
+ *
+ * @return \OCP\LDAP\ILDAPProvider
+ */
+ public function getLDAPProvider() {
+ return $this->query('LDAPProvider');
+ }
}
diff --git a/lib/public/LDAP/IDeletionFlagSupport.php b/lib/public/LDAP/IDeletionFlagSupport.php
new file mode 100644
index 00000000000..5f7d3909195
--- /dev/null
+++ b/lib/public/LDAP/IDeletionFlagSupport.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\LDAP;
+
+/**
+ * Interface IDeletionFlagSupport
+ *
+ * @package OCP\LDAP
+ * @since 9.2.0
+ */
+interface IDeletionFlagSupport {
+ /**
+ * Flag record for deletion.
+ * @param string $uid user id
+ * @since 9.2.0
+ */
+ public function flagRecord($uid);
+
+ /**
+ * Unflag record for deletion.
+ * @param string $uid user id
+ * @since 9.2.0
+ */
+ public function unflagRecord($uid);
+}
diff --git a/lib/public/LDAP/ILDAPProvider.php b/lib/public/LDAP/ILDAPProvider.php
new file mode 100644
index 00000000000..473afb13885
--- /dev/null
+++ b/lib/public/LDAP/ILDAPProvider.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\LDAP;
+
+/**
+ * Interface ILDAPProvider
+ *
+ * @package OCP\LDAP
+ * @since 9.2.0
+ */
+interface ILDAPProvider {
+ /**
+ * Translate a user id to LDAP DN.
+ * @param string $uid user id
+ * @return string
+ * @since 9.2.0
+ */
+ public function getUserDN($uid);
+
+ /**
+ * Translate a LDAP DN to an internal user name.
+ * @param string $dn LDAP DN
+ * @return string with the internal user name
+ * @throws \Exception if translation was unsuccessful
+ * @since 9.2.0
+ */
+ public function getUserName($dn);
+
+ /**
+ * Convert a stored DN so it can be used as base parameter for LDAP queries.
+ * @param string $dn the DN
+ * @return string
+ * @since 9.2.0
+ */
+ public function DNasBaseParameter($dn);
+
+ /**
+ * Sanitize a DN received from the LDAP server.
+ * @param array $dn the DN in question
+ * @return array the sanitized DN
+ * @since 9.2.0
+ */
+ public function sanitizeDN($dn);
+
+ /**
+ * Return a new LDAP connection resource for the specified user.
+ * @param string $uid user id
+ * @return resource of the LDAP connection
+ * @since 9.2.0
+ */
+ public function getLDAPConnection($uid);
+
+ /**
+ * Get the LDAP base for users.
+ * @param string $uid user id
+ * @return string the base for users
+ * @throws \Exception if user id was not found in LDAP
+ * @since 9.2.0
+ */
+ public function getLDAPBaseUsers($uid);
+
+ /**
+ * Get the LDAP base for groups.
+ * @param string $uid user id
+ * @return string the base for groups
+ * @throws \Exception if user id was not found in LDAP
+ * @since 9.2.0
+ */
+ public function getLDAPBaseGroups($uid);
+
+ /**
+ * Check whether a LDAP DN exists
+ * @param string $dn LDAP DN
+ * @return bool whether the DN exists
+ * @since 9.2.0
+ */
+ public function dnExists($dn);
+
+ /**
+ * Clear the cache if a cache is used, otherwise do nothing.
+ * @param string $uid user id
+ * @since 9.2.0
+ */
+ public function clearCache($uid);
+}
diff --git a/lib/public/LDAP/ILDAPProviderFactory.php b/lib/public/LDAP/ILDAPProviderFactory.php
new file mode 100644
index 00000000000..99e7b8d27ea
--- /dev/null
+++ b/lib/public/LDAP/ILDAPProviderFactory.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ *
+ * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\LDAP;
+
+use OCP\IServerContainer;
+
+/**
+ * Interface ILDAPProviderFactory
+ *
+ * This class is responsible for instantiating and returning an ILDAPProvider
+ * instance.
+ *
+ * @package OCP\LDAP
+ * @since 9.2.0
+ */
+interface ILDAPProviderFactory {
+
+ /**
+ * Constructor for the LDAP provider factory
+ *
+ * @param IServerContainer $serverContainer server container
+ * @since 9.2.0
+ */
+ public function __construct(IServerContainer $serverContainer);
+
+ /**
+ * creates and returns an instance of the ILDAPProvider
+ *
+ * @return ILDAPProvider
+ * @since 9.2.0
+ */
+ public function getLDAPProvider();
+}