summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Reschke <lukas@owncloud.com>2015-01-09 10:47:02 +0100
committerLukas Reschke <lukas@owncloud.com>2015-01-09 10:47:02 +0100
commita5099b01f93ec81602c8facba04233c7bc65ed47 (patch)
treefb2ac4d03d0210848c0c22a241ad956b7bf54c8d
parentb4606ec24f507ff6ad6f720d3c4f026221a163d7 (diff)
parentc1a79d24c54d3c1d6ecb2c65540f9b52a3d6dc31 (diff)
downloadnextcloud-server-a5099b01f93ec81602c8facba04233c7bc65ed47.tar.gz
nextcloud-server-a5099b01f93ec81602c8facba04233c7bc65ed47.zip
Merge pull request #12984 from owncloud/ldap-user-cleanup-master
Ldap user cleanup master
-rw-r--r--apps/user_ldap/ajax/deleteConfiguration.php3
-rw-r--r--apps/user_ldap/ajax/getNewServerConfigPrefix.php3
-rw-r--r--apps/user_ldap/ajax/wizard.php3
-rw-r--r--apps/user_ldap/appinfo/app.php29
-rw-r--r--apps/user_ldap/appinfo/register_command.php27
-rw-r--r--apps/user_ldap/appinfo/update.php3
-rw-r--r--apps/user_ldap/appinfo/version2
-rw-r--r--apps/user_ldap/command/checkuser.php121
-rw-r--r--apps/user_ldap/command/search.php17
-rw-r--r--apps/user_ldap/command/setconfig.php3
-rw-r--r--apps/user_ldap/command/showconfig.php3
-rw-r--r--apps/user_ldap/command/showremnants.php73
-rw-r--r--apps/user_ldap/command/testconfig.php3
-rw-r--r--apps/user_ldap/lib/access.php29
-rw-r--r--apps/user_ldap/lib/connection.php3
-rw-r--r--apps/user_ldap/lib/helper.php24
-rw-r--r--apps/user_ldap/lib/jobs.php14
-rw-r--r--apps/user_ldap/lib/jobs/cleanup.php217
-rw-r--r--apps/user_ldap/lib/mapping/abstractmapping.php23
-rw-r--r--apps/user_ldap/lib/proxy.php8
-rw-r--r--apps/user_ldap/lib/user/deletedusersindex.php114
-rw-r--r--apps/user_ldap/lib/user/iusertools.php1
-rw-r--r--apps/user_ldap/lib/user/manager.php118
-rw-r--r--apps/user_ldap/lib/user/offlineuser.php223
-rw-r--r--apps/user_ldap/lib/user/user.php27
-rw-r--r--apps/user_ldap/lib/wizard.php3
-rw-r--r--apps/user_ldap/settings.php5
-rw-r--r--apps/user_ldap/tests/access.php3
-rw-r--r--apps/user_ldap/tests/group_ldap.php3
-rw-r--r--apps/user_ldap/tests/jobs/cleanup.php135
-rw-r--r--apps/user_ldap/tests/mapping/abstractmappingtest.php24
-rw-r--r--apps/user_ldap/tests/user/manager.php29
-rw-r--r--apps/user_ldap/tests/user/user.php63
-rw-r--r--apps/user_ldap/tests/user_ldap.php93
-rw-r--r--apps/user_ldap/user_ldap.php132
-rw-r--r--apps/user_ldap/user_proxy.php20
-rw-r--r--config/config.sample.php16
-rw-r--r--core/command/user/delete.php47
-rw-r--r--core/register_command.php1
39 files changed, 1474 insertions, 191 deletions
diff --git a/apps/user_ldap/ajax/deleteConfiguration.php b/apps/user_ldap/ajax/deleteConfiguration.php
index bca687c81ab..d409d891f61 100644
--- a/apps/user_ldap/ajax/deleteConfiguration.php
+++ b/apps/user_ldap/ajax/deleteConfiguration.php
@@ -27,7 +27,8 @@ OCP\JSON::checkAppEnabled('user_ldap');
OCP\JSON::callCheck();
$prefix = $_POST['ldap_serverconfig_chooser'];
-if(\OCA\user_ldap\lib\Helper::deleteServerConfiguration($prefix)) {
+$helper = new \OCA\user_ldap\lib\Helper();
+if($helper->deleteServerConfiguration($prefix)) {
OCP\JSON::success();
} else {
$l = \OC::$server->getL10N('user_ldap');
diff --git a/apps/user_ldap/ajax/getNewServerConfigPrefix.php b/apps/user_ldap/ajax/getNewServerConfigPrefix.php
index 1c68b2e9a76..ce6c5ae76e8 100644
--- a/apps/user_ldap/ajax/getNewServerConfigPrefix.php
+++ b/apps/user_ldap/ajax/getNewServerConfigPrefix.php
@@ -26,7 +26,8 @@ OCP\JSON::checkAdminUser();
OCP\JSON::checkAppEnabled('user_ldap');
OCP\JSON::callCheck();
-$serverConnections = \OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes();
+$helper = new \OCA\user_ldap\lib\Helper();
+$serverConnections = $helper->getServerConfigurationPrefixes();
sort($serverConnections);
$lk = array_pop($serverConnections);
$ln = intval(str_replace('s', '', $lk));
diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php
index 6d7d70c8c5a..48bfb56311c 100644
--- a/apps/user_ldap/ajax/wizard.php
+++ b/apps/user_ldap/ajax/wizard.php
@@ -52,7 +52,8 @@ $userManager = new \OCA\user_ldap\lib\user\Manager(
new \OCA\user_ldap\lib\FilesystemHelper(),
new \OCA\user_ldap\lib\LogWrapper(),
\OC::$server->getAvatarManager(),
- new \OCP\Image());
+ new \OCP\Image(),
+ \OC::$server->getDatabaseConnection());
$access = new \OCA\user_ldap\lib\Access($con, $ldapWrapper, $userManager);
diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php
index 98d5fb60183..911688a5c20 100644
--- a/apps/user_ldap/appinfo/app.php
+++ b/apps/user_ldap/appinfo/app.php
@@ -5,6 +5,7 @@
*
* @author Dominik Schmidt
* @copyright 2011 Dominik Schmidt dev@dominik-schmidt.de
+* @copyright 2014 Arthur Schiwon <blizzz@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -23,24 +24,30 @@
OCP\App::registerAdmin('user_ldap', 'settings');
-$configPrefixes = OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes(true);
+$helper = new \OCA\user_ldap\lib\Helper();
+$configPrefixes = $helper->getServerConfigurationPrefixes(true);
$ldapWrapper = new OCA\user_ldap\lib\LDAP();
+$ocConfig = \OC::$server->getConfig();
if(count($configPrefixes) === 1) {
- $ocConfig = \OC::$server->getConfig();
+ $dbc = \OC::$server->getDatabaseConnection();
$userManager = new OCA\user_ldap\lib\user\Manager($ocConfig,
new OCA\user_ldap\lib\FilesystemHelper(),
new OCA\user_ldap\lib\LogWrapper(),
\OC::$server->getAvatarManager(),
- new \OCP\Image());
+ new \OCP\Image(),
+ $dbc
+ );
$connector = new OCA\user_ldap\lib\Connection($ldapWrapper, $configPrefixes[0]);
$ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper, $userManager);
- $dbc = \OC::$server->getDatabaseConnection();
+
$ldapAccess->setUserMapper(new OCA\User_LDAP\Mapping\UserMapping($dbc));
$ldapAccess->setGroupMapper(new OCA\User_LDAP\Mapping\GroupMapping($dbc));
- $userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess);
+ $userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess, $ocConfig);
$groupBackend = new OCA\user_ldap\GROUP_LDAP($ldapAccess);
} else if(count($configPrefixes) > 1) {
- $userBackend = new OCA\user_ldap\User_Proxy($configPrefixes, $ldapWrapper);
+ $userBackend = new OCA\user_ldap\User_Proxy(
+ $configPrefixes, $ldapWrapper, $ocConfig
+ );
$groupBackend = new OCA\user_ldap\Group_Proxy($configPrefixes, $ldapWrapper);
}
@@ -50,16 +57,10 @@ if(count($configPrefixes) > 0) {
OC_Group::useBackend($groupBackend);
}
-// add settings page to navigation
-$entry = array(
- 'id' => 'user_ldap_settings',
- 'order'=>1,
- 'href' => OCP\Util::linkTo( 'user_ldap', 'settings.php' ),
- 'name' => 'LDAP'
-);
OCP\Util::addTranslations('user_ldap');
-
OCP\Backgroundjob::registerJob('OCA\user_ldap\lib\Jobs');
+OCP\Backgroundjob::registerJob('\OCA\User_LDAP\Jobs\CleanUp');
+
if(OCP\App::isEnabled('user_webdavauth')) {
OCP\Util::writeLog('user_ldap',
'user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour',
diff --git a/apps/user_ldap/appinfo/register_command.php b/apps/user_ldap/appinfo/register_command.php
index 1a0227db95e..651e6a564e1 100644
--- a/apps/user_ldap/appinfo/register_command.php
+++ b/apps/user_ldap/appinfo/register_command.php
@@ -6,9 +6,34 @@
* See the COPYING-README file.
*/
+use OCA\user_ldap\lib\Helper;
+use OCA\user_ldap\lib\LDAP;
+use OCA\user_ldap\User_Proxy;
+use OCA\User_LDAP\Mapping\UserMapping;
+use OCA\User_LDAP\lib\User\DeletedUsersIndex;
+
+$dbConnection = \OC::$server->getDatabaseConnection();
+$userMapping = new UserMapping($dbConnection);
+$helper = new Helper();
+$ocConfig = \OC::$server->getConfig();
+$uBackend = new User_Proxy(
+ $helper->getServerConfigurationPrefixes(true),
+ new LDAP(),
+ $ocConfig
+);
+$deletedUsersIndex = new DeletedUsersIndex(
+ $ocConfig, $dbConnection, $userMapping
+);
+
$application->add(new OCA\user_ldap\Command\ShowConfig());
$application->add(new OCA\user_ldap\Command\SetConfig());
$application->add(new OCA\user_ldap\Command\TestConfig());
$application->add(new OCA\user_ldap\Command\CreateEmptyConfig());
$application->add(new OCA\user_ldap\Command\DeleteConfig());
-$application->add(new OCA\user_ldap\Command\Search());
+$application->add(new OCA\user_ldap\Command\Search($ocConfig));
+$application->add(new OCA\user_ldap\Command\ShowRemnants(
+ $deletedUsersIndex, \OC::$server->getDateTimeFormatter())
+);
+$application->add(new OCA\user_ldap\Command\CheckUser(
+ $uBackend, $helper, $deletedUsersIndex, $userMapping)
+);
diff --git a/apps/user_ldap/appinfo/update.php b/apps/user_ldap/appinfo/update.php
index 9bf0ca4ab53..b4121b19852 100644
--- a/apps/user_ldap/appinfo/update.php
+++ b/apps/user_ldap/appinfo/update.php
@@ -12,7 +12,8 @@ if($state === 'unset') {
$installedVersion = $configInstance->getAppValue('user_ldap', 'installed_version');
$enableRawMode = version_compare($installedVersion, '0.4.1', '<');
-$configPrefixes = OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes(true);
+$helper = new \OCA\user_ldap\lib\Helper();
+$configPrefixes = $helper->getServerConfigurationPrefixes(true);
$ldap = new OCA\user_ldap\lib\LDAP();
foreach($configPrefixes as $config) {
$connection = new OCA\user_ldap\lib\Connection($ldap, $config);
diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version
index 6f2743d65dc..0bfccb08040 100644
--- a/apps/user_ldap/appinfo/version
+++ b/apps/user_ldap/appinfo/version
@@ -1 +1 @@
-0.4.4
+0.4.5
diff --git a/apps/user_ldap/command/checkuser.php b/apps/user_ldap/command/checkuser.php
new file mode 100644
index 00000000000..202855e4853
--- /dev/null
+++ b/apps/user_ldap/command/checkuser.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\user_ldap\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+use OCA\user_ldap\lib\user\User;
+use OCA\User_LDAP\lib\User\DeletedUsersIndex;
+use OCA\User_LDAP\Mapping\UserMapping;
+use OCA\user_ldap\lib\Helper as LDAPHelper;
+use OCA\user_ldap\User_Proxy;
+
+class CheckUser extends Command {
+ /** @var \OCA\user_ldap\User_Proxy */
+ protected $backend;
+
+ /** @var \OCA\User_LDAP\lib\Helper */
+ protected $helper;
+
+ /** @var \OCA\User_LDAP\lib\User\DeletedUsersIndex */
+ protected $dui;
+
+ /** @var \OCA\User_LDAP\Mapping\UserMapping */
+ protected $mapping;
+
+ /**
+ * @param OCA\user_ldap\User_Proxy $uBackend
+ * @param OCA\user_ldap\lib\Helper $helper
+ * @param OCA\User_LDAP\lib\User\DeletedUsersIndex $dui
+ * @param OCA\User_LDAP\Mapping\UserMapping $mapping
+ */
+ public function __construct(User_Proxy $uBackend, LDAPHelper $helper, DeletedUsersIndex $dui, UserMapping $mapping) {
+ $this->backend = $uBackend;
+ $this->helper = $helper;
+ $this->dui = $dui;
+ $this->mapping = $mapping;
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('ldap:check-user')
+ ->setDescription('checks whether a user exists on LDAP.')
+ ->addArgument(
+ 'ocName',
+ InputArgument::REQUIRED,
+ 'the user name as used in ownCloud'
+ )
+ ->addOption(
+ 'force',
+ null,
+ InputOption::VALUE_NONE,
+ 'ignores disabled LDAP configuration'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ try {
+ $uid = $input->getArgument('ocName');
+ $this->isAllowed($input->getOption('force'));
+ $this->confirmUserIsMapped($uid);
+ $exists = $this->backend->userExistsOnLDAP($uid);
+ if($exists === true) {
+ $output->writeln('The user is still available on LDAP.');
+ return;
+ }
+
+ $this->dui->markUser($uid);
+ $output->writeln('The user does not exists on LDAP anymore.');
+ $output->writeln('Clean up the user\'s remnants by: ./occ user:delete "'
+ . $uid . '"');
+ } catch (\Exception $e) {
+ $output->writeln('<error>' . $e->getMessage(). '</error>');
+ }
+ }
+
+ /**
+ * checks whether a user is actually mapped
+ * @param string $ocName the username as used in ownCloud
+ * @throws \Exception
+ * @return true
+ */
+ protected function confirmUserIsMapped($ocName) {
+ $dn = $this->mapping->getDNByName($ocName);
+ if ($dn === false) {
+ throw new \Exception('The given user is not a recognized LDAP user.');
+ }
+
+ return true;
+ }
+
+ /**
+ * checks whether the setup allows reliable checking of LDAP user existence
+ * @throws \Exception
+ * @return true
+ */
+ protected function isAllowed($force) {
+ if($this->helper->haveDisabledConfigurations() && !$force) {
+ throw new \Exception('Cannot check user existence, because '
+ . 'disabled LDAP configurations are present.');
+ }
+
+ // we don't check ldapUserCleanupInterval from config.php because this
+ // action is triggered manually, while the setting only controls the
+ // background job.
+
+ return true;
+ }
+
+}
diff --git a/apps/user_ldap/command/search.php b/apps/user_ldap/command/search.php
index e20255510d8..ba87982d167 100644
--- a/apps/user_ldap/command/search.php
+++ b/apps/user_ldap/command/search.php
@@ -18,8 +18,20 @@ use OCA\user_ldap\User_Proxy;
use OCA\user_ldap\Group_Proxy;
use OCA\user_ldap\lib\Helper;
use OCA\user_ldap\lib\LDAP;
+use OCP\IConfig;
class Search extends Command {
+ /** @var \OCP\IConfig */
+ protected $ocConfig;
+
+ /**
+ * @param \OCP\IConfig $ocConfig
+ */
+ public function __construct(IConfig $ocConfig) {
+ $this->ocConfig = $ocConfig;
+ parent::__construct();
+ }
+
protected function configure() {
$this
->setName('ldap:search')
@@ -74,7 +86,8 @@ class Search extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output) {
- $configPrefixes = Helper::getServerConfigurationPrefixes(true);
+ $helper = new Helper();
+ $configPrefixes = $helper->getServerConfigurationPrefixes(true);
$ldapWrapper = new LDAP();
$offset = intval($input->getOption('offset'));
@@ -86,7 +99,7 @@ class Search extends Command {
$getMethod = 'getGroups';
$printID = false;
} else {
- $proxy = new User_Proxy($configPrefixes, $ldapWrapper);
+ $proxy = new User_Proxy($configPrefixes, $ldapWrapper, $this->ocConfig);
$getMethod = 'getDisplayNames';
$printID = true;
}
diff --git a/apps/user_ldap/command/setconfig.php b/apps/user_ldap/command/setconfig.php
index ab1c8d39ead..9128fcf04fc 100644
--- a/apps/user_ldap/command/setconfig.php
+++ b/apps/user_ldap/command/setconfig.php
@@ -41,7 +41,8 @@ class SetConfig extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output) {
- $availableConfigs = Helper::getServerConfigurationPrefixes();
+ $helper = new Helper();
+ $availableConfigs = $helper->getServerConfigurationPrefixes();
$configID = $input->getArgument('configID');
if(!in_array($configID, $availableConfigs)) {
$output->writeln("Invalid configID");
diff --git a/apps/user_ldap/command/showconfig.php b/apps/user_ldap/command/showconfig.php
index f51d641beec..ddbc45243ff 100644
--- a/apps/user_ldap/command/showconfig.php
+++ b/apps/user_ldap/command/showconfig.php
@@ -31,7 +31,8 @@ class ShowConfig extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output) {
- $availableConfigs = Helper::getServerConfigurationPrefixes();
+ $helper = new Helper();
+ $availableConfigs = $helper->getServerConfigurationPrefixes();
$configID = $input->getArgument('configID');
if(!is_null($configID)) {
$configIDs[] = $configID;
diff --git a/apps/user_ldap/command/showremnants.php b/apps/user_ldap/command/showremnants.php
new file mode 100644
index 00000000000..5cfab34ef95
--- /dev/null
+++ b/apps/user_ldap/command/showremnants.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\user_ldap\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+use OCA\user_ldap\lib\user\DeletedUsersIndex;
+use OCP\IDateTimeFormatter;
+
+class ShowRemnants extends Command {
+ /** @var \OCA\User_LDAP\lib\User\DeletedUsersIndex */
+ protected $dui;
+
+ /** @var \OCP\IDateTimeFormatter */
+ protected $dateFormatter;
+
+ /**
+ * @param OCA\user_ldap\lib\user\DeletedUsersIndex $dui
+ * @param OCP\IDateTimeFormatter $dateFormatter
+ */
+ public function __construct(DeletedUsersIndex $dui, IDateTimeFormatter $dateFormatter) {
+ $this->dui = $dui;
+ $this->dateFormatter = $dateFormatter;
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('ldap:show-remnants')
+ ->setDescription('shows which users are not available on LDAP anymore, but have remnants in ownCloud.')
+ ;
+ }
+
+ /**
+ * executes the command, i.e. creeates and outputs a table of LDAP users marked as deleted
+ *
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ /** @var \Symfony\Component\Console\Helper\Table $table */
+ $table = $this->getHelperSet()->get('table');
+ $table->setHeaders(array(
+ 'ownCloud name', 'Display Name', 'LDAP UID', 'LDAP DN', 'Last Login',
+ 'Dir', 'Sharer'));
+ $rows = array();
+ $resultSet = $this->dui->getUsers();
+ foreach($resultSet as $user) {
+ $hAS = $user->getHasActiveShares() ? 'Y' : 'N';
+ $lastLogin = ($user->getLastLogin() > 0) ?
+ $this->dateFormatter->formatDate($user->getLastLogin()) : '-';
+ $rows[] = array(
+ $user->getOCName(),
+ $user->getDisplayName(),
+ $user->getUid(),
+ $user->getDN(),
+ $lastLogin,
+ $user->getHomePath(),
+ $hAS
+ );
+ }
+
+ $table->setRows($rows);
+ $table->render($output);
+ }
+}
diff --git a/apps/user_ldap/command/testconfig.php b/apps/user_ldap/command/testconfig.php
index 00b4acf2f66..a44e22415e9 100644
--- a/apps/user_ldap/command/testconfig.php
+++ b/apps/user_ldap/command/testconfig.php
@@ -31,7 +31,8 @@ class TestConfig extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output) {
- $availableConfigs = Helper::getServerConfigurationPrefixes();
+ $helper = new Helper();
+ $availableConfigs = $helper->getServerConfigurationPrefixes();
$configID = $input->getArgument('configID');
if(!in_array($configID, $availableConfigs)) {
$output->writeln("Invalid configID");
diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php
index 00fb8acc59a..f3657176f70 100644
--- a/apps/user_ldap/lib/access.php
+++ b/apps/user_ldap/lib/access.php
@@ -76,6 +76,18 @@ class Access extends LDAPUtility implements user\IUserTools {
}
/**
+ * returns the User Mapper
+ * @throws \Exception
+ * @return AbstractMapping
+ */
+ public function getUserMapper() {
+ if(is_null($this->userMapper)) {
+ throw new \Exception('UserMapper was not assigned to this Access instance.');
+ }
+ return $this->userMapper;
+ }
+
+ /**
* sets the Group Mapper
* @param AbstractMapping $mapper
*/
@@ -84,6 +96,18 @@ class Access extends LDAPUtility implements user\IUserTools {
}
/**
+ * returns the Group Mapper
+ * @throws \Exception
+ * @return AbstractMapping
+ */
+ public function getGroupMapper() {
+ if(is_null($this->groupMapper)) {
+ throw new \Exception('GroupMapper was not assigned to this Access instance.');
+ }
+ return $this->groupMapper;
+ }
+
+ /**
* @return bool
*/
private function checkConnection() {
@@ -290,6 +314,7 @@ class Access extends LDAPUtility implements user\IUserTools {
}
/**
+ public function ocname2dn($name, $isUser) {
* returns the internal ownCloud name for the given LDAP DN of the group, false on DN outside of search DN or failure
* @param string $fdn the dn of the group object
* @param string $ldapName optional, the display name of the object
@@ -332,10 +357,10 @@ class Access extends LDAPUtility implements user\IUserTools {
*/
public function dn2ocname($fdn, $ldapName = null, $isUser = true) {
if($isUser) {
- $mapper = $this->userMapper;
+ $mapper = $this->getUserMapper();
$nameAttribute = $this->connection->ldapUserDisplayName;
} else {
- $mapper = $this->groupMapper;
+ $mapper = $this->getGroupMapper();
$nameAttribute = $this->connection->ldapGroupDisplayName;
}
diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php
index 204857eb61e..c9b4fded9f9 100644
--- a/apps/user_ldap/lib/connection.php
+++ b/apps/user_ldap/lib/connection.php
@@ -71,8 +71,9 @@ class Connection extends LDAPUtility {
}
$this->hasPagedResultSupport =
$this->ldap->hasPagedResultSupport();
+ $helper = new Helper();
$this->doNotValidate = !in_array($this->configPrefix,
- Helper::getServerConfigurationPrefixes());
+ $helper->getServerConfigurationPrefixes());
}
public function __destruct() {
diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php
index fa36e304171..7a96cfa36c4 100644
--- a/apps/user_ldap/lib/helper.php
+++ b/apps/user_ldap/lib/helper.php
@@ -45,7 +45,7 @@ class Helper {
* except the default (first) server shall be connected to.
*
*/
- static public function getServerConfigurationPrefixes($activeConfigurations = false) {
+ public function getServerConfigurationPrefixes($activeConfigurations = false) {
$referenceConfigkey = 'ldap_configuration_active';
$sql = '
@@ -83,7 +83,7 @@ class Helper {
* @return array an array with configprefix as keys
*
*/
- static public function getServerConfigurationHosts() {
+ public function getServerConfigurationHosts() {
$referenceConfigkey = 'ldap_host';
$query = '
@@ -110,7 +110,7 @@ class Helper {
* @param string $prefix the configuration prefix of the config to delete
* @return bool true on success, false otherwise
*/
- static public function deleteServerConfiguration($prefix) {
+ public function deleteServerConfiguration($prefix) {
if(!in_array($prefix, self::getServerConfigurationPrefixes())) {
return false;
}
@@ -142,11 +142,27 @@ class Helper {
}
/**
+ * checks whether there is one or more disabled LDAP configurations
+ * @throws \Exception
+ * @return bool
+ */
+ public function haveDisabledConfigurations() {
+ $all = $this->getServerConfigurationPrefixes(false);
+ $active = $this->getServerConfigurationPrefixes(true);
+
+ if(!is_array($all) || !is_array($active)) {
+ throw new \Exception('Unexpected Return Value');
+ }
+
+ return count($all) !== count($active) || count($all) === 0;
+ }
+
+ /**
* extracts the domain from a given URL
* @param string $url the URL
* @return string|false domain as string on success, false otherwise
*/
- static public function getDomainFromURL($url) {
+ public function getDomainFromURL($url) {
$uinfo = parse_url($url);
if(!is_array($uinfo)) {
return false;
diff --git a/apps/user_ldap/lib/jobs.php b/apps/user_ldap/lib/jobs.php
index 47e536f8f64..a887b65251c 100644
--- a/apps/user_ldap/lib/jobs.php
+++ b/apps/user_ldap/lib/jobs.php
@@ -23,6 +23,9 @@
namespace OCA\user_ldap\lib;
+use OCA\User_LDAP\Mapping\GroupMapping;
+use OCA\User_LDAP\Mapping\UserMapping;
+
class Jobs extends \OC\BackgroundJob\TimedJob {
static private $groupsFromDB;
@@ -156,18 +159,25 @@ class Jobs extends \OC\BackgroundJob\TimedJob {
if(!is_null(self::$groupBE)) {
return self::$groupBE;
}
- $configPrefixes = Helper::getServerConfigurationPrefixes(true);
+ $helper = new Helper();
+ $configPrefixes = $helper->getServerConfigurationPrefixes(true);
$ldapWrapper = new LDAP();
if(count($configPrefixes) === 1) {
//avoid the proxy when there is only one LDAP server configured
+ $dbc = \OC::$server->getDatabaseConnection();
$userManager = new user\Manager(
\OC::$server->getConfig(),
new FilesystemHelper(),
new LogWrapper(),
\OC::$server->getAvatarManager(),
- new \OCP\Image());
+ new \OCP\Image(),
+ $dbc);
$connector = new Connection($ldapWrapper, $configPrefixes[0]);
$ldapAccess = new Access($connector, $ldapWrapper, $userManager);
+ $groupMapper = new GroupMapping($dbc);
+ $userMapper = new UserMapping($dbc);
+ $ldapAccess->setGroupMapper($groupMapper);
+ $ldapAccess->setUserMapper($userMapper);
self::$groupBE = new \OCA\user_ldap\GROUP_LDAP($ldapAccess);
} else {
self::$groupBE = new \OCA\user_ldap\Group_Proxy($configPrefixes, $ldapWrapper);
diff --git a/apps/user_ldap/lib/jobs/cleanup.php b/apps/user_ldap/lib/jobs/cleanup.php
new file mode 100644
index 00000000000..caf31f89820
--- /dev/null
+++ b/apps/user_ldap/lib/jobs/cleanup.php
@@ -0,0 +1,217 @@
+<?php
+/**
+ * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\User_LDAP\Jobs;
+
+use \OC\BackgroundJob\TimedJob;
+use \OCA\user_ldap\User_LDAP;
+use \OCA\user_ldap\User_Proxy;
+use \OCA\user_ldap\lib\Helper;
+use \OCA\user_ldap\lib\LDAP;
+use \OCA\user_ldap\lib\user\DeletedUsersIndex;
+use \OCA\User_LDAP\Mapping\UserMapping;
+
+/**
+ * Class CleanUp
+ *
+ * a Background job to clean up deleted users
+ *
+ * @package OCA\user_ldap\lib;
+ */
+class CleanUp extends TimedJob {
+ /** @var int $limit amount of users that should be checked per run */
+ protected $limit = 50;
+
+ /** @var int $defaultIntervalMin default interval in minutes */
+ protected $defaultIntervalMin = 51;
+
+ /** @var User_LDAP|User_Proxy $userBackend */
+ protected $userBackend;
+
+ /** @var \OCP\IConfig $ocConfig */
+ protected $ocConfig;
+
+ /** @var \OCP\IDBConnection $db */
+ protected $db;
+
+ /** @var Helper $ldapHelper */
+ protected $ldapHelper;
+
+ /** @var \OCA\User_LDAP\Mapping\UserMapping */
+ protected $mapping;
+
+ /** @var \OCA\User_LDAP\lib\User\DeletedUsersIndex */
+ protected $dui;
+
+ public function __construct() {
+ $minutes = \OC::$server->getConfig()->getSystemValue(
+ 'ldapUserCleanupInterval', strval($this->defaultIntervalMin));
+ $this->setInterval(intval($minutes) * 60);
+ }
+
+ /**
+ * assigns the instances passed to run() to the class properties
+ * @param array $arguments
+ */
+ public function setArguments($arguments) {
+ //Dependency Injection is not possible, because the constructor will
+ //only get values that are serialized to JSON. I.e. whatever we would
+ //pass in app.php we do add here, except something else is passed e.g.
+ //in tests.
+
+ if(isset($arguments['helper'])) {
+ $this->ldapHelper = $arguments['helper'];
+ } else {
+ $this->ldapHelper = new Helper();
+ }
+
+ if(isset($arguments['ocConfig'])) {
+ $this->ocConfig = $arguments['ocConfig'];
+ } else {
+ $this->ocConfig = \OC::$server->getConfig();
+ }
+
+ if(isset($arguments['userBackend'])) {
+ $this->userBackend = $arguments['userBackend'];
+ } else {
+ $this->userBackend = new User_Proxy(
+ $this->ldapHelper->getServerConfigurationPrefixes(true),
+ new LDAP(),
+ $this->ocConfig
+ );
+ }
+
+ if(isset($arguments['db'])) {
+ $this->db = $arguments['db'];
+ } else {
+ $this->db = \OC::$server->getDatabaseConnection();
+ }
+
+ if(isset($arguments['mapping'])) {
+ $this->mapping = $arguments['mapping'];
+ } else {
+ $this->mapping = new UserMapping($this->db);
+ }
+
+ if(isset($arguments['deletedUsersIndex'])) {
+ $this->dui = $arguments['deletedUsersIndex'];
+ } else {
+ $this->dui = new DeletedUsersIndex(
+ $this->ocConfig, $this->db, $this->mapping);
+ }
+ }
+
+ /**
+ * makes the background job do its work
+ * @param array $argument
+ */
+ public function run($argument) {
+ $this->setArguments($argument);
+
+ if(!$this->isCleanUpAllowed()) {
+ return;
+ }
+ $users = $this->mapping->getList($this->getOffset(), $this->limit);
+ if(!is_array($users)) {
+ //something wrong? Let's start from the beginning next time and
+ //abort
+ $this->setOffset(true);
+ return;
+ }
+ $resetOffset = $this->isOffsetResetNecessary(count($users));
+ $this->checkUsers($users);
+ $this->setOffset($resetOffset);
+ }
+
+ /**
+ * checks whether next run should start at 0 again
+ * @param int $resultCount
+ * @return bool
+ */
+ public function isOffsetResetNecessary($resultCount) {
+ return ($resultCount < $this->limit) ? true : false;
+ }
+
+ /**
+ * checks whether cleaning up LDAP users is allowed
+ * @return bool
+ */
+ public function isCleanUpAllowed() {
+ try {
+ if($this->ldapHelper->haveDisabledConfigurations()) {
+ return false;
+ }
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ $enabled = $this->isCleanUpEnabled();
+
+ return $enabled;
+ }
+
+ /**
+ * checks whether clean up is enabled by configuration
+ * @return bool
+ */
+ private function isCleanUpEnabled() {
+ return (bool)$this->ocConfig->getSystemValue(
+ 'ldapUserCleanupInterval', strval($this->defaultIntervalMin));
+ }
+
+ /**
+ * checks users whether they are still existing
+ * @param array $users result from getMappedUsers()
+ */
+ private function checkUsers(array $users) {
+ foreach($users as $user) {
+ $this->checkUser($user);
+ }
+ }
+
+ /**
+ * checks whether a user is still existing in LDAP
+ * @param string[] $user
+ */
+ private function checkUser(array $user) {
+ if($this->userBackend->userExistsOnLDAP($user['name'])) {
+ //still available, all good
+
+ return;
+ }
+
+ $this->dui->markUser($user['name']);
+ }
+
+ /**
+ * gets the offset to fetch users from the mappings table
+ * @return int
+ */
+ private function getOffset() {
+ return intval($this->ocConfig->getAppValue('user_ldap', 'cleanUpJobOffset', 0));
+ }
+
+ /**
+ * sets the new offset for the next run
+ * @param bool $reset whether the offset should be set to 0
+ */
+ public function setOffset($reset = false) {
+ $newOffset = $reset ? 0 :
+ $this->getOffset() + $this->limit;
+ $this->ocConfig->setAppValue('user_ldap', 'cleanUpJobOffset', $newOffset);
+ }
+
+ /**
+ * returns the chunk size (limit in DB speak)
+ * @return int
+ */
+ public function getChunkSize() {
+ return $this->limit;
+ }
+
+}
diff --git a/apps/user_ldap/lib/mapping/abstractmapping.php b/apps/user_ldap/lib/mapping/abstractmapping.php
index 2c45c6bb1c1..cb9db83f683 100644
--- a/apps/user_ldap/lib/mapping/abstractmapping.php
+++ b/apps/user_ldap/lib/mapping/abstractmapping.php
@@ -32,7 +32,7 @@ abstract class AbstractMapping {
}
/**
- * checks whether a provided string represents an exisiting table col
+ * checks whether a provided string represents an existing table col
* @param string $col
* @return bool
*/
@@ -153,6 +153,27 @@ abstract class AbstractMapping {
}
/**
+ * gets a piece of the mapping list
+ * @param int $offset
+ * @param int $limit
+ * @return array
+ */
+ public function getList($offset = null, $limit = null) {
+ $query = $this->dbc->prepare('
+ SELECT
+ `ldap_dn` AS `dn`,
+ `owncloud_name` AS `name`,
+ `directory_uuid` AS `uuid`
+ FROM `' . $this->getTableName() . '`',
+ $limit,
+ $offset
+ );
+
+ $query->execute();
+ return $query->fetchAll();
+ }
+
+ /**
* attempts to map the given entry
* @param string $fdn fully distinguished name (from LDAP)
* @param string $name
diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php
index 39d4b36c8bb..b4e6e33c1f4 100644
--- a/apps/user_ldap/lib/proxy.php
+++ b/apps/user_ldap/lib/proxy.php
@@ -49,16 +49,18 @@ abstract class Proxy {
static $avatarM;
static $userMap;
static $groupMap;
+ static $db;
if(is_null($fs)) {
$ocConfig = \OC::$server->getConfig();
$fs = new FilesystemHelper();
$log = new LogWrapper();
$avatarM = \OC::$server->getAvatarManager();
- $userMap = new UserMapping(\OC::$server->getDatabaseConnection());
- $groupMap = new GroupMapping(\OC::$server->getDatabaseConnection());
+ $db = \OC::$server->getDatabaseConnection();
+ $userMap = new UserMapping($db);
+ $groupMap = new GroupMapping($db);
}
$userManager =
- new user\Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image());
+ new user\Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db);
$connector = new Connection($this->ldap, $configPrefix);
$access = new Access($connector, $this->ldap, $userManager);
$access->setUserMapper($userMap);
diff --git a/apps/user_ldap/lib/user/deletedusersindex.php b/apps/user_ldap/lib/user/deletedusersindex.php
new file mode 100644
index 00000000000..e17ed3384da
--- /dev/null
+++ b/apps/user_ldap/lib/user/deletedusersindex.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * ownCloud – LDAP Helper
+ *
+ * @author Arthur Schiwon
+ * @copyright 2014 Arthur Schiwon <blizzz@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\user_ldap\lib\user;
+
+use OCA\user_ldap\lib\user\OfflineUser;
+use OCA\User_LDAP\Mapping\UserMapping;
+
+/**
+ * Class DeletedUsersIndex
+ * @package OCA\User_LDAP
+ */
+class DeletedUsersIndex {
+ /**
+ * @var \OCP\IConfig $config
+ */
+ protected $config;
+
+ /**
+ * @var \OCP\IDBConnection $db
+ */
+ protected $db;
+
+ /**
+ * @var \OCA\User_LDAP\Mapping\UserMapping $mapping
+ */
+ protected $mapping;
+
+ /**
+ * @var array $deletedUsers
+ */
+ protected $deletedUsers;
+
+ /**
+ * @param OCP\IConfig $config
+ * @param OCP\IDBConnection $db
+ * @param OCA\User_LDAP\Mapping\UserMapping $mapping
+ */
+ public function __construct(\OCP\IConfig $config, \OCP\IDBConnection $db, UserMapping $mapping) {
+ $this->config = $config;
+ $this->db = $db;
+ $this->mapping = $mapping;
+ }
+
+ /**
+ * reads LDAP users marked as deleted from the database
+ * @return OCA\user_ldap\lib\user\OfflineUser[]
+ */
+ private function fetchDeletedUsers() {
+ $deletedUsers = $this->config->getUsersForUserValue(
+ 'user_ldap', 'isDeleted', '1');
+
+ $userObjects = array();
+ foreach($deletedUsers as $user) {
+ $userObjects[] = new OfflineUser($user, $this->config, $this->db, $this->mapping);
+ }
+ $this->deletedUsers = $userObjects;
+
+ return $this->deletedUsers;
+ }
+
+ /**
+ * returns all LDAP users that are marked as deleted
+ * @return OCA\user_ldap\lib\user\OfflineUser[]
+ */
+ public function getUsers() {
+ if(is_array($this->deletedUsers)) {
+ return $this->deletedUsers;
+ }
+ return $this->fetchDeletedUsers();
+ }
+
+ /**
+ * whether at least one user was detected as deleted
+ * @return bool
+ */
+ public function hasUsers() {
+ if($this->deletedUsers === false) {
+ $this->fetchDeletedUsers();
+ }
+ if(is_array($this->deletedUsers) && count($this->deletedUsers) > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * marks a user as deleted
+ * @param string ocName
+ */
+ public function markUser($ocName) {
+ $this->config->setUserValue($ocName, 'user_ldap', 'isDeleted', '1');
+ }
+}
diff --git a/apps/user_ldap/lib/user/iusertools.php b/apps/user_ldap/lib/user/iusertools.php
index bbc678153de..fcb00d2f746 100644
--- a/apps/user_ldap/lib/user/iusertools.php
+++ b/apps/user_ldap/lib/user/iusertools.php
@@ -38,5 +38,4 @@ interface IUserTools {
public function dn2username($dn, $ldapname = null);
public function username2dn($name);
-
}
diff --git a/apps/user_ldap/lib/user/manager.php b/apps/user_ldap/lib/user/manager.php
index 0ed3d09c48f..ec50e031281 100644
--- a/apps/user_ldap/lib/user/manager.php
+++ b/apps/user_ldap/lib/user/manager.php
@@ -27,6 +27,7 @@ use OCA\user_ldap\lib\user\IUserTools;
use OCA\user_ldap\lib\user\User;
use OCA\user_ldap\lib\LogWrapper;
use OCA\user_ldap\lib\FilesystemHelper;
+use OCA\user_ldap\lib\user\OfflineUser;
/**
* Manager
@@ -35,32 +36,31 @@ use OCA\user_ldap\lib\FilesystemHelper;
* cache
*/
class Manager {
- /**
- * @var IUserTools
- */
+ /** @var IUserTools */
protected $access;
- /**
- * @var \OCP\IConfig
- */
+
+ /** @var \OCP\IConfig */
protected $ocConfig;
- /**
- * @var FilesystemHelper
- */
+
+ /** @var \OCP\IDBConnection */
+ protected $db;
+
+ /** @var FilesystemHelper */
protected $ocFilesystem;
- /**
- * @var LogWrapper
- */
+
+ /** @var LogWrapper */
protected $ocLog;
- /**
- * @var \OCP\Image
- */
+
+ /** @var \OCP\Image */
protected $image;
- /**
- * @param \OCP\IAvatarManager
- */
+
+ /** @param \OCP\IAvatarManager */
protected $avatarManager;
+
/**
- * @var string[][]
+ * array['byDN'] \OCA\user_ldap\lib\User[]
+ * ['byUid'] \OCA\user_ldap\lib\User[]
+ * @var array $users
*/
protected $users = array(
'byDN' => array(),
@@ -68,29 +68,25 @@ class Manager {
);
/**
- * @brief Constructor
- * @param \OCP\IConfig respectively an instance that provides the methods
- * setUserValue and getUserValue as implemented in \OCP\Config
- * @param \OCA\user_ldap\lib\FilesystemHelper object that gives access to
- * necessary functions from the OC filesystem
- * @param \OCA\user_ldap\lib\LogWrapper
- * @param \OCP\IAvatarManager
- * @param \OCP\Image an empty image instance
+ * @param \OCP\IConfig $ocConfig
+ * @param \OCA\user_ldap\lib\FilesystemHelper $ocFilesystem object that
+ * gives access to necessary functions from the OC filesystem
+ * @param \OCA\user_ldap\lib\LogWrapper $ocLog
+ * @param \OCP\IAvatarManager $avatarManager
+ * @param \OCP\Image $image an empty image instance
+ * @param \OCP\IDBConnection $db
* @throws Exception when the methods mentioned above do not exist
*/
public function __construct(\OCP\IConfig $ocConfig,
FilesystemHelper $ocFilesystem, LogWrapper $ocLog,
- \OCP\IAvatarManager $avatarManager, \OCP\Image $image) {
+ \OCP\IAvatarManager $avatarManager, \OCP\Image $image, \OCP\IDBConnection $db) {
- if(!method_exists($ocConfig, 'setUserValue')
- || !method_exists($ocConfig, 'getUserValue')) {
- throw new \Exception('Invalid ownCloud User Config object');
- }
$this->ocConfig = $ocConfig;
$this->ocFilesystem = $ocFilesystem;
$this->ocLog = $ocLog;
$this->avatarManager = $avatarManager;
$this->image = $image;
+ $this->db = $db;
}
/**
@@ -131,9 +127,45 @@ class Manager {
}
/**
+ * Checks whether the specified user is marked as deleted
+ * @param string $id the ownCloud user name
+ * @return bool
+ */
+ public function isDeletedUser($id) {
+ $isDeleted = $this->ocConfig->getUserValue(
+ $id, 'user_ldap', 'isDeleted', 0);
+ return intval($isDeleted) === 1;
+ }
+
+ /**
+ * creates and returns an instance of OfflineUser for the specified user
+ * @param string $id
+ * @return \OCA\user_ldap\lib\user\OfflineUser
+ */
+ public function getDeletedUser($id) {
+ return new OfflineUser(
+ $id,
+ $this->ocConfig,
+ $this->db,
+ $this->access->getUserMapper());
+ }
+
+ protected function createInstancyByUserName($id) {
+ //most likely a uid. Check whether it is a deleted user
+ if($this->isDeletedUser($id)) {
+ return $this->getDeletedUser($id);
+ }
+ $dn = $this->access->username2dn($id);
+ if($dn !== false) {
+ return $this->createAndCache($dn, $id);
+ }
+ throw new \Exception('Could not create User instance');
+ }
+
+ /**
* @brief returns a User object by it's DN or ownCloud username
* @param string the DN or username of the user
- * @return \OCA\user_ldap\lib\User | null
+ * @return \OCA\user_ldap\lib\user\User|\OCA\user_ldap\lib\user\OfflineUser|null
*/
public function get($id) {
$this->checkAccess();
@@ -143,25 +175,19 @@ class Manager {
return $this->users['byUid'][$id];
}
- if(!$this->access->stringResemblesDN($id) ) {
- //most likely a uid
- $dn = $this->access->username2dn($id);
- if($dn !== false) {
- return $this->createAndCache($dn, $id);
- }
- } else {
- //so it's a DN
+ if($this->access->stringResemblesDN($id) ) {
$uid = $this->access->dn2username($id);
if($uid !== false) {
return $this->createAndCache($id, $uid);
}
}
- //either funny uid or invalid. Assume funny to be on the safe side.
- $dn = $this->access->username2dn($id);
- if($dn !== false) {
- return $this->createAndCache($dn, $id);
+
+ try {
+ $user = $this->createInstancyByUserName($id);
+ return $user;
+ } catch (\Exception $e) {
+ return null;
}
- return null;
}
}
diff --git a/apps/user_ldap/lib/user/offlineuser.php b/apps/user_ldap/lib/user/offlineuser.php
new file mode 100644
index 00000000000..1833f4be968
--- /dev/null
+++ b/apps/user_ldap/lib/user/offlineuser.php
@@ -0,0 +1,223 @@
+<?php
+
+/**
+ * ownCloud – LDAP User
+ *
+ * @author Arthur Schiwon
+ * @copyright 2014 Arthur Schiwon blizzz@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\user_ldap\lib\user;
+
+use OCA\User_LDAP\Mapping\UserMapping;
+
+class OfflineUser {
+ /**
+ * @var string $ocName
+ */
+ protected $ocName;
+ /**
+ * @var string $dn
+ */
+ protected $dn;
+ /**
+ * @var string $uid the UID as provided by LDAP
+ */
+ protected $uid;
+ /**
+ * @var string $displayName
+ */
+ protected $displayName;
+ /**
+ * @var string $homePath
+ */
+ protected $homePath;
+ /**
+ * @var string $lastLogin the timestamp of the last login
+ */
+ protected $lastLogin;
+ /**
+ * @var string $email
+ */
+ protected $email;
+ /**
+ * @var bool $hasActiveShares
+ */
+ protected $hasActiveShares;
+ /**
+ * @var \OCP\IConfig $config
+ */
+ protected $config;
+ /**
+ * @var \OCP\IDBConnection $db
+ */
+ protected $db;
+ /**
+ * @var \OCA\User_LDAP\Mapping\UserMapping
+ */
+ protected $mapping;
+
+ /**
+ * @param string $ocName
+ * @param OCP\IConfig $config
+ * @param OCP\IDBConnection $db
+ * @param OCA\User_LDAP\Mapping\UserMapping $mapping
+ */
+ public function __construct($ocName, \OCP\IConfig $config, \OCP\IDBConnection $db, UserMapping $mapping) {
+ $this->ocName = $ocName;
+ $this->config = $config;
+ $this->db = $db;
+ $this->mapping = $mapping;
+ $this->fetchDetails();
+ }
+
+ /**
+ * exports the user details in an assoc array
+ * @return array
+ */
+ public function export() {
+ $data = array();
+ $data['ocName'] = $this->getOCName();
+ $data['dn'] = $this->getDN();
+ $data['uid'] = $this->getUID();
+ $data['displayName'] = $this->getDisplayName();
+ $data['homePath'] = $this->getHomePath();
+ $data['lastLogin'] = $this->getLastLogin();
+ $data['email'] = $this->getEmail();
+ $data['hasActiveShares'] = $this->getHasActiveShares();
+
+ return $data;
+ }
+
+ /**
+ * getter for ownCloud internal name
+ * @return string
+ */
+ public function getOCName() {
+ return $this->ocName;
+ }
+
+ /**
+ * getter for LDAP uid
+ * @return string
+ */
+ public function getUID() {
+ return $this->uid;
+ }
+
+ /**
+ * getter for LDAP DN
+ * @return string
+ */
+ public function getDN() {
+ return $this->dn;
+ }
+
+ /**
+ * getter for display name
+ * @return string
+ */
+ public function getDisplayName() {
+ return $this->displayName;
+ }
+
+ /**
+ * getter for email
+ * @return string
+ */
+ public function getEmail() {
+ return $this->email;
+ }
+
+ /**
+ * getter for home directory path
+ * @return string
+ */
+ public function getHomePath() {
+ return $this->homePath;
+ }
+
+ /**
+ * getter for the last login timestamp
+ * @return int
+ */
+ public function getLastLogin() {
+ return intval($this->lastLogin);
+ }
+
+ /**
+ * getter for having active shares
+ * @return bool
+ */
+ public function getHasActiveShares() {
+ return $this->hasActiveShares;
+ }
+
+ /**
+ * reads the user details
+ */
+ protected function fetchDetails() {
+ $properties = array (
+ 'displayName' => 'user_ldap',
+ 'uid' => 'user_ldap',
+ 'homePath' => 'user_ldap',
+ 'email' => 'settings',
+ 'lastLogin' => 'login'
+ );
+ foreach($properties as $property => $app) {
+ $this->$property = $this->config->getUserValue($this->ocName, $app, $property, '');
+ }
+
+ $dn = $this->mapping->getDNByName($this->ocName);
+ $this->dn = ($dn !== false) ? $dn : '';
+
+ $this->determineShares();
+ }
+
+
+ /**
+ * finds out whether the user has active shares. The result is stored in
+ * $this->hasActiveShares
+ */
+ protected function determineShares() {
+ $query = $this->db->prepare('
+ SELECT COUNT(`uid_owner`)
+ FROM `*PREFIX*share`
+ WHERE `uid_owner` = ?
+ ', 1);
+ $query->execute(array($this->ocName));
+ $sResult = $query->fetchColumn(0);
+ if(intval($sResult) === 1) {
+ $this->hasActiveShares = true;
+ return;
+ }
+
+ $query = $this->db->prepare('
+ SELECT COUNT(`owner`)
+ FROM `*PREFIX*share_external`
+ WHERE `owner` = ?
+ ', 1);
+ $query->execute(array($this->ocName));
+ $sResult = $query->fetchColumn(0);
+ if(intval($sResult) === 1) {
+ $this->hasActiveShares = true;
+ return;
+ }
+
+ $this->hasActiveShares = false;
+ }
+}
diff --git a/apps/user_ldap/lib/user/user.php b/apps/user_ldap/lib/user/user.php
index d4d2294307d..7f67ebca39b 100644
--- a/apps/user_ldap/lib/user/user.php
+++ b/apps/user_ldap/lib/user/user.php
@@ -92,7 +92,7 @@ class User {
* @param string the LDAP DN
* @param IUserTools $access an instance that implements IUserTools for
* LDAP interaction
- * @param \OCP\Config
+ * @param \OCP\IConfig
* @param FilesystemHelper
* @param \OCP\Image any empty instance
* @param LogWrapper
@@ -213,6 +213,31 @@ class User {
}
/**
+ * Stores a key-value pair in relation to this user
+ * @param string $key
+ * @param string $value
+ */
+ private function store($key, $value) {
+ $this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
+ }
+
+ /**
+ * Stores the display name in the databae
+ * @param string $displayName
+ */
+ public function storeDisplayName($displayName) {
+ $this->store('displayName', $displayName);
+ }
+
+ /**
+ * Stores the LDAP Username in the Database
+ * @param string $userName
+ */
+ public function storeLDAPUserName($userName) {
+ $this->store('uid', $userName);
+ }
+
+ /**
* @brief checks whether an update method specified by feature was run
* already. If not, it will marked like this, because it is expected that
* the method will be run, when false is returned.
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index 578a920f00e..2e4507a2585 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -659,7 +659,8 @@ class Wizard extends LDAPUtility {
//this did not help :(
//Let's see whether we can parse the Host URL and convert the domain to
//a base DN
- $domain = Helper::getDomainFromURL($this->configuration->ldapHost);
+ $helper = new Helper();
+ $domain = $helper->getDomainFromURL($this->configuration->ldapHost);
if(!$domain) {
return false;
}
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index 5527cf2c6da..a19ec0bda6f 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -35,8 +35,9 @@ OCP\Util::addStyle('user_ldap', 'settings');
// fill template
$tmpl = new OCP\Template('user_ldap', 'settings');
-$prefixes = \OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes();
-$hosts = \OCA\user_ldap\lib\Helper::getServerConfigurationHosts();
+$helper = new \OCA\user_ldap\lib\Helper();
+$prefixes = $helper->getServerConfigurationPrefixes();
+$hosts = $helper->getServerConfigurationHosts();
$wizardHtml = '';
$toc = array();
diff --git a/apps/user_ldap/tests/access.php b/apps/user_ldap/tests/access.php
index 85849229152..5c502f288eb 100644
--- a/apps/user_ldap/tests/access.php
+++ b/apps/user_ldap/tests/access.php
@@ -47,7 +47,8 @@ class Test_Access extends \Test\TestCase {
$this->getMock('\OCA\user_ldap\lib\FilesystemHelper'),
$this->getMock('\OCA\user_ldap\lib\LogWrapper'),
$this->getMock('\OCP\IAvatarManager'),
- $this->getMock('\OCP\Image')));
+ $this->getMock('\OCP\Image'),
+ $this->getMock('\OCP\IDBConnection')));
return array($lw, $connector, $um);
}
diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php
index 0e01eb3ba6f..efd7f803f3b 100644
--- a/apps/user_ldap/tests/group_ldap.php
+++ b/apps/user_ldap/tests/group_ldap.php
@@ -45,7 +45,8 @@ class Test_Group_Ldap extends \Test\TestCase {
$this->getMock('\OCA\user_ldap\lib\FilesystemHelper'),
$this->getMock('\OCA\user_ldap\lib\LogWrapper'),
$this->getMock('\OCP\IAvatarManager'),
- $this->getMock('\OCP\Image')
+ $this->getMock('\OCP\Image'),
+ $this->getMock('\OCP\IDBConnection')
);
$access = $this->getMock('\OCA\user_ldap\lib\Access',
$accMethods,
diff --git a/apps/user_ldap/tests/jobs/cleanup.php b/apps/user_ldap/tests/jobs/cleanup.php
new file mode 100644
index 00000000000..78bda66c54f
--- /dev/null
+++ b/apps/user_ldap/tests/jobs/cleanup.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\user_ldap\tests;
+
+class Test_CleanUp extends \PHPUnit_Framework_TestCase {
+ public function getMocks() {
+ $mocks = array();
+ $mocks['userBackend'] =
+ $this->getMockBuilder('\OCA\user_ldap\User_Proxy')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mocks['deletedUsersIndex'] =
+ $this->getMockBuilder('\OCA\user_ldap\lib\user\deletedUsersIndex')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mocks['ocConfig'] = $this->getMock('\OCP\IConfig');
+ $mocks['db'] = $this->getMock('\OCP\IDBConnection');
+ $mocks['helper'] = $this->getMock('\OCA\user_ldap\lib\Helper');
+
+ return $mocks;
+ }
+
+ /**
+ * clean up job must not run when there are disabled configurations
+ */
+ public function test_runNotAllowedByDisabledConfigurations() {
+ $args = $this->getMocks();
+ $args['helper']->expects($this->once())
+ ->method('haveDisabledConfigurations')
+ ->will($this->returnValue(true) );
+
+ $args['ocConfig']->expects($this->never())
+ ->method('getSystemValue');
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isCleanUpAllowed();
+ $this->assertSame(false, $result);
+ }
+
+ /**
+ * clean up job must not run when LDAP Helper is broken i.e.
+ * returning unexpected results
+ */
+ public function test_runNotAllowedByBrokenHelper() {
+ $args = $this->getMocks();
+ $args['helper']->expects($this->once())
+ ->method('haveDisabledConfigurations')
+ ->will($this->throwException(new \Exception()));
+
+ $args['ocConfig']->expects($this->never())
+ ->method('getSystemValue');
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isCleanUpAllowed();
+ $this->assertSame(false, $result);
+ }
+
+ /**
+ * clean up job must not run when it is not enabled
+ */
+ public function test_runNotAllowedBySysConfig() {
+ $args = $this->getMocks();
+ $args['helper']->expects($this->once())
+ ->method('haveDisabledConfigurations')
+ ->will($this->returnValue(false));
+
+ $args['ocConfig']->expects($this->once())
+ ->method('getSystemValue')
+ ->will($this->returnValue(false));
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isCleanUpAllowed();
+ $this->assertSame(false, $result);
+ }
+
+ /**
+ * clean up job is allowed to run
+ */
+ public function test_runIsAllowed() {
+ $args = $this->getMocks();
+ $args['helper']->expects($this->once())
+ ->method('haveDisabledConfigurations')
+ ->will($this->returnValue(false));
+
+ $args['ocConfig']->expects($this->once())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isCleanUpAllowed();
+ $this->assertSame(true, $result);
+ }
+
+ /**
+ * check whether offset will be reset when it needs to
+ */
+ public function test_OffsetResetIsNecessary() {
+ $args = $this->getMocks();
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isOffsetResetNecessary($bgJob->getChunkSize() - 1);
+ $this->assertSame(true, $result);
+ }
+
+ /**
+ * make sure offset is not reset when it is not due
+ */
+ public function test_OffsetResetIsNotNecessary() {
+ $args = $this->getMocks();
+
+ $bgJob = new \OCA\User_LDAP\Jobs\CleanUp();
+ $bgJob->setArguments($args);
+
+ $result = $bgJob->isOffsetResetNecessary($bgJob->getChunkSize());
+ $this->assertSame(false, $result);
+ }
+
+}
+
diff --git a/apps/user_ldap/tests/mapping/abstractmappingtest.php b/apps/user_ldap/tests/mapping/abstractmappingtest.php
index a5cb62253af..cafa36a4edb 100644
--- a/apps/user_ldap/tests/mapping/abstractmappingtest.php
+++ b/apps/user_ldap/tests/mapping/abstractmappingtest.php
@@ -191,4 +191,28 @@ abstract class AbstractMappingTest extends \Test\TestCase {
$this->assertFalse($name);
}
}
+
+ /**
+ * tests getList() method
+ */
+ public function testList() {
+ list($mapper, $data) = $this->initTest();
+
+ // get all entries without specifying offset or limit
+ $results = $mapper->getList();
+ $this->assertSame(3, count($results));
+
+ // get all-1 entries by specifying offset, and an high limit
+ // specifying only offset without limit will not work by underlying lib
+ $results = $mapper->getList(1, 999);
+ $this->assertSame(count($data) - 1, count($results));
+
+ // get first 2 entries by limit, but not offset
+ $results = $mapper->getList(null, 2);
+ $this->assertSame(2, count($results));
+
+ // get 2nd entry by specifying both offset and limit
+ $results = $mapper->getList(1, 1);
+ $this->assertSame(1, count($results));
+ }
}
diff --git a/apps/user_ldap/tests/user/manager.php b/apps/user_ldap/tests/user/manager.php
index b3e52084dba..4ce504365b8 100644
--- a/apps/user_ldap/tests/user/manager.php
+++ b/apps/user_ldap/tests/user/manager.php
@@ -33,12 +33,13 @@ class Test_User_Manager extends \Test\TestCase {
$log = $this->getMock('\OCA\user_ldap\lib\LogWrapper');
$avaMgr = $this->getMock('\OCP\IAvatarManager');
$image = $this->getMock('\OCP\Image');
+ $dbc = $this->getMock('\OCP\IDBConnection');
- return array($access, $config, $filesys, $image, $log, $avaMgr);
+ return array($access, $config, $filesys, $image, $log, $avaMgr, $dbc);
}
public function testGetByDNExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$inputDN = 'cn=foo,dc=foobar,dc=bar';
@@ -57,7 +58,7 @@ class Test_User_Manager extends \Test\TestCase {
$access->expects($this->never())
->method('username2dn');
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($inputDN);
@@ -65,7 +66,7 @@ class Test_User_Manager extends \Test\TestCase {
}
public function testGetByEDirectoryDN() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$inputDN = 'uid=foo,o=foobar,c=bar';
@@ -84,7 +85,7 @@ class Test_User_Manager extends \Test\TestCase {
$access->expects($this->never())
->method('username2dn');
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($inputDN);
@@ -92,7 +93,7 @@ class Test_User_Manager extends \Test\TestCase {
}
public function testGetByExoticDN() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$inputDN = 'ab=cde,f=ghei,mno=pq';
@@ -111,7 +112,7 @@ class Test_User_Manager extends \Test\TestCase {
$access->expects($this->never())
->method('username2dn');
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($inputDN);
@@ -119,7 +120,7 @@ class Test_User_Manager extends \Test\TestCase {
}
public function testGetByDNNotExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$inputDN = 'cn=gone,dc=foobar,dc=bar';
@@ -139,7 +140,7 @@ class Test_User_Manager extends \Test\TestCase {
->with($this->equalTo($inputDN))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($inputDN);
@@ -147,7 +148,7 @@ class Test_User_Manager extends \Test\TestCase {
}
public function testGetByUidExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$dn = 'cn=foo,dc=foobar,dc=bar';
@@ -166,7 +167,7 @@ class Test_User_Manager extends \Test\TestCase {
->with($this->equalTo($uid))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($uid);
@@ -174,7 +175,7 @@ class Test_User_Manager extends \Test\TestCase {
}
public function testGetByUidNotExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
$dn = 'cn=foo,dc=foobar,dc=bar';
@@ -183,12 +184,12 @@ class Test_User_Manager extends \Test\TestCase {
$access->expects($this->never())
->method('dn2username');
- $access->expects($this->exactly(2))
+ $access->expects($this->exactly(1))
->method('username2dn')
->with($this->equalTo($uid))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image);
+ $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc);
$manager->setLdapAccess($access);
$user = $manager->get($uid);
diff --git a/apps/user_ldap/tests/user/user.php b/apps/user_ldap/tests/user/user.php
index e110921d2d3..5282a9f8b6e 100644
--- a/apps/user_ldap/tests/user/user.php
+++ b/apps/user_ldap/tests/user/user.php
@@ -33,11 +33,12 @@ class Test_User_User extends \Test\TestCase {
$log = $this->getMock('\OCA\user_ldap\lib\LogWrapper');
$avaMgr = $this->getMock('\OCP\IAvatarManager');
$image = $this->getMock('\OCP\Image');
+ $dbc = $this->getMock('\OCP\IDBConnection');
- return array($access, $config, $filesys, $image, $log, $avaMgr);
+ return array($access, $config, $filesys, $image, $log, $avaMgr, $dbc);
}
- private function getAdvancedMocks($cfMock, $fsMock, $logMock, $avaMgr) {
+ private function getAdvancedMocks($cfMock, $fsMock, $logMock, $avaMgr, $dbc) {
static $conMethods;
static $accMethods;
static $umMethods;
@@ -52,7 +53,7 @@ class Test_User_User extends \Test\TestCase {
$lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper');
$im = $this->getMock('\OCP\Image');
$um = $this->getMock('\OCA\user_ldap\lib\user\Manager',
- $umMethods, array($cfMock, $fsMock, $logMock, $avaMgr, $im));
+ $umMethods, array($cfMock, $fsMock, $logMock, $avaMgr, $im, $dbc));
$connector = $this->getMock('\OCA\user_ldap\lib\Connection',
$conMethods, array($lw, null, null));
$access = $this->getMock('\OCA\user_ldap\lib\Access',
@@ -76,11 +77,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateEmailProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->once())
->method('__get')
@@ -110,11 +111,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateEmailNotProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->once())
->method('__get')
@@ -140,11 +141,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateEmailNotConfigured() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->once())
->method('__get')
@@ -167,11 +168,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateQuotaAllProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->at(0))
->method('__get')
@@ -210,11 +211,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateQuotaDefaultProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->at(0))
->method('__get')
@@ -253,11 +254,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateQuotaIndividualProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->at(0))
->method('__get')
@@ -296,11 +297,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateQuotaNoneProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->at(0))
->method('__get')
@@ -334,11 +335,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateQuotaNoneConfigured() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$connection->expects($this->at(0))
->method('__get')
@@ -370,11 +371,11 @@ class Test_User_User extends \Test\TestCase {
//the testUpdateAvatar series also implicitely tests getAvatarImage
public function testUpdateAvatarJpegPhotoProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$access->expects($this->once())
->method('readAttribute')
@@ -419,11 +420,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateAvatarThumbnailPhotoProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$access->expects($this->at(0))
->method('readAttribute')
@@ -477,11 +478,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateAvatarNotProvided() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$access->expects($this->at(0))
->method('readAttribute')
@@ -523,11 +524,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateBeforeFirstLogin() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$config->expects($this->at(0))
->method('getUserValue')
@@ -559,11 +560,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateAfterFirstLogin() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$config->expects($this->at(0))
->method('getUserValue')
@@ -599,11 +600,11 @@ class Test_User_User extends \Test\TestCase {
}
public function testUpdateNoRefresh() {
- list($access, $config, $filesys, $image, $log, $avaMgr) =
+ list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) =
$this->getTestInstances();
list($access, $connection) =
- $this->getAdvancedMocks($config, $filesys, $log, $avaMgr);
+ $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc);
$config->expects($this->at(0))
->method('getUserValue')
diff --git a/apps/user_ldap/tests/user_ldap.php b/apps/user_ldap/tests/user_ldap.php
index 33cec0247b6..3fa4f2bf0a1 100644
--- a/apps/user_ldap/tests/user_ldap.php
+++ b/apps/user_ldap/tests/user_ldap.php
@@ -62,7 +62,8 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
$this->getMock('\OCA\user_ldap\lib\FilesystemHelper'),
$this->getMock('\OCA\user_ldap\lib\LogWrapper'),
$this->getMock('\OCP\IAvatarManager'),
- $this->getMock('\OCP\Image')
+ $this->getMock('\OCP\Image'),
+ $this->getMock('\OCP\IDBConnection')
);
$access = $this->getMock('\OCA\user_ldap\lib\Access',
@@ -123,7 +124,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
->method('fetchListOfUsers')
->will($this->returnCallback(function($filter) {
if($filter === 'roland') {
- return array('dnOfRoland,dc=test');
+ return array(array('dn' => 'dnOfRoland,dc=test'));
}
return array();
}));
@@ -156,7 +157,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = $backend->checkPassword('roland', 'dt19');
@@ -167,7 +168,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = $backend->checkPassword('roland', 'wrong');
@@ -178,7 +179,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = $backend->checkPassword('mallory', 'evil');
@@ -193,7 +194,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
->method('username2dn')
->will($this->returnValue(false));
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = $backend->checkPassword('roland', 'dt19');
@@ -203,7 +204,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testCheckPasswordPublicAPI() {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::checkPassword('roland', 'dt19');
@@ -213,7 +214,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testCheckPasswordPublicAPIWrongPassword() {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::checkPassword('roland', 'wrong');
@@ -223,13 +224,43 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testCheckPasswordPublicAPIWrongUser() {
$access = $this->getAccessMock();
$this->prepareAccessForCheckPassword($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::checkPassword('mallory', 'evil');
$this->assertFalse($result);
}
+ public function testDeleteUserCancel() {
+ $access = $this->getAccessMock();
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
+ $result = $backend->deleteUser('notme');
+ $this->assertFalse($result);
+ }
+
+ public function testDeleteUserSuccess() {
+ $access = $this->getAccessMock();
+ $mapping = $this->getMockBuilder('\OCA\User_LDAP\Mapping\UserMapping')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mapping->expects($this->once())
+ ->method('unmap')
+ ->will($this->returnValue(true));
+ $access->expects($this->once())
+ ->method('getUserMapper')
+ ->will($this->returnValue($mapping));
+
+ $config = $this->getMock('\OCP\IConfig');
+ $config->expects($this->exactly(2))
+ ->method('getUserValue')
+ ->will($this->returnValue(1));
+
+ $backend = new UserLDAP($access, $config);
+
+ $result = $backend->deleteUser('jeremy');
+ $this->assertTrue($result);
+ }
+
/**
* Prepares the Access mock for getUsers tests
* @param \OCA\user_ldap\lib\Access $access mock
@@ -282,7 +313,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersNoParam() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->getUsers();
$this->assertEquals(3, count($result));
@@ -291,7 +322,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersLimitOffset() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->getUsers('', 1, 2);
$this->assertEquals(1, count($result));
@@ -300,7 +331,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersLimitOffset2() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->getUsers('', 2, 1);
$this->assertEquals(2, count($result));
@@ -309,7 +340,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersSearchWithResult() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->getUsers('yo');
$this->assertEquals(2, count($result));
@@ -318,7 +349,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersSearchEmptyResult() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->getUsers('nix');
$this->assertEquals(0, count($result));
@@ -327,7 +358,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersViaAPINoParam() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::getUsers();
@@ -337,7 +368,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersViaAPILimitOffset() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::getUsers('', 1, 2);
@@ -347,7 +378,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersViaAPILimitOffset2() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::getUsers('', 2, 1);
@@ -357,7 +388,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersViaAPISearchWithResult() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::getUsers('yo');
@@ -367,7 +398,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetUsersViaAPISearchEmptyResult() {
$access = $this->getAccessMock();
$this->prepareAccessForGetUsers($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
\OC_User::useBackend($backend);
$result = \OCP\User::getUsers('nix');
@@ -376,7 +407,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testUserExists() {
$access = $this->getAccessMock();
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$this->prepareMockForUserExists($access);
$access->expects($this->any())
@@ -403,7 +434,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testUserExistsPublicAPI() {
$access = $this->getAccessMock();
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$this->prepareMockForUserExists($access);
\OC_User::useBackend($backend);
@@ -431,7 +462,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testDeleteUser() {
$access = $this->getAccessMock();
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
//we do not support deleting users at all
$result = $backend->deleteUser('gunslinger');
@@ -440,7 +471,8 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetHome() {
$access = $this->getAccessMock();
- $backend = new UserLDAP($access);
+ $config = $this->getMock('\OCP\IConfig');
+ $backend = new UserLDAP($access, $config);
$this->prepareMockForUserExists($access);
$access->connection->expects($this->any())
@@ -473,14 +505,17 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
}
}));
+ $datadir = '/my/data/dir';
+ $config->expects($this->once())
+ ->method('getSystemValue')
+ ->will($this->returnValue($datadir));
+
//absolut path
$result = $backend->getHome('gunslinger');
$this->assertEquals('/tmp/rolandshome/', $result);
//datadir-relativ path
$result = $backend->getHome('ladyofshadows');
- $datadir = \OCP\Config::getSystemValue('datadirectory',
- \OC::$SERVERROOT.'/data');
$this->assertEquals($datadir.'/susannah/', $result);
//no path at all – triggers OC default behaviour
@@ -518,7 +553,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetDisplayName() {
$access = $this->getAccessMock();
$this->prepareAccessForGetDisplayName($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$this->prepareMockForUserExists($access);
//with displayName
@@ -533,7 +568,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
public function testGetDisplayNamePublicAPI() {
$access = $this->getAccessMock();
$this->prepareAccessForGetDisplayName($access);
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$this->prepareMockForUserExists($access);
\OC_User::useBackend($backend);
@@ -556,7 +591,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
->method('countUsers')
->will($this->returnValue(5));
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->countUsers();
$this->assertEquals(5, $result);
@@ -569,7 +604,7 @@ class Test_User_Ldap_Direct extends \Test\TestCase {
->method('countUsers')
->will($this->returnValue(false));
- $backend = new UserLDAP($access);
+ $backend = new UserLDAP($access, $this->getMock('\OCP\IConfig'));
$result = $backend->countUsers();
$this->assertFalse($result);
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index 482715b3686..051e760105b 100644
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -26,8 +26,27 @@
namespace OCA\user_ldap;
use OCA\user_ldap\lib\BackendUtility;
+use OCA\user_ldap\lib\Access;
+use OCA\user_ldap\lib\user\OfflineUser;
+use OCA\User_LDAP\lib\User\User;
+use OCP\IConfig;
class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface {
+ /** @var string[] $homesToKill */
+ protected $homesToKill = array();
+
+ /** @var \OCP\IConfig */
+ protected $ocConfig;
+
+ /**
+ * @param \OCA\user_ldap\lib\Access $access
+ * @param \OCP\IConfig $ocConfig
+ */
+ public function __construct(Access $access, IConfig $ocConfig) {
+ parent::__construct($access);
+ $this->ocConfig = $ocConfig;
+ }
+
/**
* checks whether the user is allowed to change his avatar in ownCloud
* @param string $uid the ownCloud user name
@@ -35,7 +54,7 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
*/
public function canChangeAvatar($uid) {
$user = $this->access->userManager->get($uid);
- if(is_null($user)) {
+ if(!$user instanceof User) {
return false;
}
if($user->getAvatarImage() === false) {
@@ -49,7 +68,7 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
* Check if the password is correct
* @param string $uid The username
* @param string $password The password
- * @return boolean
+ * @return false|string
*
* Check if the password is correct without logging in the user
*/
@@ -57,15 +76,17 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$uid = $this->access->escapeFilterPart($uid);
//find out dn of the user name
+ $attrs = array($this->access->connection->ldapUserDisplayName, 'dn',
+ 'uid', 'samaccountname');
$filter = \OCP\Util::mb_str_replace(
'%uid', $uid, $this->access->connection->ldapLoginFilter, 'UTF-8');
- $ldap_users = $this->access->fetchListOfUsers($filter, 'dn');
- if(count($ldap_users) < 1) {
+ $users = $this->access->fetchListOfUsers($filter, $attrs);
+ if(count($users) < 1) {
return false;
}
- $dn = $ldap_users[0];
+ $dn = $users[0]['dn'];
$user = $this->access->userManager->get($dn);
- if(is_null($user)) {
+ if(!$user instanceof User) {
\OCP\Util::writeLog('user_ldap',
'LDAP Login: Could not get user object for DN ' . $dn .
'. Maybe the LDAP entry has no set display name attribute?',
@@ -79,6 +100,15 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
}
$user->markLogin();
+ if(isset($users[0][$this->access->connection->ldapUserDisplayName])) {
+ $dpn = $users[0][$this->access->connection->ldapUserDisplayName];
+ $user->storeDisplayName($dpn);
+ }
+ if(isset($users[0]['uid'])) {
+ $user->storeLDAPUserName($users[0]['uid']);
+ } else if(isset($users[0]['samaccountname'])) {
+ $user->storeLDAPUserName($users[0]['samaccountname']);
+ }
return $user->getUsername();
}
@@ -128,6 +158,33 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
}
/**
+ * checks whether a user is still available on LDAP
+ * @param string|\OCA\User_LDAP\lib\user\User $user either the ownCloud user
+ * name or an instance of that user
+ * @return bool
+ */
+ public function userExistsOnLDAP($user) {
+ if(is_string($user)) {
+ $user = $this->access->userManager->get($user);
+ }
+ if(!$user instanceof User) {
+ return false;
+ }
+
+ $dn = $user->getDN();
+ //check if user really still exists by reading its entry
+ if(!is_array($this->access->readAttribute($dn, ''))) {
+ $lcr = $this->access->connection->getConnectionResource();
+ if(is_null($lcr)) {
+ throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* check if a user exists
* @param string $uid the username
* @return boolean
@@ -143,36 +200,55 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$this->access->connection->ldapHost, \OCP\Util::DEBUG);
$this->access->connection->writeToCache('userExists'.$uid, false);
return false;
+ } else if($user instanceof OfflineUser) {
+ //express check for users marked as deleted. Returning true is
+ //necessary for cleanup
+ return true;
}
- $dn = $user->getDN();
- //check if user really still exists by reading its entry
- if(!is_array($this->access->readAttribute($dn, ''))) {
- \OCP\Util::writeLog('user_ldap', 'LDAP says no user '.$dn.' on '.
- $this->access->connection->ldapHost, \OCP\Util::DEBUG);
- $this->access->connection->writeToCache('userExists'.$uid, false);
+
+ try {
+ $result = $this->userExistsOnLDAP($user);
+ $this->access->connection->writeToCache('userExists'.$uid, $result);
+ if($result === true) {
+ $user->update();
+ }
+ return $result;
+ } catch (\Exception $e) {
+ \OCP\Util::writeLog('user_ldap', $e->getMessage(), \OCP\Util::WARN);
return false;
}
-
- $this->access->connection->writeToCache('userExists'.$uid, true);
- $user->update();
- return true;
}
/**
- * delete a user
+ * returns whether a user was deleted in LDAP
+ *
* @param string $uid The username of the user to delete
* @return bool
- *
- * Deletes a user
*/
public function deleteUser($uid) {
- return false;
+ $marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
+ if(intval($marked) === 0) {
+ \OC::$server->getLogger()->notice(
+ 'User '.$uid . ' is not marked as deleted, not cleaning up.',
+ array('app' => 'user_ldap'));
+ return false;
+ }
+ \OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
+ array('app' => 'user_ldap'));
+
+ //Get Home Directory out of user preferences so we can return it later,
+ //necessary for removing directories as done by OC_User.
+ $home = $this->ocConfig->getUserValue($uid, 'user_ldap', 'homePath', '');
+ $this->homesToKill[$uid] = $home;
+ $this->access->getUserMapper()->unmap($uid);
+
+ return true;
}
/**
* get the user's home directory
* @param string $uid the username
- * @return boolean
+ * @return string|bool
*/
public function getHome($uid) {
// user Exists check required as it is not done in user proxy!
@@ -180,6 +256,11 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return false;
}
+ if(isset($this->homesToKill[$uid]) && !empty($this->homesToKill[$uid])) {
+ //a deleted user who needs some clean up
+ return $this->homesToKill[$uid];
+ }
+
$cacheKey = 'getHome'.$uid;
if($this->access->connection->isCached($cacheKey)) {
return $this->access->connection->getFromCache($cacheKey);
@@ -199,16 +280,23 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
) {
$homedir = $path;
} else {
- $homedir = \OC::$server->getConfig()->getSystemValue('datadirectory',
+ $homedir = $this->ocConfig->getSystemValue('datadirectory',
\OC::$SERVERROOT.'/data' ) . '/' . $homedir[0];
}
$this->access->connection->writeToCache($cacheKey, $homedir);
+ //we need it to store it in the DB as well in case a user gets
+ //deleted so we can clean up afterwards
+ $this->ocConfig->setUserValue(
+ $uid, 'user_ldap', 'homePath', $homedir
+ );
+ //TODO: if home directory changes, the old one needs to be removed.
return $homedir;
}
}
//false will apply default behaviour as defined and done by OC_User
$this->access->connection->writeToCache($cacheKey, false);
+ $this->ocConfig->setUserValue($uid, 'user_ldap', 'homePath', '');
return false;
}
diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php
index 6414a048071..f5912fe1355 100644
--- a/apps/user_ldap/user_proxy.php
+++ b/apps/user_ldap/user_proxy.php
@@ -24,6 +24,9 @@
namespace OCA\user_ldap;
use OCA\user_ldap\lib\ILDAPWrapper;
+use OCA\User_LDAP\lib\User\User;
+use \OCA\user_ldap\User_LDAP;
+use OCP\IConfig;
class User_Proxy extends lib\Proxy implements \OCP\IUserBackend, \OCP\UserInterface {
private $backends = array();
@@ -33,11 +36,11 @@ class User_Proxy extends lib\Proxy implements \OCP\IUserBackend, \OCP\UserInterf
* Constructor
* @param array $serverConfigPrefixes array containing the config Prefixes
*/
- public function __construct($serverConfigPrefixes, ILDAPWrapper $ldap) {
+ public function __construct(array $serverConfigPrefixes, ILDAPWrapper $ldap, IConfig $ocConfig) {
parent::__construct($ldap);
foreach($serverConfigPrefixes as $configPrefix) {
$this->backends[$configPrefix] =
- new \OCA\user_ldap\USER_LDAP($this->getAccess($configPrefix));
+ new User_LDAP($this->getAccess($configPrefix), $ocConfig);
if(is_null($this->refBackend)) {
$this->refBackend = &$this->backends[$configPrefix];
}
@@ -153,6 +156,17 @@ class User_Proxy extends lib\Proxy implements \OCP\IUserBackend, \OCP\UserInterf
}
/**
+ * check if a user exists on LDAP
+ * @param string|OCA\User_LDAP\lib\User\User $user either the ownCloud user
+ * name or an instance of that user
+ * @return boolean
+ */
+ public function userExistsOnLDAP($user) {
+ $id = ($user instanceof User) ? $user->getUsername() : $user;
+ return $this->handleRequest($id, 'userExistsOnLDAP', array($user));
+ }
+
+ /**
* Check if the password is correct
* @param string $uid The username
* @param string $password The password
@@ -217,7 +231,7 @@ class User_Proxy extends lib\Proxy implements \OCP\IUserBackend, \OCP\UserInterf
* Deletes a user
*/
public function deleteUser($uid) {
- return false;
+ return $this->handleRequest($uid, 'deleteUser', array($uid));
}
/**
diff --git a/config/config.sample.php b/config/config.sample.php
index 91428bdc3e4..d0d735ed537 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -80,7 +80,7 @@ $CONFIG = array(
/**
* Where user files are stored; this defaults to ``data/`` in the ownCloud
- * directory. The SQLite database is also stored here, when you use SQLite. (SQLite is
+ * directory. The SQLite database is also stored here, when you use SQLite. (SQLite is
* available only in ownCloud Community Edition)
*/
'datadirectory' => '/var/www/owncloud/data',
@@ -665,6 +665,20 @@ $CONFIG = array(
'OC\Preview\MarkDown'
),
+/**
+ * LDAP
+ *
+ * Global settings used by LDAP User and Group Backend
+ */
+
+/**
+ * defines the interval in minutes for the background job that checks user
+ * existance and marks them as ready to be cleaned up. The number is always
+ * minutes. Setting it to 0 disables the feature.
+ * See command line (occ) methods ldap:show-remnants and user:delete
+ */
+'ldapUserCleanupInterval' => 51,
+
/**
* Maintenance
diff --git a/core/command/user/delete.php b/core/command/user/delete.php
new file mode 100644
index 00000000000..d5ec3ee0bde
--- /dev/null
+++ b/core/command/user/delete.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Core\Command\User;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+
+class Delete extends Command {
+ /** @var \OC\User\Manager */
+ protected $userManager;
+
+ /**
+ * @param \OC\User\Manager $userManager
+ */
+ public function __construct(\OC\User\Manager $userManager) {
+ $this->userManager = $userManager;
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('user:delete')
+ ->setDescription('deletes the specified user')
+ ->addArgument(
+ 'uid',
+ InputArgument::REQUIRED,
+ 'the username'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $wasSuccessful = $this->userManager->get($input->getArgument('uid'))->delete();
+ if($wasSuccessful === true) {
+ $output->writeln('The specified user was deleted');
+ return;
+ }
+ $output->writeln('<error>The specified could not be deleted. Please check the logs.</error>');
+ }
+}
diff --git a/core/register_command.php b/core/register_command.php
index 8f79473ced8..5aa55be3e2c 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -22,5 +22,6 @@ $application->add(new OC\Core\Command\Maintenance\Repair($repair, \OC::$server->
$application->add(new OC\Core\Command\User\Report());
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\LastSeen());
+$application->add(new OC\Core\Command\User\Delete(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\L10n\CreateJs());