diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 5239e52234..7ea578ab9c 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -10,6 +10,8 @@ * @author Morris Jobke * @author Robin Appelman * @author Thomas Müller + * @author Vinicius Brand + * @author Daniel Tygel * * @license AGPL-3.0 * @@ -27,6 +29,13 @@ * */ +\OC::$server->registerService('LDAPUserPluginManager', function() { + return new OCA\User_LDAP\UserPluginManager(); +}); +\OC::$server->registerService('LDAPGroupPluginManager', function() { + return new OCA\User_LDAP\GroupPluginManager(); +}); + $helper = new \OCA\User_LDAP\Helper(\OC::$server->getConfig()); $configPrefixes = $helper->getServerConfigurationPrefixes(true); if(count($configPrefixes) > 0) { @@ -46,12 +55,19 @@ if(count($configPrefixes) > 0) { }); $userSession = \OC::$server->getUserSession(); + $userPluginManager = \OC::$server->query('LDAPUserPluginManager'); + $groupPluginManager = \OC::$server->query('LDAPGroupPluginManager'); + $userBackend = new OCA\User_LDAP\User_Proxy( - $configPrefixes, $ldapWrapper, $ocConfig, $notificationManager, $userSession + $configPrefixes, $ldapWrapper, $ocConfig, $notificationManager, $userSession, $userPluginManager ); - $groupBackend = new OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper); + $groupBackend = new OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper, $groupPluginManager); // register user backend OC_User::useBackend($userBackend); + + // Hook to allow plugins to work on registered backends + OC::$server->getEventDispatcher()->dispatch('OCA\\User_LDAP\\User\\User::postLDAPBackendAdded'); + \OC::$server->getGroupManager()->addBackend($groupBackend); } diff --git a/apps/user_ldap/appinfo/register_command.php b/apps/user_ldap/appinfo/register_command.php index bd706e61f2..495445b3fa 100644 --- a/apps/user_ldap/appinfo/register_command.php +++ b/apps/user_ldap/appinfo/register_command.php @@ -37,7 +37,8 @@ $uBackend = new User_Proxy( new LDAP(), $ocConfig, \OC::$server->getNotificationManager(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + \OC::$server->query('LDAPUserPluginManager') ); $deletedUsersIndex = new DeletedUsersIndex( $ocConfig, $dbConnection, $userMapping diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php index 6558af0021..0962fe2c4e 100644 --- a/apps/user_ldap/composer/composer/autoload_classmap.php +++ b/apps/user_ldap/composer/composer/autoload_classmap.php @@ -24,9 +24,13 @@ return array( 'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => $baseDir . '/../lib/Exceptions/ConstraintViolationException.php', 'OCA\\User_LDAP\\Exceptions\\NotOnLDAP' => $baseDir . '/../lib/Exceptions/NotOnLDAP.php', 'OCA\\User_LDAP\\FilesystemHelper' => $baseDir . '/../lib/FilesystemHelper.php', + 'OCA\\User_LDAP\\GroupPluginManager' => $baseDir . '/../lib/GroupPluginManager.php', 'OCA\\User_LDAP\\Group_LDAP' => $baseDir . '/../lib/Group_LDAP.php', 'OCA\\User_LDAP\\Group_Proxy' => $baseDir . '/../lib/Group_Proxy.php', 'OCA\\User_LDAP\\Helper' => $baseDir . '/../lib/Helper.php', + 'OCA\\User_LDAP\\IGroupLDAP' => $baseDir . '/../lib/IGroupLDAP.php', + 'OCA\\User_LDAP\\ILDAPGroupPlugin' => $baseDir . '/../lib/ILDAPGroupPlugin.php', + 'OCA\\User_LDAP\\ILDAPUserPlugin' => $baseDir . '/../lib/ILDAPUserPlugin.php', 'OCA\\User_LDAP\\ILDAPWrapper' => $baseDir . '/../lib/ILDAPWrapper.php', 'OCA\\User_LDAP\\IUserLDAP' => $baseDir . '/../lib/IUserLDAP.php', 'OCA\\User_LDAP\\Jobs\\CleanUp' => $baseDir . '/../lib/Jobs/CleanUp.php', @@ -47,6 +51,7 @@ return array( 'OCA\\User_LDAP\\Proxy' => $baseDir . '/../lib/Proxy.php', 'OCA\\User_LDAP\\Settings\\Admin' => $baseDir . '/../lib/Settings/Admin.php', 'OCA\\User_LDAP\\Settings\\Section' => $baseDir . '/../lib/Settings/Section.php', + 'OCA\\User_LDAP\\UserPluginManager' => $baseDir . '/../lib/UserPluginManager.php', 'OCA\\User_LDAP\\User\\DeletedUsersIndex' => $baseDir . '/../lib/User/DeletedUsersIndex.php', 'OCA\\User_LDAP\\User\\IUserTools' => $baseDir . '/../lib/User/IUserTools.php', 'OCA\\User_LDAP\\User\\Manager' => $baseDir . '/../lib/User/Manager.php', diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php index f80900f790..ece7dd69d2 100644 --- a/apps/user_ldap/composer/composer/autoload_static.php +++ b/apps/user_ldap/composer/composer/autoload_static.php @@ -39,9 +39,13 @@ class ComposerStaticInitUser_LDAP 'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => __DIR__ . '/..' . '/../lib/Exceptions/ConstraintViolationException.php', 'OCA\\User_LDAP\\Exceptions\\NotOnLDAP' => __DIR__ . '/..' . '/../lib/Exceptions/NotOnLDAP.php', 'OCA\\User_LDAP\\FilesystemHelper' => __DIR__ . '/..' . '/../lib/FilesystemHelper.php', + 'OCA\\User_LDAP\\GroupPluginManager' => __DIR__ . '/..' . '/../lib/GroupPluginManager.php', 'OCA\\User_LDAP\\Group_LDAP' => __DIR__ . '/..' . '/../lib/Group_LDAP.php', 'OCA\\User_LDAP\\Group_Proxy' => __DIR__ . '/..' . '/../lib/Group_Proxy.php', 'OCA\\User_LDAP\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', + 'OCA\\User_LDAP\\IGroupLDAP' => __DIR__ . '/..' . '/../lib/IGroupLDAP.php', + 'OCA\\User_LDAP\\ILDAPGroupPlugin' => __DIR__ . '/..' . '/../lib/ILDAPGroupPlugin.php', + 'OCA\\User_LDAP\\ILDAPUserPlugin' => __DIR__ . '/..' . '/../lib/ILDAPUserPlugin.php', 'OCA\\User_LDAP\\ILDAPWrapper' => __DIR__ . '/..' . '/../lib/ILDAPWrapper.php', 'OCA\\User_LDAP\\IUserLDAP' => __DIR__ . '/..' . '/../lib/IUserLDAP.php', 'OCA\\User_LDAP\\Jobs\\CleanUp' => __DIR__ . '/..' . '/../lib/Jobs/CleanUp.php', @@ -62,6 +66,7 @@ class ComposerStaticInitUser_LDAP 'OCA\\User_LDAP\\Proxy' => __DIR__ . '/..' . '/../lib/Proxy.php', 'OCA\\User_LDAP\\Settings\\Admin' => __DIR__ . '/..' . '/../lib/Settings/Admin.php', 'OCA\\User_LDAP\\Settings\\Section' => __DIR__ . '/..' . '/../lib/Settings/Section.php', + 'OCA\\User_LDAP\\UserPluginManager' => __DIR__ . '/..' . '/../lib/UserPluginManager.php', 'OCA\\User_LDAP\\User\\DeletedUsersIndex' => __DIR__ . '/..' . '/../lib/User/DeletedUsersIndex.php', 'OCA\\User_LDAP\\User\\IUserTools' => __DIR__ . '/..' . '/../lib/User/IUserTools.php', 'OCA\\User_LDAP\\User\\Manager' => __DIR__ . '/..' . '/../lib/User/Manager.php', diff --git a/apps/user_ldap/lib/Command/Search.php b/apps/user_ldap/lib/Command/Search.php index d348d5b31c..4b2212a43c 100644 --- a/apps/user_ldap/lib/Command/Search.php +++ b/apps/user_ldap/lib/Command/Search.php @@ -111,7 +111,7 @@ class Search extends Command { $this->validateOffsetAndLimit($offset, $limit); if($input->getOption('group')) { - $proxy = new Group_Proxy($configPrefixes, $ldapWrapper); + $proxy = new Group_Proxy($configPrefixes, $ldapWrapper, \OC::$server->query('LDAPGroupPluginManager')); $getMethod = 'getGroups'; $printID = false; // convert the limit of groups to null. This will show all the groups available instead of @@ -125,7 +125,8 @@ class Search extends Command { $ldapWrapper, $this->ocConfig, \OC::$server->getNotificationManager(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + \OC::$server->query('LDAPUserPluginManager') ); $getMethod = 'getDisplayNames'; $printID = true; diff --git a/apps/user_ldap/lib/GroupPluginManager.php b/apps/user_ldap/lib/GroupPluginManager.php new file mode 100644 index 0000000000..50b50315b8 --- /dev/null +++ b/apps/user_ldap/lib/GroupPluginManager.php @@ -0,0 +1,169 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP; + +use OCP\GroupInterface; + +class GroupPluginManager { + + private $respondToActions = 0; + + private $which = array( + GroupInterface::CREATE_GROUP => null, + GroupInterface::DELETE_GROUP => null, + GroupInterface::ADD_TO_GROUP => null, + GroupInterface::REMOVE_FROM_GROUP => null, + GroupInterface::COUNT_USERS => null, + GroupInterface::GROUP_DETAILS => null + ); + + /** + * @return int All implemented actions + */ + public function getImplementedActions() { + return $this->respondToActions; + } + + /** + * Registers a group plugin that may implement some actions, overriding User_LDAP's group actions. + * @param ILDAPGroupPlugin $plugin + */ + public function register(ILDAPGroupPlugin $plugin) { + $respondToActions = $plugin->respondToActions(); + $this->respondToActions |= $respondToActions; + + foreach($this->which as $action => $v) { + if ((bool)($respondToActions & $action)) { + $this->which[$action] = $plugin; + \OC::$server->getLogger()->debug("Registered action ".$action." to plugin ".get_class($plugin), ['app' => 'user_ldap']); + } + } + } + + /** + * Signal if there is a registered plugin that implements some given actions + * @param int $actions Actions defined in \OCP\GroupInterface, like GroupInterface::REMOVE_FROM_GROUP + * @return bool + */ + public function implementsActions($actions) { + return ($actions & $this->respondToActions) == $actions; + } + + /** + * Create a group + * @param string $gid Group Id + * @return string | null The group DN if group creation was successful. + * @throws \Exception + */ + public function createGroup($gid) { + $plugin = $this->which[GroupInterface::CREATE_GROUP]; + + if ($plugin) { + return $plugin->createGroup($gid); + } + throw new \Exception('No plugin implements createGroup in this LDAP Backend.'); + } + + /** + * Delete a group + * @param string $gid Group Id of the group to delete + * @return bool + * @throws \Exception + */ + public function deleteGroup($gid) { + $plugin = $this->which[GroupInterface::DELETE_GROUP]; + + if ($plugin) { + return $plugin->deleteGroup($gid); + } + throw new \Exception('No plugin implements deleteGroup in this LDAP Backend.'); + } + + /** + * Add a user to a group + * @param string $uid ID of the user to add to group + * @param string $gid ID of the group in which add the user + * @return bool + * @throws \Exception + * + * Adds a user to a group. + */ + public function addToGroup($uid, $gid) { + $plugin = $this->which[GroupInterface::ADD_TO_GROUP]; + + if ($plugin) { + return $plugin->addToGroup($uid, $gid); + } + throw new \Exception('No plugin implements addToGroup in this LDAP Backend.'); + } + + /** + * Removes a user from a group + * @param string $uid ID of the user to remove from group + * @param string $gid ID of the group from which remove the user + * @return bool + * @throws \Exception + * + * removes the user from a group. + */ + public function removeFromGroup($uid, $gid) { + $plugin = $this->which[GroupInterface::REMOVE_FROM_GROUP]; + + if ($plugin) { + return $plugin->removeFromGroup($uid, $gid); + } + throw new \Exception('No plugin implements removeFromGroup in this LDAP Backend.'); + } + + /** + * get the number of all users matching the search string in a group + * @param string $gid ID of the group + * @param string $search query string + * @return int|false + * @throws \Exception + */ + public function countUsersInGroup($gid, $search = '') { + $plugin = $this->which[GroupInterface::COUNT_USERS]; + + if ($plugin) { + return $plugin->countUsersInGroup($gid,$search); + } + throw new \Exception('No plugin implements countUsersInGroup in this LDAP Backend.'); + } + + /** + * get an array with group details + * @param string $gid + * @return array|false + * @throws \Exception + */ + public function getGroupDetails($gid) { + $plugin = $this->which[GroupInterface::GROUP_DETAILS]; + + if ($plugin) { + return $plugin->getGroupDetails($gid); + } + throw new \Exception('No plugin implements getGroupDetails in this LDAP Backend.'); + } +} diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php index 55d31649f1..09303276c2 100644 --- a/apps/user_ldap/lib/Group_LDAP.php +++ b/apps/user_ldap/lib/Group_LDAP.php @@ -39,8 +39,9 @@ namespace OCA\User_LDAP; use OC\Cache\CappedMemoryCache; +use OCP\GroupInterface; -class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { +class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLDAP { protected $enabled = false; /** @@ -53,7 +54,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { */ protected $cachedGroupsByMember; - public function __construct(Access $access) { + /** @var GroupPluginManager */ + protected $groupPluginManager; + + public function __construct(Access $access, GroupPluginManager $groupPluginManager) { parent::__construct($access); $filter = $this->access->connection->ldapGroupFilter; $gassoc = $this->access->connection->ldapGroupMemberAssocAttr; @@ -63,6 +67,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { $this->cachedGroupMembers = new CappedMemoryCache(); $this->cachedGroupsByMember = new CappedMemoryCache(); + $this->groupPluginManager = $groupPluginManager; } /** @@ -860,6 +865,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { * @return int|bool */ public function countUsersInGroup($gid, $search = '') { + if ($this->groupPluginManager->implementsActions(GroupInterface::COUNT_USERS)) { + return $this->groupPluginManager->countUsersInGroup($gid, $search); + } + $cacheKey = 'countUsersInGroup-'.$gid.'-'.$search; if(!$this->enabled || !$this->groupExists($gid)) { return false; @@ -1067,17 +1076,114 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { * @return boolean * * Returns the supported actions as int to be - * compared with \OC\User\Backend::CREATE_USER etc. + * compared with GroupInterface::CREATE_GROUP etc. */ public function implementsActions($actions) { - return (bool)(\OC\Group\Backend::COUNT_USERS & $actions); + return (bool)((GroupInterface::COUNT_USERS | + $this->groupPluginManager->getImplementedActions()) & $actions); } /** * Return access for LDAP interaction. * @return Access instance of Access for LDAP interaction */ - public function getLDAPAccess() { + public function getLDAPAccess($gid) { return $this->access; } + + /** + * create a group + * @param string $gid + * @return bool + * @throws \Exception + */ + public function createGroup($gid) { + if ($this->groupPluginManager->implementsActions(GroupInterface::CREATE_GROUP)) { + if ($dn = $this->groupPluginManager->createGroup($gid)) { + //updates group mapping + $this->access->dn2ocname($dn, $gid, false); + $this->access->connection->writeToCache("groupExists".$gid, true); + } + return $dn != null; + } + throw new \Exception('Could not create group in LDAP backend.'); + } + + /** + * delete a group + * @param string $gid gid of the group to delete + * @return bool + * @throws \Exception + */ + public function deleteGroup($gid) { + if ($this->groupPluginManager->implementsActions(GroupInterface::DELETE_GROUP)) { + if ($ret = $this->groupPluginManager->deleteGroup($gid)) { + #delete group in nextcloud internal db + $this->access->getGroupMapper()->unmap($gid); + $this->access->connection->writeToCache("groupExists".$gid, false); + } + return $ret; + } + throw new \Exception('Could not delete group in LDAP backend.'); + } + + /** + * Add a user to a group + * @param string $uid Name of the user to add to group + * @param string $gid Name of the group in which add the user + * @return bool + * @throws \Exception + */ + public function addToGroup($uid, $gid) { + if ($this->groupPluginManager->implementsActions(GroupInterface::ADD_TO_GROUP)) { + if ($ret = $this->groupPluginManager->addToGroup($uid, $gid)) { + $this->access->connection->clearCache(); + } + return $ret; + } + throw new \Exception('Could not add user to group in LDAP backend.'); + } + + /** + * Removes a user from a group + * @param string $uid Name of the user to remove from group + * @param string $gid Name of the group from which remove the user + * @return bool + * @throws \Exception + */ + public function removeFromGroup($uid, $gid) { + if ($this->groupPluginManager->implementsActions(GroupInterface::REMOVE_FROM_GROUP)) { + if ($ret = $this->groupPluginManager->removeFromGroup($uid, $gid)) { + $this->access->connection->clearCache(); + } + return $ret; + } + throw new \Exception('Could not remove user from group in LDAP backend.'); + } + + /** + * Gets group details + * @param string $gid Name of the group + * @return array | false + * @throws \Exception + */ + public function getGroupDetails($gid) { + if ($this->groupPluginManager->implementsActions(GroupInterface::GROUP_DETAILS)) { + return $this->groupPluginManager->getGroupDetails($gid); + } + throw new \Exception('Could not get group details in LDAP backend.'); + } + + /** + * Return LDAP connection resource from a cloned connection. + * The cloned connection needs to be closed manually. + * of the current access. + * @param string $gid + * @return resource of the LDAP connection + */ + public function getNewLDAPConnection($gid) { + $connection = clone $this->access->getConnection(); + return $connection->getConnectionResource(); + } + } diff --git a/apps/user_ldap/lib/Group_Proxy.php b/apps/user_ldap/lib/Group_Proxy.php index e546c84a90..50c46dfbc0 100644 --- a/apps/user_ldap/lib/Group_Proxy.php +++ b/apps/user_ldap/lib/Group_Proxy.php @@ -26,7 +26,7 @@ namespace OCA\User_LDAP; -class Group_Proxy extends Proxy implements \OCP\GroupInterface { +class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP { private $backends = array(); private $refBackend = null; @@ -34,11 +34,11 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface { * Constructor * @param string[] $serverConfigPrefixes array containing the config Prefixes */ - public function __construct($serverConfigPrefixes, ILDAPWrapper $ldap) { + public function __construct($serverConfigPrefixes, ILDAPWrapper $ldap, GroupPluginManager $groupPluginManager) { parent::__construct($ldap); foreach($serverConfigPrefixes as $configPrefix) { $this->backends[$configPrefix] = - new \OCA\User_LDAP\Group_LDAP($this->getAccess($configPrefix)); + new \OCA\User_LDAP\Group_LDAP($this->getAccess($configPrefix), $groupPluginManager); if(is_null($this->refBackend)) { $this->refBackend = &$this->backends[$configPrefix]; } @@ -145,6 +145,51 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface { return $users; } + /** + * @param string $gid + * @return bool + */ + public function createGroup($gid) { + return $this->handleRequest( + $gid, 'createGroup', array($gid)); + } + + /** + * delete a group + * @param string $gid gid of the group to delete + * @return bool + */ + public function deleteGroup($gid) { + return $this->handleRequest( + $gid, 'deleteGroup', array($gid)); + } + + /** + * Add a user to a group + * @param string $uid Name of the user to add to group + * @param string $gid Name of the group in which add the user + * @return bool + * + * Adds a user to a group. + */ + public function addToGroup($uid, $gid) { + return $this->handleRequest( + $gid, 'addToGroup', array($uid, $gid)); + } + + /** + * Removes a user from a group + * @param string $uid Name of the user to remove from group + * @param string $gid Name of the group from which remove the user + * @return bool + * + * removes the user from a group. + */ + public function removeFromGroup($uid, $gid) { + return $this->handleRequest( + $gid, 'removeFromGroup', array($uid, $gid)); + } + /** * returns the number of users in a group, who match the search term * @param string $gid the internal group name @@ -156,6 +201,16 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface { $gid, 'countUsersInGroup', array($gid, $search)); } + /** + * get an array with group details + * @param string $gid + * @return array|false + */ + public function getGroupDetails($gid) { + return $this->handleRequest( + $gid, 'getGroupDetails', array($gid)); + } + /** * get a list of all groups * @return string[] with group names @@ -190,7 +245,7 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface { * @return boolean * * Returns the supported actions as int to be - * compared with \OC\User\Backend::CREATE_USER etc. + * compared with \OCP\GroupInterface::CREATE_GROUP etc. */ public function implementsActions($actions) { //it's the same across all our user backends obviously @@ -203,6 +258,17 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface { * @return Access instance of Access for LDAP interaction */ public function getLDAPAccess($gid) { - return $this->handleRequest($gid, 'getLDAPAccess', []); + return $this->handleRequest($gid, 'getLDAPAccess', [$gid]); } + + /** + * Return a new LDAP connection for the specified group. + * The connection needs to be closed manually. + * @param string $gid + * @return resource of the LDAP connection + */ + public function getNewLDAPConnection($gid) { + return $this->handleRequest($gid, 'getNewLDAPConnection', array($gid)); + } + } diff --git a/apps/user_ldap/lib/Helper.php b/apps/user_ldap/lib/Helper.php index 891ab7f0a3..ce65ee2909 100644 --- a/apps/user_ldap/lib/Helper.php +++ b/apps/user_ldap/lib/Helper.php @@ -294,10 +294,12 @@ class Helper { $ldapWrapper = new LDAP(); $ocConfig = \OC::$server->getConfig(); $notificationManager = \OC::$server->getNotificationManager(); + $userSession = \OC::$server->getUserSession(); + $userPluginManager = \OC::$server->query('LDAPUserPluginManager'); $userBackend = new User_Proxy( - $configPrefixes, $ldapWrapper, $ocConfig, $notificationManager, $userSession + $configPrefixes, $ldapWrapper, $ocConfig, $notificationManager, $userSession, $userPluginManager ); $uid = $userBackend->loginName2UserName($param['uid'] ); if($uid !== false) { diff --git a/apps/user_ldap/lib/IGroupLDAP.php b/apps/user_ldap/lib/IGroupLDAP.php new file mode 100644 index 0000000000..378e182fb6 --- /dev/null +++ b/apps/user_ldap/lib/IGroupLDAP.php @@ -0,0 +1,45 @@ + + * + * @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 . + * + */ + +namespace OCA\User_LDAP; + +interface IGroupLDAP { + + //Used by LDAPProvider + + /** + * Return access for LDAP interaction. + * @param string $gid + * @return Access instance of Access for LDAP interaction + */ + public function getLDAPAccess($gid); + + /** + * Return a new LDAP connection for the specified group. + * @param string $gid + * @return resource of the LDAP connection + */ + public function getNewLDAPConnection($gid); + +} diff --git a/apps/user_ldap/lib/ILDAPGroupPlugin.php b/apps/user_ldap/lib/ILDAPGroupPlugin.php new file mode 100644 index 0000000000..8afc4c8648 --- /dev/null +++ b/apps/user_ldap/lib/ILDAPGroupPlugin.php @@ -0,0 +1,86 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP; + + +interface ILDAPGroupPlugin { + + /** + * Check if plugin implements actions + * @return int + * + * Returns the supported actions as int to be + * compared with OC_GROUP_BACKEND_CREATE_GROUP etc. + */ + public function respondToActions(); + + /** + * @param string $gid + * @return string|null The group DN if group creation was successful. + */ + public function createGroup($gid); + + /** + * delete a group + * @param string $gid gid of the group to delete + * @return bool + */ + public function deleteGroup($gid); + + /** + * Add a user to a group + * @param string $uid Name of the user to add to group + * @param string $gid Name of the group in which add the user + * @return bool + * + * Adds a user to a group. + */ + public function addToGroup($uid, $gid); + + /** + * Removes a user from a group + * @param string $uid Name of the user to remove from group + * @param string $gid Name of the group from which remove the user + * @return bool + * + * removes the user from a group. + */ + public function removeFromGroup($uid, $gid); + + /** + * get the number of all users matching the search string in a group + * @param string $gid + * @param string $search + * @return int|false + */ + public function countUsersInGroup($gid, $search = ''); + + /** + * get an array with group details + * @param string $gid + * @return array|false + */ + public function getGroupDetails($gid); + +} diff --git a/apps/user_ldap/lib/ILDAPUserPlugin.php b/apps/user_ldap/lib/ILDAPUserPlugin.php new file mode 100644 index 0000000000..d2e8544c8a --- /dev/null +++ b/apps/user_ldap/lib/ILDAPUserPlugin.php @@ -0,0 +1,93 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP; + + +interface ILDAPUserPlugin { + + /** + * Check if plugin implements actions + * @return int + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function respondToActions(); + + /** + * Create a new user in LDAP Backend + * + * @param string $uid The UID of the user to create + * @param string $password The password of the new user + * @return bool + */ + public function createUser($uid, $password); + + /** + * Set password + * + * @param string $uid The username + * @param string $password The new password + * @return bool + * + * Change the password of a user + */ + public function setPassword($uid, $password); + + /** + * get the user's home directory + * @param string $uid the username + * @return boolean + */ + public function getHome($uid); + + /** + * get display name of the user + * @param string $uid user ID of the user + * @return string display name + */ + public function getDisplayName($uid); + + /** + * set display name of the user + * @param string $uid user ID of the user + * @param string $displayName new user's display name + * @return string display name + */ + public function setDisplayName($uid, $displayName); + + /** + * checks whether the user is allowed to change his avatar in Nextcloud + * @param string $uid the Nextcloud user name + * @return boolean either the user can or cannot + */ + public function canChangeAvatar($uid); + + /** + * Count the number of users + * @return int|bool + */ + public function countUsers(); + +} diff --git a/apps/user_ldap/lib/ILDAPWrapper.php b/apps/user_ldap/lib/ILDAPWrapper.php index 71dd60c372..e5969cc298 100644 --- a/apps/user_ldap/lib/ILDAPWrapper.php +++ b/apps/user_ldap/lib/ILDAPWrapper.php @@ -163,7 +163,7 @@ interface ILDAPWrapper { * @return resource|false an LDAP search result resource, false on error */ public function search($link, $baseDN, $filter, $attr, $attrsOnly = 0, $limit = 0); - + /** * Replace the value of a userPassword by $password * @param resource $link LDAP link resource diff --git a/apps/user_ldap/lib/Jobs/CleanUp.php b/apps/user_ldap/lib/Jobs/CleanUp.php index 44e8f5469f..92bca036b2 100644 --- a/apps/user_ldap/lib/Jobs/CleanUp.php +++ b/apps/user_ldap/lib/Jobs/CleanUp.php @@ -100,7 +100,8 @@ class CleanUp extends TimedJob { new LDAP(), $this->ocConfig, \OC::$server->getNotificationManager(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + \OC::$server->query('LDAPUserPluginManager') ); } diff --git a/apps/user_ldap/lib/Jobs/UpdateGroups.php b/apps/user_ldap/lib/Jobs/UpdateGroups.php index 4c9a06a5f6..7e4f0c0c1b 100644 --- a/apps/user_ldap/lib/Jobs/UpdateGroups.php +++ b/apps/user_ldap/lib/Jobs/UpdateGroups.php @@ -193,9 +193,9 @@ class UpdateGroups extends \OC\BackgroundJob\TimedJob { $userMapper = new UserMapping($dbc); $ldapAccess->setGroupMapper($groupMapper); $ldapAccess->setUserMapper($userMapper); - self::$groupBE = new \OCA\User_LDAP\Group_LDAP($ldapAccess); + self::$groupBE = new \OCA\User_LDAP\Group_LDAP($ldapAccess, \OC::$server->query('LDAPGroupPluginManager')); } else { - self::$groupBE = new \OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper); + self::$groupBE = new \OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper, \OC::$server->query('LDAPGroupPluginManager')); } return self::$groupBE; diff --git a/apps/user_ldap/lib/LDAPProvider.php b/apps/user_ldap/lib/LDAPProvider.php index bf8691006c..c62372bdd1 100644 --- a/apps/user_ldap/lib/LDAPProvider.php +++ b/apps/user_ldap/lib/LDAPProvider.php @@ -3,6 +3,10 @@ * * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de) * + * @author Roger Szabo + * @author Vinicius Brand + * @author Daniel Tygel + * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -33,7 +37,8 @@ use OCA\User_LDAP\User\DeletedUsersIndex; */ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { - private $backend; + private $userBackend; + private $groupBackend; private $logger; private $helper; private $deletedUsersIndex; @@ -41,20 +46,36 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { /** * Create new LDAPProvider * @param \OCP\IServerContainer $serverContainer + * @param Helper $helper + * @param DeletedUsersIndex $deletedUsersIndex * @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; + $userBackendFound = false; + $groupBackendFound = false; foreach ($serverContainer->getUserManager()->getBackends() as $backend){ - $this->logger->debug('instance '.get_class($backend).' backend.', ['app' => 'user_ldap']); + $this->logger->debug('instance '.get_class($backend).' user backend.', ['app' => 'user_ldap']); if ($backend instanceof IUserLDAP) { - $this->backend = $backend; - return; + $this->userBackend = $backend; + $userBackendFound = true; + break; } } - throw new \Exception('To use the LDAPProvider, user_ldap app must be enabled'); + foreach ($serverContainer->getGroupManager()->getBackends() as $backend){ + $this->logger->debug('instance '.get_class($backend).' group backend.', ['app' => 'user_ldap']); + if ($backend instanceof IGroupLDAP) { + $this->groupBackend = $backend; + $groupBackendFound = true; + break; + } + } + + if (!$userBackendFound or !$groupBackendFound) { + throw new \Exception('To use the LDAPProvider, user_ldap app must be enabled'); + } } /** @@ -64,16 +85,33 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if translation was unsuccessful */ public function getUserDN($uid) { - if(!$this->backend->userExists($uid)){ + if(!$this->userBackend->userExists($uid)){ throw new \Exception('User id not found in LDAP'); } - $result = $this->backend->getLDAPAccess($uid)->username2dn($uid); + $result = $this->userBackend->getLDAPAccess($uid)->username2dn($uid); if(!$result){ throw new \Exception('Translation to LDAP DN unsuccessful'); } return $result; } - + + /** + * Translate a group id to LDAP DN. + * @param string $gid group id + * @return string + * @throws \Exception + */ + public function getGroupDN($gid) { + if(!$this->groupBackend->groupExists($gid)){ + throw new \Exception('Group id not found in LDAP'); + } + $result = $this->groupBackend->getLDAPAccess($gid)->groupname2dn($gid); + 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. @@ -82,7 +120,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if translation was unsuccessful */ public function getUserName($dn) { - $result = $this->backend->dn2UserName($dn); + $result = $this->userBackend->dn2UserName($dn); if(!$result){ throw new \Exception('Translation to internal user name unsuccessful'); } @@ -115,10 +153,24 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if user id was not found in LDAP */ public function getLDAPConnection($uid) { - if(!$this->backend->userExists($uid)){ + if(!$this->userBackend->userExists($uid)){ throw new \Exception('User id not found in LDAP'); } - return $this->backend->getNewLDAPConnection($uid); + return $this->userBackend->getNewLDAPConnection($uid); + } + + /** + * Return a new LDAP connection resource for the specified user. + * The connection must be closed manually. + * @param string $gid group id + * @return resource of the LDAP connection + * @throws \Exception if group id was not found in LDAP + */ + public function getGroupLDAPConnection($gid) { + if(!$this->groupBackend->groupExists($gid)){ + throw new \Exception('Group id not found in LDAP'); + } + return $this->groupBackend->getNewLDAPConnection($gid); } /** @@ -128,10 +180,10 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if user id was not found in LDAP */ public function getLDAPBaseUsers($uid) { - if(!$this->backend->userExists($uid)){ + if(!$this->userBackend->userExists($uid)){ throw new \Exception('User id not found in LDAP'); } - return $this->backend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_users']; + return $this->userBackend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_users']; } /** @@ -141,10 +193,10 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if user id was not found in LDAP */ public function getLDAPBaseGroups($uid) { - if(!$this->backend->userExists($uid)){ + if(!$this->userBackend->userExists($uid)){ throw new \Exception('User id not found in LDAP'); } - return $this->backend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_groups']; + return $this->userBackend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_base_groups']; } /** @@ -153,10 +205,23 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @throws \Exception if user id was not found in LDAP */ public function clearCache($uid) { - if(!$this->backend->userExists($uid)){ + if(!$this->userBackend->userExists($uid)){ throw new \Exception('User id not found in LDAP'); } - $this->backend->getLDAPAccess($uid)->getConnection()->clearCache(); + $this->userBackend->getLDAPAccess($uid)->getConnection()->clearCache(); + } + + /** + * Clear the cache if a cache is used, otherwise do nothing. + * Acts on the LDAP connection of a group + * @param string $gid group id + * @throws \Exception if user id was not found in LDAP + */ + public function clearGroupCache($gid) { + if(!$this->groupBackend->groupExists($gid)){ + throw new \Exception('Group id not found in LDAP'); + } + $this->groupBackend->getLDAPAccess($gid)->getConnection()->clearCache(); } /** @@ -165,7 +230,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { * @return bool whether the DN exists */ public function dnExists($dn) { - $result = $this->backend->dn2UserName($dn); + $result = $this->userBackend->dn2UserName($dn); return !$result ? false : true; } @@ -184,4 +249,44 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { public function unflagRecord($uid) { //do nothing } + + /** + * Get the LDAP attribute name for the user's display name + * @param string $uid user id + * @return string the display name field + * @throws \Exception if user id was not found in LDAP + */ + public function getLDAPDisplayNameField($uid) { + if(!$this->userBackend->userExists($uid)){ + throw new \Exception('User id not found in LDAP'); + } + return $this->userBackend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_display_name']; + } + + /** + * Get the LDAP attribute name for the email + * @param string $uid user id + * @return string the email field + * @throws \Exception if user id was not found in LDAP + */ + public function getLDAPEmailField($uid) { + if(!$this->userBackend->userExists($uid)){ + throw new \Exception('User id not found in LDAP'); + } + return $this->userBackend->getLDAPAccess($uid)->getConnection()->getConfiguration()['ldap_email_attr']; + } + + /** + * Get the LDAP type of association between users and groups + * @param string $gid group id + * @return string the configuration, one of: 'memberUid', 'uniqueMember', 'member', 'gidNumber' + * @throws \Exception if group id was not found in LDAP + */ + public function getLDAPGroupMemberAssoc($gid) { + if(!$this->groupBackend->groupExists($gid)){ + throw new \Exception('Group id not found in LDAP'); + } + return $this->groupBackend->getLDAPAccess($gid)->getConnection()->getConfiguration()['ldap_group_member_assoc_attribute']; + } + } diff --git a/apps/user_ldap/lib/Migration/UUIDFixGroup.php b/apps/user_ldap/lib/Migration/UUIDFixGroup.php index 9ea406efad..94e0778b9a 100644 --- a/apps/user_ldap/lib/Migration/UUIDFixGroup.php +++ b/apps/user_ldap/lib/Migration/UUIDFixGroup.php @@ -33,6 +33,7 @@ class UUIDFixGroup extends UUIDFix { public function __construct(GroupMapping $mapper, LDAP $ldap, IConfig $config, Helper $helper) { $this->mapper = $mapper; $this->proxy = new User_Proxy($helper->getServerConfigurationPrefixes(true), $ldap, $config, - \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), + \OC::$server->query('LDAPUserPluginManager')); } } diff --git a/apps/user_ldap/lib/Migration/UUIDFixUser.php b/apps/user_ldap/lib/Migration/UUIDFixUser.php index ee1457dccc..68003fd118 100644 --- a/apps/user_ldap/lib/Migration/UUIDFixUser.php +++ b/apps/user_ldap/lib/Migration/UUIDFixUser.php @@ -32,6 +32,7 @@ use OCP\IConfig; class UUIDFixUser extends UUIDFix { public function __construct(UserMapping $mapper, LDAP $ldap, IConfig $config, Helper $helper) { $this->mapper = $mapper; - $this->proxy = new Group_Proxy($helper->getServerConfigurationPrefixes(true), $ldap, $config); + $groupPluginManager = \OC::$server->query('LDAPGroupPluginManager'); + $this->proxy = new Group_Proxy($helper->getServerConfigurationPrefixes(true), $ldap, $groupPluginManager); } } diff --git a/apps/user_ldap/lib/UserPluginManager.php b/apps/user_ldap/lib/UserPluginManager.php new file mode 100644 index 0000000000..cee972f145 --- /dev/null +++ b/apps/user_ldap/lib/UserPluginManager.php @@ -0,0 +1,210 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP; + +use OC\User\Backend; + +class UserPluginManager { + + public $test = false; + + private $respondToActions = 0; + + private $which = array( + Backend::CREATE_USER => null, + Backend::SET_PASSWORD => null, + Backend::GET_HOME => null, + Backend::GET_DISPLAYNAME => null, + Backend::SET_DISPLAYNAME => null, + Backend::PROVIDE_AVATAR => null, + Backend::COUNT_USERS => null, + 'deleteUser' => null + ); + + /** + * @return int All implemented actions, except for 'deleteUser' + */ + public function getImplementedActions() { + return $this->respondToActions; + } + + /** + * Registers a group plugin that may implement some actions, overriding User_LDAP's user actions. + * + * @param ILDAPUserPlugin $plugin + */ + public function register(ILDAPUserPlugin $plugin) { + $respondToActions = $plugin->respondToActions(); + $this->respondToActions |= $respondToActions; + + foreach($this->which as $action => $v) { + if (is_int($action) && (bool)($respondToActions & $action)) { + $this->which[$action] = $plugin; + \OC::$server->getLogger()->debug("Registered action ".$action." to plugin ".get_class($plugin), ['app' => 'user_ldap']); + } + } + if (method_exists($plugin,'deleteUser')) { + $this->which['deleteUser'] = $plugin; + \OC::$server->getLogger()->debug("Registered action deleteUser to plugin ".get_class($plugin), ['app' => 'user_ldap']); + } + } + + /** + * Signal if there is a registered plugin that implements some given actions + * @param int $actions Actions defined in \OC\User\Backend, like Backend::CREATE_USER + * @return bool + */ + public function implementsActions($actions) { + return ($actions & $this->respondToActions) == $actions; + } + + /** + * Create a new user in LDAP Backend + * + * @param string $username The username of the user to create + * @param string $password The password of the new user + * @return bool + * @throws \Exception + */ + public function createUser($username, $password) { + $plugin = $this->which[Backend::CREATE_USER]; + + if ($plugin) { + return $plugin->createUser($username,$password); + } + throw new \Exception('No plugin implements createUser in this LDAP Backend.'); + } + + /** + * Change the password of a user* + * @param string $uid The username + * @param string $password The new password + * @return bool + * @throws \Exception + */ + public function setPassword($uid, $password) { + $plugin = $this->which[Backend::SET_PASSWORD]; + + if ($plugin) { + return $plugin->setPassword($uid,$password); + } + throw new \Exception('No plugin implements setPassword in this LDAP Backend.'); + } + + /** + * checks whether the user is allowed to change his avatar in Nextcloud + * @param string $uid the Nextcloud user name + * @return boolean either the user can or cannot + * @throws \Exception + */ + public function canChangeAvatar($uid) { + $plugin = $this->which[Backend::PROVIDE_AVATAR]; + + if ($plugin) { + return $plugin->canChangeAvatar($uid); + } + throw new \Exception('No plugin implements canChangeAvatar in this LDAP Backend.'); + } + + /** + * Get the user's home directory + * @param string $uid the username + * @return boolean + * @throws \Exception + */ + public function getHome($uid) { + $plugin = $this->which[Backend::GET_HOME]; + + if ($plugin) { + return $plugin->getHome($uid); + } + throw new \Exception('No plugin implements getHome in this LDAP Backend.'); + } + + /** + * Get display name of the user + * @param string $uid user ID of the user + * @return string display name + * @throws \Exception + */ + public function getDisplayName($uid) { + $plugin = $this->which[Backend::GET_DISPLAYNAME]; + + if ($plugin) { + return $plugin->getDisplayName($uid); + } + throw new \Exception('No plugin implements getDisplayName in this LDAP Backend.'); + } + + /** + * Set display name of the user + * @param string $uid user ID of the user + * @param string $displayName new user's display name + * @return string display name + * @throws \Exception + */ + public function setDisplayName($uid, $displayName) { + $plugin = $this->which[Backend::SET_DISPLAYNAME]; + + if ($plugin) { + return $plugin->setDisplayName($uid, $displayName); + } + throw new \Exception('No plugin implements setDisplayName in this LDAP Backend.'); + } + + /** + * Count the number of users + * @return int|bool + * @throws \Exception + */ + public function countUsers() { + $plugin = $this->which[Backend::COUNT_USERS]; + + if ($plugin) { + return $plugin->countUsers(); + } + throw new \Exception('No plugin implements countUsers in this LDAP Backend.'); + } + + /** + * @return bool + */ + public function canDeleteUser() { + return $this->which['deleteUser'] !== null; + } + + /** + * @param $uid + * @return bool + * @throws \Exception + */ + public function deleteUser($uid) { + $plugin = $this->which['deleteUser']; + if ($plugin) { + return $plugin->deleteUser($uid); + } + throw new \Exception('No plugin implements deleteUser in this LDAP Backend.'); + } +} + diff --git a/apps/user_ldap/lib/User_LDAP.php b/apps/user_ldap/lib/User_LDAP.php index 0a9a1cfe4c..87706dcfe8 100644 --- a/apps/user_ldap/lib/User_LDAP.php +++ b/apps/user_ldap/lib/User_LDAP.php @@ -16,6 +16,8 @@ * @author Thomas Müller * @author Tom Needham * @author Roger Szabo + * @author Vinicius Brand + * @author Daniel Tygel * * @license AGPL-3.0 * @@ -56,16 +58,20 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn /** @var string */ protected $currentUserInDeletionProcess; + /** @var UserPluginManager */ + protected $userPluginManager; + /** * @param Access $access * @param \OCP\IConfig $ocConfig * @param \OCP\Notification\IManager $notificationManager * @param IUserSession $userSession */ - public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession) { + public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession, UserPluginManager $userPluginManager) { parent::__construct($access); $this->ocConfig = $ocConfig; $this->notificationManager = $notificationManager; + $this->userPluginManager = $userPluginManager; $this->registerHooks($userSession); } @@ -88,6 +94,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn * @return boolean either the user can or cannot */ public function canChangeAvatar($uid) { + if ($this->userPluginManager->implementsActions(Backend::PROVIDE_AVATAR)) { + return $this->userPluginManager->canChangeAvatar($uid); + } + $user = $this->access->userManager->get($uid); if(!$user instanceof User) { return false; @@ -207,6 +217,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn * @return bool */ public function setPassword($uid, $password) { + if ($this->userPluginManager->implementsActions(Backend::SET_PASSWORD)) { + return $this->userPluginManager->setPassword($uid, $password); + } + $user = $this->access->userManager->get($uid); if(!$user instanceof User) { @@ -364,6 +378,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn * @return bool */ public function deleteUser($uid) { + if ($this->userPluginManager->canDeleteUser()) { + return $this->userPluginManager->deleteUser($uid); + } + $marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0); if(intval($marked) === 0) { \OC::$server->getLogger()->notice( @@ -393,6 +411,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn return false; } + if ($this->userPluginManager->implementsActions(Backend::GET_HOME)) { + return $this->userPluginManager->getHome($uid); + } + $cacheKey = 'getHome'.$uid; $path = $this->access->connection->getFromCache($cacheKey); if(!is_null($path)) { @@ -425,6 +447,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn * @return string|false display name */ public function getDisplayName($uid) { + if ($this->userPluginManager->implementsActions(Backend::GET_DISPLAYNAME)) { + return $this->userPluginManager->getDisplayName($uid); + } + if(!$this->userExists($uid)) { return false; } @@ -469,6 +495,19 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn return null; } + /** + * set display name of the user + * @param string $uid user ID of the user + * @param string $displayName new display name of the user + * @return string|false display name + */ + public function setDisplayName($uid, $displayName) { + if ($this->userPluginManager->implementsActions(Backend::SET_DISPLAYNAME)) { + return $this->userPluginManager->setDisplayName($uid, $displayName); + } + return false; + } + /** * Get a list of all display names * @@ -506,7 +545,8 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn | Backend::GET_DISPLAYNAME | Backend::PROVIDE_AVATAR | Backend::COUNT_USERS - | ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0)) + | ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0) + | $this->userPluginManager->getImplementedActions()) & $actions); } @@ -523,6 +563,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn * @return int|bool */ public function countUsers() { + if ($this->userPluginManager->implementsActions(Backend::COUNT_USERS)) { + return $this->userPluginManager->countUsers(); + } + $filter = $this->access->getFilterForUserCount(); $cacheKey = 'countUsers-'.$filter; if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) { @@ -561,4 +605,18 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn $connection = clone $this->access->getConnection(); return $connection->getConnectionResource(); } + + /** + * create new user + * @param string $username username of the new user + * @param string $password password of the new user + * @return bool was the user created? + */ + public function createUser($username, $password) { + if ($this->userPluginManager->implementsActions(Backend::CREATE_USER)) { + return $this->userPluginManager->createUser($username, $password); + } + return false; + } + } diff --git a/apps/user_ldap/lib/User_Proxy.php b/apps/user_ldap/lib/User_Proxy.php index a25eb1bc62..c65999e3fd 100644 --- a/apps/user_ldap/lib/User_Proxy.php +++ b/apps/user_ldap/lib/User_Proxy.php @@ -10,6 +10,8 @@ * @author Robin McCorkell * @author Thomas Müller * @author Roger Szabo + * @author Vinicius Brand + * @author Daniel Tygel * * @license AGPL-3.0 * @@ -48,11 +50,13 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, * @param IUserSession $userSession */ public function __construct(array $serverConfigPrefixes, ILDAPWrapper $ldap, IConfig $ocConfig, - INotificationManager $notificationManager, IUserSession $userSession) { + INotificationManager $notificationManager, IUserSession $userSession, + UserPluginManager $userPluginManager) { parent::__construct($ldap); foreach($serverConfigPrefixes as $configPrefix) { $this->backends[$configPrefix] = - new User_LDAP($this->getAccess($configPrefix), $ocConfig, $notificationManager, $userSession); + new User_LDAP($this->getAccess($configPrefix), $ocConfig, $notificationManager, $userSession, $userPluginManager); + if(is_null($this->refBackend)) { $this->refBackend = &$this->backends[$configPrefix]; } @@ -232,13 +236,24 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, return $this->handleRequest($uid, 'getDisplayName', array($uid)); } + /** + * set display name of the user + * + * @param string $uid user ID of the user + * @param string $displayName new display name + * @return string display name + */ + public function setDisplayName($uid, $displayName) { + return $this->handleRequest($uid, 'setDisplayName', array($uid, $displayName)); + } + /** * checks whether the user is allowed to change his avatar in Nextcloud * @param string $uid the Nextcloud user name * @return boolean either the user can or cannot */ public function canChangeAvatar($uid) { - return $this->handleRequest($uid, 'canChangeAvatar', array($uid), true); + return $this->handleRequest($uid, 'canChangeAvatar', array($uid)); } /** @@ -322,4 +337,14 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, public function getNewLDAPConnection($uid) { return $this->handleRequest($uid, 'getNewLDAPConnection', array($uid)); } + + /** + * Creates a new user in LDAP + * @param $username + * @param $password + * @return bool + */ + public function createUser($username, $password) { + return $this->handleRequest($username, 'createUser', array($username,$password)); + } } diff --git a/apps/user_ldap/tests/GroupLDAPPluginTest.php b/apps/user_ldap/tests/GroupLDAPPluginTest.php new file mode 100644 index 0000000000..861806677e --- /dev/null +++ b/apps/user_ldap/tests/GroupLDAPPluginTest.php @@ -0,0 +1,247 @@ + + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP\Tests; + + +use OCP\GroupInterface; +use OCA\User_LDAP\GroupPluginManager; + +class GroupLDAPPluginTest extends \Test\TestCase { + + /** + * @return GroupPluginManager + */ + private function getGroupPluginManager() { + return new GroupPluginManager(); + } + + public function testImplementsActions() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::CREATE_GROUP); + + $plugin2 = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions']) + ->getMock(); + + $plugin2->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::ADD_TO_GROUP); + + $pluginManager->register($plugin); + $pluginManager->register($plugin2); + + $this->assertEquals($pluginManager->getImplementedActions(), GroupInterface::CREATE_GROUP | GroupInterface::ADD_TO_GROUP); + $this->assertTrue($pluginManager->implementsActions(GroupInterface::CREATE_GROUP)); + $this->assertTrue($pluginManager->implementsActions(GroupInterface::ADD_TO_GROUP)); + } + + public function testCreateGroup() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'createGroup']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::CREATE_GROUP); + + $plugin->expects($this->once()) + ->method('createGroup') + ->with( + $this->equalTo('group') + ); + + $pluginManager->register($plugin); + $pluginManager->createGroup('group'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements createGroup in this LDAP Backend. + */ + public function testCreateGroupNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->createGroup('foo'); + } + + public function testDeleteGroup() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'deleteGroup']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::DELETE_GROUP); + + $plugin->expects($this->once()) + ->method('deleteGroup') + ->with( + $this->equalTo('group') + ); + + $pluginManager->register($plugin); + $pluginManager->deleteGroup('group'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements deleteGroup in this LDAP Backend. + */ + public function testDeleteGroupNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->deleteGroup('foo'); + } + + public function testAddToGroup() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'addToGroup']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::ADD_TO_GROUP); + + $plugin->expects($this->once()) + ->method('addToGroup') + ->with( + $this->equalTo('uid'), + $this->equalTo('gid') + ); + + $pluginManager->register($plugin); + $pluginManager->addToGroup('uid', 'gid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements addToGroup in this LDAP Backend. + */ + public function testAddToGroupNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->addToGroup('foo', 'bar'); + } + + public function testRemoveFromGroup() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'removeFromGroup']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::REMOVE_FROM_GROUP); + + $plugin->expects($this->once()) + ->method('removeFromGroup') + ->with( + $this->equalTo('uid'), + $this->equalTo('gid') + ); + + $pluginManager->register($plugin); + $pluginManager->removeFromGroup('uid', 'gid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements removeFromGroup in this LDAP Backend. + */ + public function testRemoveFromGroupNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->removeFromGroup('foo', 'bar'); + } + + public function testCountUsersInGroup() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'countUsersInGroup']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::COUNT_USERS); + + $plugin->expects($this->once()) + ->method('countUsersInGroup') + ->with( + $this->equalTo('gid'), + $this->equalTo('search') + ); + + $pluginManager->register($plugin); + $pluginManager->countUsersInGroup('gid', 'search'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements countUsersInGroup in this LDAP Backend. + */ + public function testCountUsersInGroupNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->countUsersInGroup('foo', 'bar'); + } + + public function testgetGroupDetails() { + $pluginManager = $this->getGroupPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPGroupPluginDummy') + ->setMethods(['respondToActions', 'getGroupDetails']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(GroupInterface::GROUP_DETAILS); + + $plugin->expects($this->once()) + ->method('getGroupDetails') + ->with( + $this->equalTo('gid') + ); + + $pluginManager->register($plugin); + $pluginManager->getGroupDetails('gid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements getGroupDetails in this LDAP Backend. + */ + public function testgetGroupDetailsNotRegistered() { + $pluginManager = $this->getGroupPluginManager(); + $pluginManager->getGroupDetails('foo'); + } +} diff --git a/apps/user_ldap/tests/Group_LDAPTest.php b/apps/user_ldap/tests/Group_LDAPTest.php index 9b5216742f..8ca7556e09 100644 --- a/apps/user_ldap/tests/Group_LDAPTest.php +++ b/apps/user_ldap/tests/Group_LDAPTest.php @@ -29,6 +29,7 @@ namespace OCA\User_LDAP\Tests; +use OCP\GroupInterface; use OCA\User_LDAP\Group_LDAP as GroupLDAP; use OCA\User_LDAP\ILDAPWrapper; @@ -69,6 +70,10 @@ class Group_LDAPTest extends \Test\TestCase { return $access; } + private function getPluginManagerMock() { + return $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')->getMock(); + } + private function enableGroups($access) { $access->connection->expects($this->any()) ->method('__get') @@ -82,6 +87,7 @@ class Group_LDAPTest extends \Test\TestCase { public function testCountEmptySearchString() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); $this->enableGroups($access); @@ -98,7 +104,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('countUsers') ->will($this->returnValue(2)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $users = $groupBackend->countUsersInGroup('group'); $this->assertSame(6, $users); @@ -106,6 +112,7 @@ class Group_LDAPTest extends \Test\TestCase { public function testCountWithSearchString() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); $this->enableGroups($access); @@ -137,14 +144,39 @@ class Group_LDAPTest extends \Test\TestCase { return 'foobar' . \OCP\Util::generateRandomBytes(7); })); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access,$pluginManager); $users = $groupBackend->countUsersInGroup('group', '3'); $this->assertSame(2, $users); } + public function testCountUsersWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','countUsersInGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::COUNT_USERS) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('countUsersInGroup') + ->with('gid', 'search') + ->willReturn(42); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $this->assertEquals($ldap->countUsersInGroup('gid', 'search'),42); + } + public function testGidNumber2NameSuccess() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -158,7 +190,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with('cn=foo,dc=barfoo,dc=bar') ->will($this->returnValue('MyGroup')); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->gidNumber2Name('3117', $userDN); @@ -167,6 +199,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testGidNumberID2NameNoGroup() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -178,7 +212,7 @@ class Group_LDAPTest extends \Test\TestCase { $access->expects($this->never()) ->method('dn2groupname'); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->gidNumber2Name('3117', $userDN); @@ -187,6 +221,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testGidNumberID2NameNoName() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -199,7 +235,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('dn2groupname') ->will($this->returnValue(false)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->gidNumber2Name('3117', $userDN); @@ -208,6 +244,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testGetEntryGidNumberValue() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar'; @@ -218,7 +256,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with($dn, $attr) ->will($this->returnValue(array('3117'))); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $gid = $groupBackend->getGroupGidNumber($dn); @@ -227,6 +265,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testGetEntryGidNumberNoValue() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar'; @@ -237,7 +277,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with($dn, $attr) ->will($this->returnValue(false)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $gid = $groupBackend->getGroupGidNumber($dn); @@ -246,6 +286,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testPrimaryGroupID2NameSuccess() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -264,7 +306,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with('cn=foo,dc=barfoo,dc=bar') ->will($this->returnValue('MyGroup')); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->primaryGroupID2Name('3117', $userDN); @@ -273,6 +315,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testPrimaryGroupID2NameNoSID() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -288,7 +332,7 @@ class Group_LDAPTest extends \Test\TestCase { $access->expects($this->never()) ->method('dn2groupname'); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->primaryGroupID2Name('3117', $userDN); @@ -297,6 +341,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testPrimaryGroupID2NameNoGroup() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -313,7 +359,7 @@ class Group_LDAPTest extends \Test\TestCase { $access->expects($this->never()) ->method('dn2groupname'); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->primaryGroupID2Name('3117', $userDN); @@ -322,6 +368,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testPrimaryGroupID2NameNoName() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar'; @@ -339,7 +387,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('dn2groupname') ->will($this->returnValue(false)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $group = $groupBackend->primaryGroupID2Name('3117', $userDN); @@ -350,6 +398,8 @@ class Group_LDAPTest extends \Test\TestCase { //tests getEntryGroupID via getGroupPrimaryGroupID //which is basically identical to getUserPrimaryGroupIDs $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar'; @@ -360,7 +410,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with($dn, $attr) ->will($this->returnValue(array('3117'))); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $gid = $groupBackend->getGroupPrimaryGroupID($dn); @@ -371,6 +421,8 @@ class Group_LDAPTest extends \Test\TestCase { //tests getEntryGroupID via getGroupPrimaryGroupID //which is basically identical to getUserPrimaryGroupIDs $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar'; @@ -381,7 +433,7 @@ class Group_LDAPTest extends \Test\TestCase { ->with($dn, $attr) ->will($this->returnValue(false)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $gid = $groupBackend->getGroupPrimaryGroupID($dn); @@ -394,6 +446,8 @@ class Group_LDAPTest extends \Test\TestCase { */ public function testInGroupHitsUidGidCache() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $uid = 'someUser'; @@ -408,19 +462,21 @@ class Group_LDAPTest extends \Test\TestCase { $access->expects($this->never()) ->method('username2dn'); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $groupBackend->inGroup($uid, $gid); } public function testGetGroupsWithOffset() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $access->expects($this->once()) ->method('nextcloudGroupNames') ->will($this->returnValue(array('group1', 'group2'))); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $groups = $groupBackend->getGroups('', 2, 2); $this->assertSame(2, count($groups)); @@ -432,6 +488,8 @@ class Group_LDAPTest extends \Test\TestCase { */ public function testUsersInGroupPrimaryMembersOnly() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $access->connection->expects($this->any()) @@ -457,7 +515,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('nextcloudUserNames') ->willReturnOnConsecutiveCalls(['lisa', 'bart', 'kira', 'brad'], ['walle', 'dino', 'xenia']); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $users = $groupBackend->usersInGroup('foobar'); $this->assertSame(7, count($users)); @@ -469,6 +527,8 @@ class Group_LDAPTest extends \Test\TestCase { */ public function testUsersInGroupPrimaryAndUnixMembers() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $access->connection->expects($this->any()) @@ -492,7 +552,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('nextcloudUserNames') ->will($this->returnValue(array('lisa', 'bart', 'kira', 'brad'))); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $users = $groupBackend->usersInGroup('foobar'); $this->assertSame(4, count($users)); @@ -504,6 +564,8 @@ class Group_LDAPTest extends \Test\TestCase { */ public function testCountUsersInGroupPrimaryMembersOnly() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $access->connection->expects($this->any()) @@ -527,7 +589,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('countUsers') ->will($this->returnValue(4)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $users = $groupBackend->countUsersInGroup('foobar'); $this->assertSame(4, $users); @@ -535,6 +597,8 @@ class Group_LDAPTest extends \Test\TestCase { public function testGetUserGroupsMemberOf() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); + $this->enableGroups($access); $dn = 'cn=userX,dc=foobar'; @@ -558,7 +622,7 @@ class Group_LDAPTest extends \Test\TestCase { ->method('groupsMatchFilter') ->will($this->returnArgument(0)); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $groups = $groupBackend->getUserGroups('userX'); $this->assertSame(2, count($groups)); @@ -566,6 +630,7 @@ class Group_LDAPTest extends \Test\TestCase { public function testGetUserGroupsMemberOfDisabled() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); $access->connection->expects($this->any()) ->method('__get') @@ -595,12 +660,13 @@ class Group_LDAPTest extends \Test\TestCase { ->method('nextcloudGroupNames') ->will($this->returnValue([])); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $groupBackend->getUserGroups('userX'); } public function testGetGroupsByMember() { $access = $this->getAccessMock(); + $pluginManager = $this->getPluginManagerMock(); $access->connection->expects($this->any()) ->method('__get') @@ -646,11 +712,243 @@ class Group_LDAPTest extends \Test\TestCase { ->method('fetchListOfGroups') ->will($this->returnValue([$group1, $group2])); - $groupBackend = new GroupLDAP($access); + $groupBackend = new GroupLDAP($access, $pluginManager); $groups = $groupBackend->getUserGroups('userX'); $this->assertEquals(['group1', 'group2'], $groups); $groupsAgain = $groupBackend->getUserGroups('userX'); $this->assertEquals(['group1', 'group2'], $groupsAgain); } + + public function testCreateGroupWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','createGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::CREATE_GROUP) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('createGroup') + ->with('gid') + ->willReturn('result'); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $this->assertEquals($ldap->createGroup('gid'),true); + } + + /** + * @expectedException \Exception + */ + public function testCreateGroupFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions', 'createGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::CREATE_GROUP) + ->willReturn(false); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $ldap->createGroup('gid'); + } + + public function testDeleteGroupWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','deleteGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::DELETE_GROUP) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('deleteGroup') + ->with('gid') + ->willReturn('result'); + + $access = $this->getAccessMock(); + + $mapper = $this->getMockBuilder('\OCA\User_LDAP\Mapping\GroupMapping') + ->setMethods(['unmap']) + ->disableOriginalConstructor() + ->getMock(); + + $access->expects($this->any()) + ->method('getGroupMapper') + ->will($this->returnValue($mapper)); + + $ldap = new GroupLDAP( + $access, + $pluginManager + ); + + $this->assertEquals($ldap->deleteGroup('gid'),'result'); + } + + /** + * @expectedException \Exception + */ + public function testDeleteGroupFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions', 'deleteGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::DELETE_GROUP) + ->willReturn(false); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $ldap->deleteGroup('gid'); + } + + public function testAddToGroupWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','addToGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::ADD_TO_GROUP) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('addToGroup') + ->with('uid', 'gid') + ->willReturn('result'); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $this->assertEquals($ldap->addToGroup('uid', 'gid'),'result'); + } + + /** + * @expectedException \Exception + */ + public function testAddToGroupFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions', 'addToGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::ADD_TO_GROUP) + ->willReturn(false); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $ldap->addToGroup('uid', 'gid'); + } + + public function testRemoveFromGroupWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','removeFromGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::REMOVE_FROM_GROUP) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('removeFromGroup') + ->with('uid', 'gid') + ->willReturn('result'); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $this->assertEquals($ldap->removeFromGroup('uid', 'gid'),'result'); + } + + /** + * @expectedException \Exception + */ + public function testRemoveFromGroupFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions', 'removeFromGroup']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::REMOVE_FROM_GROUP) + ->willReturn(false); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $ldap->removeFromGroup('uid', 'gid'); + } + + public function testGetGroupDetailsWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions','getGroupDetails']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::GROUP_DETAILS) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('getGroupDetails') + ->with('gid') + ->willReturn('result'); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $this->assertEquals($ldap->getGroupDetails('gid'),'result'); + } + + /** + * @expectedException \Exception + */ + public function testGetGroupDetailsFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager') + ->setMethods(['implementsActions', 'getGroupDetails']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(GroupInterface::GROUP_DETAILS) + ->willReturn(false); + + $ldap = new GroupLDAP( + $this->getAccessMock(), + $pluginManager + ); + + $ldap->getGroupDetails('gid'); + } + } diff --git a/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php b/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php index 84e1e6b458..8f9104999d 100644 --- a/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php +++ b/apps/user_ldap/tests/Integration/AbstractIntegrationTest.php @@ -68,6 +68,13 @@ abstract class AbstractIntegrationTest { * the LDAP backend. */ public function init() { + \OC::$server->registerService('LDAPUserPluginManager', function() { + return new \OCA\User_LDAP\UserPluginManager(); + }); + \OC::$server->registerService('LDAPGroupPluginManager', function() { + return new \OCA\User_LDAP\GroupPluginManager(); + }); + $this->initLDAPWrapper(); $this->initConnection(); $this->initUserManager(); diff --git a/apps/user_ldap/tests/Integration/Lib/IntegrationTestAttributeDetection.php b/apps/user_ldap/tests/Integration/Lib/IntegrationTestAttributeDetection.php index bd8e4bdd7a..bc616bfc77 100644 --- a/apps/user_ldap/tests/Integration/Lib/IntegrationTestAttributeDetection.php +++ b/apps/user_ldap/tests/Integration/Lib/IntegrationTestAttributeDetection.php @@ -49,12 +49,12 @@ class IntegrationTestAttributeDetection extends AbstractIntegrationTest { $groupMapper->clear(); $this->access->setGroupMapper($groupMapper); - $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); $userManager = \OC::$server->getUserManager(); $userManager->clearBackends(); $userManager->registerBackend($userBackend); - $groupBackend = new Group_LDAP($this->access); + $groupBackend = new Group_LDAP($this->access, \OC::$server->query('LDAPGroupPluginManager')); $groupManger = \OC::$server->getGroupManager(); $groupManger->clearBackends(); $groupManger->addBackend($groupBackend); diff --git a/apps/user_ldap/tests/Integration/Lib/IntegrationTestFetchUsersByLoginName.php b/apps/user_ldap/tests/Integration/Lib/IntegrationTestFetchUsersByLoginName.php index 95bfb99b65..e96e44a685 100644 --- a/apps/user_ldap/tests/Integration/Lib/IntegrationTestFetchUsersByLoginName.php +++ b/apps/user_ldap/tests/Integration/Lib/IntegrationTestFetchUsersByLoginName.php @@ -47,7 +47,7 @@ class IntegrationTestFetchUsersByLoginName extends AbstractIntegrationTest { $this->mapping = new UserMapping(\OC::$server->getDatabaseConnection()); $this->mapping->clear(); $this->access->setUserMapper($this->mapping); - $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); } /** diff --git a/apps/user_ldap/tests/Integration/Lib/IntegrationTestPaging.php b/apps/user_ldap/tests/Integration/Lib/IntegrationTestPaging.php index 3c8cf22bb5..c5f74863d9 100644 --- a/apps/user_ldap/tests/Integration/Lib/IntegrationTestPaging.php +++ b/apps/user_ldap/tests/Integration/Lib/IntegrationTestPaging.php @@ -47,7 +47,7 @@ class IntegrationTestPaging extends AbstractIntegrationTest { require(__DIR__ . '/../setup-scripts/createExplicitUsers.php'); parent::init(); - $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); } public function initConnection() { diff --git a/apps/user_ldap/tests/Integration/Lib/IntegrationTestUserHome.php b/apps/user_ldap/tests/Integration/Lib/IntegrationTestUserHome.php index 765cee00f9..c50baef49f 100644 --- a/apps/user_ldap/tests/Integration/Lib/IntegrationTestUserHome.php +++ b/apps/user_ldap/tests/Integration/Lib/IntegrationTestUserHome.php @@ -51,7 +51,7 @@ class IntegrationTestUserHome extends AbstractIntegrationTest { $this->mapping = new UserMapping(\OC::$server->getDatabaseConnection()); $this->mapping->clear(); $this->access->setUserMapper($this->mapping); - $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); } /** diff --git a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php index 8c9e215eda..f8a317f0b1 100644 --- a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php +++ b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php @@ -50,7 +50,7 @@ class IntegrationTestUserAvatar extends AbstractIntegrationTest { $this->mapping = new UserMapping(\OC::$server->getDatabaseConnection()); $this->mapping->clear(); $this->access->setUserMapper($this->mapping); - $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); \OC_User::useBackend($userBackend); } diff --git a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserCleanUp.php b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserCleanUp.php index ce81b9a26d..10f0968efb 100644 --- a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserCleanUp.php +++ b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserCleanUp.php @@ -46,7 +46,7 @@ class IntegrationTestUserCleanUp extends AbstractIntegrationTest { $this->mapping->clear(); $this->access->setUserMapper($this->mapping); - $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); \OC_User::useBackend($userBackend); } diff --git a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserDisplayName.php b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserDisplayName.php index 1f5d16567f..187d13dfdb 100644 --- a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserDisplayName.php +++ b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserDisplayName.php @@ -43,7 +43,7 @@ class IntegrationTestUserDisplayName extends AbstractIntegrationTest { $this->mapping = new UserMapping(\OC::$server->getDatabaseConnection()); $this->mapping->clear(); $this->access->setUserMapper($this->mapping); - $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession()); + $userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query('LDAPUserPluginManager')); \OC_User::useBackend($userBackend); } diff --git a/apps/user_ldap/tests/LDAPGroupPluginDummy.php b/apps/user_ldap/tests/LDAPGroupPluginDummy.php new file mode 100644 index 0000000000..c2ccf3338a --- /dev/null +++ b/apps/user_ldap/tests/LDAPGroupPluginDummy.php @@ -0,0 +1,59 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP\Tests; + + +use OCA\User_LDAP\ILDAPGroupPlugin; + +class LDAPGroupPluginDummy implements ILDAPGroupPlugin { + + + public function respondToActions() { + return null; + } + + public function createGroup($gid) { + return null; + } + + public function deleteGroup($gid) { + return null; + } + + public function addToGroup($uid, $gid) { + return null; + } + + public function removeFromGroup($uid, $gid) { + return null; + } + + public function countUsersInGroup($gid, $search = '') { + return null; + } + + public function getGroupDetails($gid) { + return null; + } +} diff --git a/apps/user_ldap/tests/LDAPProviderTest.php b/apps/user_ldap/tests/LDAPProviderTest.php index 585e0df662..42a1b0a3c2 100644 --- a/apps/user_ldap/tests/LDAPProviderTest.php +++ b/apps/user_ldap/tests/LDAPProviderTest.php @@ -3,6 +3,9 @@ * * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de) * + * @author Roger Szabo + * @author Vinicius Brand + * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -22,6 +25,8 @@ namespace OCA\User_LDAP\Tests; +use OCA\User_LDAP\IGroupLDAP; +use OCP\IConfig; use OCP\IServerContainer; use OCA\User_LDAP\IUserLDAP; @@ -38,21 +43,57 @@ class LDAPProviderTest extends \Test\TestCase { parent::setUp(); } - private function getServerMock(IUserLDAP $backend) { + private function getServerMock(IUserLDAP $userBackend, IGroupLDAP $groupBackend) { $server = $this->getMockBuilder('OC\Server') - ->setMethods(['getUserManager', 'getBackends']) + ->setMethods(['getUserManager', 'getBackends', 'getGroupManager']) ->setConstructorArgs(['', new \OC\Config(\OC::$configDir)]) ->getMock(); $server->expects($this->at(1)) ->method('getBackends') - ->willReturn([$backend]); + ->willReturn([$userBackend]); + $server->expects($this->any()) + ->method('getUserManager') + ->willReturn($this->getUserManagerMock($userBackend)); + $server->expects($this->any()) + ->method('getGroupManager') + ->willReturn($this->getGroupManagerMock($groupBackend)); $server->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); return $server; } + + private function getUserManagerMock(IUserLDAP $userBackend) { + $userManager = $this->getMockBuilder('OC\User\Manager') + ->setMethods(['getBackends']) + ->setConstructorArgs([$this->createMock(IConfig::class)]) + ->getMock(); + $userManager->expects($this->any()) + ->method('getBackends') + ->willReturn([$userBackend]); + return $userManager; + } + private function getGroupManagerMock(IGroupLDAP $groupBackend) { + $groupManager = $this->getMockBuilder('OC\Group\Manager') + ->setMethods(['getBackends']) + ->disableOriginalConstructor() + ->getMock(); + $groupManager->expects($this->any()) + ->method('getBackends') + ->willReturn([$groupBackend]); + return $groupManager; + } + + private function getDefaultGroupBackendMock() { + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + return $groupBackend; + } + private function getLDAPProvider(IServerContainer $serverContainer) { $factory = new \OCA\User_LDAP\LDAPProviderFactory($serverContainer); return $factory->getLDAPProvider(); @@ -63,50 +104,100 @@ class LDAPProviderTest extends \Test\TestCase { * @expectedExceptionMessage User id not found in LDAP */ public function testGetUserDNUserIDNotFound() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any())->method('userExists')->willReturn(false); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->getUserDN('nonexisting_user'); } public function testGetUserDN() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists', 'getLDAPAccess', 'username2dn']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->at(0)) + $userBackend->expects($this->at(0)) ->method('userExists') ->willReturn(true); - $backend->expects($this->at(2)) + $userBackend->expects($this->at(2)) ->method('username2dn') ->willReturn('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org'); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $this->assertEquals('cn=existing_user,ou=Are Sufficient To,ou=Test,dc=example,dc=org', $ldapProvider->getUserDN('existing_user')); } + /** + * @expectedException \Exception + * @expectedExceptionMessage Group id not found in LDAP + */ + public function testGetGroupDNGroupIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->any())->method('groupExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->getGroupDN('nonexisting_group'); + } + + public function testGetGroupDN() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->setMethods(['userExists', 'getLDAPAccess', 'username2dn']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists', 'getLDAPAccess', 'groupname2dn']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->at(0)) + ->method('groupExists') + ->willReturn(true); + $groupBackend->expects($this->at(2)) + ->method('groupname2dn') + ->willReturn('cn=existing_group,ou=Are Sufficient To,ou=Test,dc=example,dc=org'); + $groupBackend->expects($this->any()) + ->method($this->anything()) + ->willReturnSelf(); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $this->assertEquals('cn=existing_group,ou=Are Sufficient To,ou=Test,dc=example,dc=org', + $ldapProvider->getGroupDN('existing_group')); + } + public function testGetUserName() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['dn2UserName']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method('dn2UserName') ->willReturn('existing_user'); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $this->assertEquals('existing_user', @@ -114,12 +205,12 @@ class LDAPProviderTest extends \Test\TestCase { } public function testDNasBaseParameter() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods([]) ->disableOriginalConstructor() ->getMock(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $helper = new \OCA\User_LDAP\Helper(\OC::$server->getConfig()); @@ -130,12 +221,12 @@ class LDAPProviderTest extends \Test\TestCase { } public function testSanitizeDN() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods([]) ->disableOriginalConstructor() ->getMock(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $helper = new \OCA\User_LDAP\Helper(\OC::$server->getConfig()); @@ -150,69 +241,115 @@ class LDAPProviderTest extends \Test\TestCase { * @expectedExceptionMessage User id not found in LDAP */ public function testGetLDAPConnectionUserIDNotFound() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any())->method('userExists')->willReturn(false); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->getLDAPConnection('nonexisting_user'); } public function testGetLDAPConnection() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists', 'getNewLDAPConnection']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method('userExists') ->willReturn(true); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method('getNewLDAPConnection') ->willReturn(true); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $this->assertTrue($ldapProvider->getLDAPConnection('existing_user')); } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Group id not found in LDAP + */ + public function testGetGroupLDAPConnectionGroupIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->any())->method('groupExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->getGroupLDAPConnection('nonexisting_group'); + } + + public function testGetGroupLDAPConnection() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists','getNewLDAPConnection']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->any()) + ->method('groupExists') + ->willReturn(true); + + $groupBackend->expects($this->any()) + ->method('getNewLDAPConnection') + ->willReturn(true); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $this->assertTrue($ldapProvider->getGroupLDAPConnection('existing_group')); + } /** * @expectedException \Exception * @expectedExceptionMessage User id not found in LDAP */ public function testGetLDAPBaseUsersUserIDNotFound() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any())->method('userExists')->willReturn(false); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->getLDAPBaseUsers('nonexisting_user'); } public function testGetLDAPBaseUsers() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->at(0)) + $userBackend->expects($this->at(0)) ->method('userExists') ->willReturn(true); - $backend->expects($this->at(3)) + $userBackend->expects($this->at(3)) ->method('getConfiguration') ->willReturn(array('ldap_base_users'=>'ou=users,dc=example,dc=org')); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $this->assertEquals('ou=users,dc=example,dc=org', $ldapProvider->getLDAPBaseUsers('existing_user')); @@ -223,34 +360,34 @@ class LDAPProviderTest extends \Test\TestCase { * @expectedExceptionMessage User id not found in LDAP */ public function testGetLDAPBaseGroupsUserIDNotFound() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any())->method('userExists')->willReturn(false); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->getLDAPBaseGroups('nonexisting_user'); } public function testGetLDAPBaseGroups() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->at(0)) + $userBackend->expects($this->at(0)) ->method('userExists') ->willReturn(true); - $backend->expects($this->at(3)) + $userBackend->expects($this->at(3)) ->method('getConfiguration') ->willReturn(array('ldap_base_groups'=>'ou=groups,dc=example,dc=org')); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $this->assertEquals('ou=groups,dc=example,dc=org', $ldapProvider->getLDAPBaseGroups('existing_user')); @@ -261,62 +398,107 @@ class LDAPProviderTest extends \Test\TestCase { * @expectedExceptionMessage User id not found in LDAP */ public function testClearCacheUserIDNotFound() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any())->method('userExists')->willReturn(false); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->clearCache('nonexisting_user'); } public function testClearCache() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'clearCache']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->at(0)) + $userBackend->expects($this->at(0)) ->method('userExists') ->willReturn(true); - $backend->expects($this->at(3)) + $userBackend->expects($this->at(3)) ->method('clearCache') ->willReturn(true); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method($this->anything()) ->willReturnSelf(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->clearCache('existing_user'); $this->assertTrue(TRUE); } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Group id not found in LDAP + */ + public function testClearGroupCacheGroupIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists']) + ->disableOriginalConstructor() + ->getMock(); + $groupBackend->expects($this->any())->method('groupExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->clearGroupCache('nonexisting_group'); + } + + public function testClearGroupCache() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists', 'getLDAPAccess', 'getConnection', 'clearCache']) + ->disableOriginalConstructor() + ->getMock(); + $groupBackend->expects($this->at(0)) + ->method('groupExists') + ->willReturn(true); + $groupBackend->expects($this->at(3)) + ->method('clearCache') + ->willReturn(true); + $groupBackend->expects($this->any()) + ->method($this->anything()) + ->willReturnSelf(); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->clearGroupCache('existing_group'); + $this->assertTrue(TRUE); + } public function testDnExists() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods(['dn2UserName']) ->disableOriginalConstructor() ->getMock(); - $backend->expects($this->any()) + $userBackend->expects($this->any()) ->method('dn2UserName') ->willReturn('existing_user'); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $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') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods([]) ->disableOriginalConstructor() ->getMock(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->flagRecord('existing_user'); @@ -324,15 +506,140 @@ class LDAPProviderTest extends \Test\TestCase { } public function testUnflagRecord() { - $backend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') ->setMethods([]) ->disableOriginalConstructor() ->getMock(); - $server = $this->getServerMock($backend); + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); $ldapProvider = $this->getLDAPProvider($server); $ldapProvider->unflagRecord('existing_user'); $this->assertTrue(TRUE); } + + /** + * @expectedException \Exception + * @expectedExceptionMessage User id not found in LDAP + */ + public function testGetLDAPDisplayNameFieldUserIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->setMethods(['userExists']) + ->disableOriginalConstructor() + ->getMock(); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->getLDAPDisplayNameField('nonexisting_user'); + } + + public function testGetLDAPDisplayNameField() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration']) + ->disableOriginalConstructor() + ->getMock(); + $userBackend->expects($this->at(0)) + ->method('userExists') + ->willReturn(true); + $userBackend->expects($this->at(3)) + ->method('getConfiguration') + ->willReturn(array('ldap_display_name'=>'displayName')); + $userBackend->expects($this->any()) + ->method($this->anything()) + ->willReturnSelf(); + + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); + + $ldapProvider = $this->getLDAPProvider($server); + $this->assertEquals('displayName', $ldapProvider->getLDAPDisplayNameField('existing_user')); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage User id not found in LDAP + */ + public function testGetLDAPEmailFieldUserIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->setMethods(['userExists']) + ->disableOriginalConstructor() + ->getMock(); + $userBackend->expects($this->any())->method('userExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->getLDAPEmailField('nonexisting_user'); + } + + public function testGetLDAPEmailField() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->setMethods(['userExists', 'getLDAPAccess', 'getConnection', 'getConfiguration']) + ->disableOriginalConstructor() + ->getMock(); + $userBackend->expects($this->at(0)) + ->method('userExists') + ->willReturn(true); + $userBackend->expects($this->at(3)) + ->method('getConfiguration') + ->willReturn(array('ldap_email_attr'=>'mail')); + $userBackend->expects($this->any()) + ->method($this->anything()) + ->willReturnSelf(); + + $server = $this->getServerMock($userBackend, $this->getDefaultGroupBackendMock()); + + $ldapProvider = $this->getLDAPProvider($server); + $this->assertEquals('mail', $ldapProvider->getLDAPEmailField('existing_user')); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Group id not found in LDAP + */ + public function testGetLDAPGroupMemberAssocUserIDNotFound() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->any())->method('groupExists')->willReturn(false); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $ldapProvider->getLDAPGroupMemberAssoc('nonexisting_group'); + } + + public function testgetLDAPGroupMemberAssoc() { + $userBackend = $this->getMockBuilder('OCA\User_LDAP\User_LDAP') + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend = $this->getMockBuilder('OCA\User_LDAP\Group_LDAP') + ->setMethods(['groupExists', 'getLDAPAccess', 'getConnection', 'getConfiguration']) + ->disableOriginalConstructor() + ->getMock(); + + $groupBackend->expects($this->at(0)) + ->method('groupExists') + ->willReturn(true); + $groupBackend->expects($this->any()) + ->method('getConfiguration') + ->willReturn(array('ldap_group_member_assoc_attribute'=>'assoc_type')); + $groupBackend->expects($this->any()) + ->method($this->anything()) + ->willReturnSelf(); + + $server = $this->getServerMock($userBackend, $groupBackend); + + $ldapProvider = $this->getLDAPProvider($server); + $this->assertEquals('assoc_type', $ldapProvider->getLDAPGroupMemberAssoc('existing_group')); + } + } diff --git a/apps/user_ldap/tests/LDAPUserPluginDummy.php b/apps/user_ldap/tests/LDAPUserPluginDummy.php new file mode 100644 index 0000000000..8115141b5e --- /dev/null +++ b/apps/user_ldap/tests/LDAPUserPluginDummy.php @@ -0,0 +1,63 @@ + + * @author Daniel Tygel + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP\Tests; + + +use OCA\User_LDAP\ILDAPUserPlugin; + +class LDAPUserPluginDummy implements ILDAPUserPlugin { + + public function respondToActions() { + return null; + } + + public function createUser($username, $password) { + return null; + } + + public function setPassword($uid, $password) { + return null; + } + + public function getHome($uid) { + return null; + } + + public function getDisplayName($uid) { + return null; + } + + public function setDisplayName($uid, $displayName) { + return null; + } + + public function canChangeAvatar($uid) { + return null; + } + + public function countUsers() { + return null; + } + +} diff --git a/apps/user_ldap/tests/UserLDAPPluginTest.php b/apps/user_ldap/tests/UserLDAPPluginTest.php new file mode 100644 index 0000000000..2fe9d6f735 --- /dev/null +++ b/apps/user_ldap/tests/UserLDAPPluginTest.php @@ -0,0 +1,310 @@ + + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\User_LDAP\Tests; + + +use OC\User\Backend; +use OCA\User_LDAP\UserPluginManager; + +class UserLDAPPluginTest extends \Test\TestCase { + + /** + * @return UserPluginManager + */ + private function getUserPluginManager() { + return new UserPluginManager(); + } + + public function testImplementsActions() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::CREATE_USER); + + $plugin2 = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions']) + ->getMock(); + + $plugin2->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::PROVIDE_AVATAR); + + $pluginManager->register($plugin); + $pluginManager->register($plugin2); + + $this->assertEquals($pluginManager->getImplementedActions(), Backend::CREATE_USER | Backend::PROVIDE_AVATAR); + $this->assertTrue($pluginManager->implementsActions(Backend::CREATE_USER)); + $this->assertTrue($pluginManager->implementsActions(Backend::PROVIDE_AVATAR)); + } + + public function testCreateUser() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'createUser']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::CREATE_USER); + + $plugin->expects($this->once()) + ->method('createUser') + ->with( + $this->equalTo('user'), + $this->equalTo('password') + ); + + $pluginManager->register($plugin); + $pluginManager->createUser('user', 'password'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements createUser in this LDAP Backend. + */ + public function testCreateUserNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->createUser('foo','bar'); + } + + public function testSetPassword() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'setPassword']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::SET_PASSWORD); + + $plugin->expects($this->once()) + ->method('setPassword') + ->with( + $this->equalTo('user'), + $this->equalTo('password') + ); + + $pluginManager->register($plugin); + $pluginManager->setPassword('user', 'password'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements setPassword in this LDAP Backend. + */ + public function testSetPasswordNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->setPassword('foo','bar'); + } + + public function testGetHome() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'getHome']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::GET_HOME); + + $plugin->expects($this->once()) + ->method('getHome') + ->with( + $this->equalTo('uid') + ); + + $pluginManager->register($plugin); + $pluginManager->getHome('uid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements getHome in this LDAP Backend. + */ + public function testGetHomeNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->getHome('foo'); + } + + public function testGetDisplayName() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'getDisplayName']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::GET_DISPLAYNAME); + + $plugin->expects($this->once()) + ->method('getDisplayName') + ->with( + $this->equalTo('uid') + ); + + $pluginManager->register($plugin); + $pluginManager->getDisplayName('uid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements getDisplayName in this LDAP Backend. + */ + public function testGetDisplayNameNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->getDisplayName('foo'); + } + + public function testSetDisplayName() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'setDisplayName']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::SET_DISPLAYNAME); + + $plugin->expects($this->once()) + ->method('setDisplayName') + ->with( + $this->equalTo('user'), + $this->equalTo('password') + ); + + $pluginManager->register($plugin); + $pluginManager->setDisplayName('user', 'password'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements setDisplayName in this LDAP Backend. + */ + public function testSetDisplayNameNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->setDisplayName('foo', 'bar'); + } + + public function testCanChangeAvatar() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'canChangeAvatar']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::PROVIDE_AVATAR); + + $plugin->expects($this->once()) + ->method('canChangeAvatar') + ->with( + $this->equalTo('uid') + ); + + $pluginManager->register($plugin); + $pluginManager->canChangeAvatar('uid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements canChangeAvatar in this LDAP Backend. + */ + public function testCanChangeAvatarNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->canChangeAvatar('foo'); + } + + public function testCountUsers() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'countUsers']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(Backend::COUNT_USERS); + + $plugin->expects($this->once()) + ->method('countUsers'); + + $pluginManager->register($plugin); + $pluginManager->countUsers(); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements countUsers in this LDAP Backend. + */ + public function testCountUsersNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->countUsers(); + } + + public function testDeleteUser() { + $pluginManager = $this->getUserPluginManager(); + + $plugin = $this->getMockBuilder('OCA\User_LDAP\Tests\LDAPUserPluginDummy') + ->setMethods(['respondToActions', 'canDeleteUser','deleteUser']) + ->getMock(); + + $plugin->expects($this->any()) + ->method('respondToActions') + ->willReturn(0); + + $plugin->expects($this->any()) + ->method('canDeleteUser') + ->willReturn(true); + + $plugin->expects($this->once()) + ->method('deleteUser') + ->with( + $this->equalTo('uid') + ); + + $this->assertFalse($pluginManager->canDeleteUser()); + $pluginManager->register($plugin); + $this->assertTrue($pluginManager->canDeleteUser()); + $pluginManager->deleteUser('uid'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage No plugin implements deleteUser in this LDAP Backend. + */ + public function testDeleteUserNotRegistered() { + $pluginManager = $this->getUserPluginManager(); + $pluginManager->deleteUser('foo'); + } +} diff --git a/apps/user_ldap/tests/User_LDAPTest.php b/apps/user_ldap/tests/User_LDAPTest.php index 44bc55b414..b6582c816e 100644 --- a/apps/user_ldap/tests/User_LDAPTest.php +++ b/apps/user_ldap/tests/User_LDAPTest.php @@ -10,6 +10,7 @@ * @author Robin McCorkell * @author Thomas Müller * @author Roger Szabo + * @author Vinicius Brand * * @license AGPL-3.0 * @@ -29,6 +30,7 @@ namespace OCA\User_LDAP\Tests; +use OC\User\Backend; use OC\User\Session; use OCA\User_LDAP\Access; use OCA\User_LDAP\Connection; @@ -119,6 +121,10 @@ class User_LDAPTest extends TestCase { return $access; } + private function getDefaultPluginManagerMock() { + return $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager')->getMock(); + } + private function prepareMockForUserExists(&$access) { $access->expects($this->any()) ->method('username2dn') @@ -207,7 +213,8 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = $backend->checkPassword('roland', 'dt19'); @@ -218,7 +225,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = $backend->checkPassword('roland', 'wrong'); @@ -229,7 +236,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = $backend->checkPassword('mallory', 'evil'); @@ -244,7 +251,7 @@ class User_LDAPTest extends TestCase { ->method('username2dn') ->will($this->returnValue(false)); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = $backend->checkPassword('roland', 'dt19'); @@ -254,7 +261,7 @@ class User_LDAPTest extends TestCase { public function testCheckPasswordPublicAPI() { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::checkPassword('roland', 'dt19'); @@ -264,7 +271,7 @@ class User_LDAPTest extends TestCase { public function testCheckPasswordPublicAPIWrongPassword() { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::checkPassword('roland', 'wrong'); @@ -274,7 +281,7 @@ class User_LDAPTest extends TestCase { public function testCheckPasswordPublicAPIWrongUser() { $access = $this->getAccessMock(); $this->prepareAccessForCheckPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::checkPassword('mallory', 'evil'); @@ -283,7 +290,7 @@ class User_LDAPTest extends TestCase { public function testDeleteUserCancel() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->deleteUser('notme'); $this->assertFalse($result); } @@ -313,7 +320,7 @@ class User_LDAPTest extends TestCase { ->method('getOCName') ->willReturn($uid); - $backend = new UserLDAP($access, $this->configMock, $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->configMock, $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $user = $this->createMock(IUser::class); $user->expects($this->once()) @@ -326,6 +333,36 @@ class User_LDAPTest extends TestCase { $this->assertSame($backend->getHome($uid), $home); } + public function testDeleteUserWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['canDeleteUser','deleteUser']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('canDeleteUser') + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('deleteUser') + ->with('uid') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->deleteUser('uid'),'result'); + } + /** * Prepares the Access mock for getUsers tests * @param Access $access mock @@ -381,7 +418,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersNoParam() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->getUsers(); $this->assertEquals(3, count($result)); @@ -390,7 +427,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersLimitOffset() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->getUsers('', 1, 2); $this->assertEquals(1, count($result)); @@ -399,7 +436,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersLimitOffset2() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->getUsers('', 2, 1); $this->assertEquals(2, count($result)); @@ -408,7 +445,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersSearchWithResult() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->getUsers('yo'); $this->assertEquals(2, count($result)); @@ -417,7 +454,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersSearchEmptyResult() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->getUsers('nix'); $this->assertEquals(0, count($result)); @@ -426,7 +463,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersViaAPINoParam() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::getUsers(); @@ -436,7 +473,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersViaAPILimitOffset() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::getUsers('', 1, 2); @@ -446,7 +483,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersViaAPILimitOffset2() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::getUsers('', 2, 1); @@ -456,7 +493,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersViaAPISearchWithResult() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::getUsers('yo'); @@ -466,7 +503,7 @@ class User_LDAPTest extends TestCase { public function testGetUsersViaAPISearchEmptyResult() { $access = $this->getAccessMock(); $this->prepareAccessForGetUsers($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $result = \OCP\User::getUsers('nix'); @@ -475,7 +512,7 @@ class User_LDAPTest extends TestCase { public function testUserExists() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->expects($this->any()) @@ -497,7 +534,7 @@ class User_LDAPTest extends TestCase { */ public function testUserExistsForDeleted() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->expects($this->any()) @@ -515,7 +552,7 @@ class User_LDAPTest extends TestCase { public function testUserExistsForNeverExisting() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->expects($this->any()) @@ -534,7 +571,7 @@ class User_LDAPTest extends TestCase { public function testUserExistsPublicAPI() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); \OC_User::useBackend($backend); @@ -557,7 +594,7 @@ class User_LDAPTest extends TestCase { */ public function testUserExistsPublicAPIForDeleted() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); \OC_User::useBackend($backend); @@ -576,7 +613,7 @@ class User_LDAPTest extends TestCase { public function testUserExistsPublicAPIForNeverExisting() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); \OC_User::useBackend($backend); @@ -596,7 +633,7 @@ class User_LDAPTest extends TestCase { public function testDeleteUserExisting() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); //we do not support deleting existing users at all $result = $backend->deleteUser('gunslinger'); @@ -607,7 +644,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $config = $this->createMock(IConfig::class); $noti = $this->createMock(INotificationManager::class); - $backend = new UserLDAP($access, $config, $noti, $this->createMock(Session::class)); + $backend = new UserLDAP($access, $config, $noti, $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->connection->expects($this->any()) @@ -643,7 +680,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $config = $this->createMock(IConfig::class); $noti = $this->createMock(INotificationManager::class); - $backend = new UserLDAP($access, $config, $noti, $this->createMock(Session::class)); + $backend = new UserLDAP($access, $config, $noti, $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $dataDir = \OC::$server->getConfig()->getSystemValue( @@ -686,7 +723,7 @@ class User_LDAPTest extends TestCase { */ public function testGetHomeNoPath() { $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->connection->expects($this->any()) @@ -719,7 +756,7 @@ class User_LDAPTest extends TestCase { $uid = 'newyorker'; $access = $this->getAccessMock(); - $backend = new UserLDAP($access, $this->configMock, $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->configMock, $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->connection->expects($this->any()) @@ -751,6 +788,43 @@ class User_LDAPTest extends TestCase { $backend->getHome($uid); } + public function testGetHomeWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','getHome']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::GET_HOME) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('getHome') + ->with('uid') + ->willReturn('result'); + + $access = $this->getAccessMock(); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $access->connection->expects($this->any()) + ->method('getFromCache') + ->will($this->returnCallback(function($uid) { + return true; + })); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->getHome('uid'),'result'); + } + private function prepareAccessForGetDisplayName(&$access) { $access->connection->expects($this->any()) ->method('__get') @@ -792,7 +866,7 @@ class User_LDAPTest extends TestCase { public function testGetDisplayName() { $access = $this->getAccessMock(); $this->prepareAccessForGetDisplayName($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->connection->expects($this->any()) @@ -833,7 +907,7 @@ class User_LDAPTest extends TestCase { } })); $this->prepareAccessForGetDisplayName($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $this->prepareMockForUserExists($access); $access->connection->expects($this->any()) @@ -853,6 +927,37 @@ class User_LDAPTest extends TestCase { $this->assertEquals('newyorker', $result); } + public function testGetDisplayNameWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','getDisplayName']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::GET_DISPLAYNAME) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('getDisplayName') + ->with('uid') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->getDisplayName('uid'),'result'); + } + //no test for getDisplayNames, because it just invokes getUsers and //getDisplayName @@ -863,7 +968,7 @@ class User_LDAPTest extends TestCase { ->method('countUsers') ->will($this->returnValue(5)); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->countUsers(); $this->assertEquals(5, $result); @@ -876,12 +981,42 @@ class User_LDAPTest extends TestCase { ->method('countUsers') ->will($this->returnValue(false)); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $result = $backend->countUsers(); $this->assertFalse($result); } + public function testCountUsersWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','countUsers']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::COUNT_USERS) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('countUsers') + ->willReturn(42); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->countUsers(),42); + } + public function testLoginName2UserNameSuccess() { $loginName = 'Alice'; $username = 'alice'; @@ -909,7 +1044,7 @@ class User_LDAPTest extends TestCase { ->method('writeToCache') ->with($this->equalTo('loginName2UserName-'.$loginName), $this->equalTo($username)); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $name = $backend->loginName2UserName($loginName); $this->assertSame($username, $name); @@ -938,7 +1073,7 @@ class User_LDAPTest extends TestCase { ->method('writeToCache') ->with($this->equalTo('loginName2UserName-'.$loginName), false); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $name = $backend->loginName2UserName($loginName); $this->assertSame(false, $name); @@ -985,7 +1120,7 @@ class User_LDAPTest extends TestCase { ->method('getUserValue') ->willReturn(1); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); $name = $backend->loginName2UserName($loginName); $this->assertSame(false, $name); @@ -1010,7 +1145,7 @@ class User_LDAPTest extends TestCase { } return null; })); - + $access->connection->expects($this->any()) ->method('getFromCache') ->will($this->returnCallback(function($uid) { @@ -1066,7 +1201,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForSetPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $this->assertTrue(\OC_User::setPassword('roland', 'dt')); @@ -1076,7 +1211,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForSetPassword($access); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $this->assertTrue(\OC_User::setPassword('roland', 'dt12234$')); @@ -1086,7 +1221,7 @@ class User_LDAPTest extends TestCase { $access = $this->getAccessMock(); $this->prepareAccessForSetPassword($access, false); - $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class)); + $backend = new UserLDAP($access, $this->createMock(IConfig::class), $this->createMock(INotificationManager::class), $this->createMock(Session::class), $this->getDefaultPluginManagerMock()); \OC_User::useBackend($backend); $this->assertFalse(\OC_User::setPassword('roland', 'dt12234$')); @@ -1111,7 +1246,8 @@ class User_LDAPTest extends TestCase { $access, $config, $noti, - $userSession + $userSession, + $this->getDefaultPluginManagerMock() ); $ldap->setPassword('NotExistingUser', 'Password'); } @@ -1136,8 +1272,185 @@ class User_LDAPTest extends TestCase { $access, $config, $noti, - $userSession + $userSession, + $this->getDefaultPluginManagerMock() ); $this->assertFalse($ldap->setPassword('NotExistingUser', 'Password')); } + + public function testSetPasswordWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','setPassword']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::SET_PASSWORD) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('setPassword') + ->with('uid','password') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->setPassword('uid', 'password'),'result'); + } + + public function testCanChangeAvatarWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','canChangeAvatar']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::PROVIDE_AVATAR) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('canChangeAvatar') + ->with('uid') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->canChangeAvatar('uid'),'result'); + } + + public function testSetDisplayNameWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','setDisplayName']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::SET_DISPLAYNAME) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('setDisplayName') + ->with('uid','displayName') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->setDisplayName('uid', 'displayName'),'result'); + } + + public function testSetDisplayNameFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','setDisplayName']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::SET_DISPLAYNAME) + ->willReturn(false); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertFalse($ldap->setDisplayName('uid', 'displayName')); + } + + public function testCreateUserWithPlugin() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions','createUser']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::CREATE_USER) + ->willReturn(true); + + $pluginManager->expects($this->once()) + ->method('createUser') + ->with('uid','password') + ->willReturn('result'); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertEquals($ldap->createUser('uid', 'password'),'result'); + } + + public function testCreateUserFailing() { + $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\UserPluginManager') + ->setMethods(['implementsActions', 'createUser']) + ->getMock(); + + $pluginManager->expects($this->once()) + ->method('implementsActions') + ->with(Backend::CREATE_USER) + ->willReturn(false); + + $access = $this->createMock(Access::class); + $config = $this->createMock(IConfig::class); + $noti = $this->createMock(INotificationManager::class); + $session = $this->createMock(Session::class); + + $ldap = new User_LDAP( + $access, + $config, + $noti, + $session, + $pluginManager + ); + + $this->assertFalse($ldap->createUser('uid', 'password')); + } } diff --git a/apps/user_ldap/tests/User_ProxyTest.php b/apps/user_ldap/tests/User_ProxyTest.php index 68b1e4428c..f6aaa01cb8 100644 --- a/apps/user_ldap/tests/User_ProxyTest.php +++ b/apps/user_ldap/tests/User_ProxyTest.php @@ -2,6 +2,9 @@ /** * @copyright Copyright (c) 2016 Lukas Reschke * + * @author Lukas Reschke + * @author Vinicius Brand + * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,8 +24,10 @@ namespace OCA\User_LDAP\Tests; +use OCA\User_LDAP\ILDAPUserPlugin; use OCA\User_LDAP\ILDAPWrapper; use OCA\User_LDAP\User_Proxy; +use OCA\User_LDAP\UserPluginManager; use OCP\IConfig; use OCP\IUserSession; use OCP\Notification\IManager as INotificationManager; @@ -39,6 +44,8 @@ class User_ProxyTest extends TestCase { private $userSession; /** @var User_Proxy|\PHPUnit_Framework_MockObject_MockObject */ private $proxy; + /** @var UserPluginManager|\PHPUnit_Framework_MockObject_MockObject */ + private $userPluginManager; public function setUp() { parent::setUp(); @@ -47,6 +54,7 @@ class User_ProxyTest extends TestCase { $this->config = $this->createMock(IConfig::class); $this->notificationManager = $this->createMock(INotificationManager::class); $this->userSession = $this->createMock(IUserSession::class); + $this->userPluginManager = $this->createMock(UserPluginManager::class); $this->proxy = $this->getMockBuilder(User_Proxy::class) ->setConstructorArgs([ [], @@ -54,6 +62,7 @@ class User_ProxyTest extends TestCase { $this->config, $this->notificationManager, $this->userSession, + $this->userPluginManager ]) ->setMethods(['handleRequest']) ->getMock(); @@ -68,4 +77,23 @@ class User_ProxyTest extends TestCase { $this->assertTrue($this->proxy->setPassword('MyUid', 'MyPassword')); } + + public function testSetDisplayName() { + $this->proxy + ->expects($this->once()) + ->method('handleRequest') + ->with('MyUid', 'setDisplayName', ['MyUid', 'MyPassword']) + ->willReturn(true); + + $this->assertTrue($this->proxy->setDisplayName('MyUid', 'MyPassword')); } + + public function testCreateUser() { + $this->proxy + ->expects($this->once()) + ->method('handleRequest') + ->with('MyUid', 'createUser', ['MyUid', 'MyPassword']) + ->willReturn(true); + + $this->assertTrue($this->proxy->createUser('MyUid', 'MyPassword')); + } } diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php index 15d83380ac..20d19f106b 100644 --- a/lib/private/Group/Manager.php +++ b/lib/private/Group/Manager.php @@ -74,7 +74,7 @@ class Manager extends PublicEmitter implements IGroupManager { private $cachedGroups = array(); /** - * @var \OC\Group\Group[][] + * @var \OC\Group\Group[] */ private $cachedUserGroups = array(); @@ -144,7 +144,16 @@ class Manager extends PublicEmitter implements IGroupManager { $this->backends = array(); $this->clearCaches(); } - + + /** + * Get the active backends + * @return \OCP\GroupInterface[] + */ + public function getBackends() { + return $this->backends; + } + + protected function clearCaches() { $this->cachedGroups = array(); $this->cachedUserGroups = array(); diff --git a/lib/public/IGroupManager.php b/lib/public/IGroupManager.php index be322b6432..778a0ef169 100644 --- a/lib/public/IGroupManager.php +++ b/lib/public/IGroupManager.php @@ -65,6 +65,13 @@ interface IGroupManager { */ public function clearBackends(); + /** + * Get the active backends + * @return \OCP\GroupInterface[] + * @since 13.0.0 + */ + public function getBackends(); + /** * @param string $gid * @return \OCP\IGroup diff --git a/lib/public/LDAP/ILDAPProvider.php b/lib/public/LDAP/ILDAPProvider.php index 3c07dfcbe8..a65d3e85cd 100644 --- a/lib/public/LDAP/ILDAPProvider.php +++ b/lib/public/LDAP/ILDAPProvider.php @@ -3,6 +3,10 @@ * * @copyright Copyright (c) 2016, Roger Szabo (roger.szabo@web.de) * + * @author Roger Szabo + * @author Vinicius Brand + * @author Daniel Tygel + * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -36,7 +40,15 @@ interface ILDAPProvider { * @since 11.0.0 */ public function getUserDN($uid); - + + /** + * Translate a group id to LDAP DN. + * @param string $gid group id + * @return string + * @since 13.0.0 + */ + public function getGroupDN($gid); + /** * Translate a LDAP DN to an internal user name. * @param string $dn LDAP DN @@ -69,6 +81,14 @@ interface ILDAPProvider { * @since 11.0.0 */ public function getLDAPConnection($uid); + + /** + * Return a new LDAP connection resource for the specified group. + * @param string $gid group id + * @return resource of the LDAP connection + * @since 13.0.0 + */ + public function getGroupLDAPConnection($gid); /** * Get the LDAP base for users. @@ -102,4 +122,39 @@ interface ILDAPProvider { * @since 11.0.0 */ public function clearCache($uid); + + /** + * Clear the cache if a cache is used, otherwise do nothing. + * @param string $gid group id + * @since 13.0.0 + */ + public function clearGroupCache($gid); + + /** + * Get the LDAP attribute name for the user's display name + * @param string $uid user id + * @return string the display name field + * @throws \Exception if user id was not found in LDAP + * @since 12.0.0 + */ + public function getLDAPDisplayNameField($uid); + + /** + * Get the LDAP attribute name for the email + * @param string $uid user id + * @return string the email field + * @throws \Exception if user id was not found in LDAP + * @since 12.0.0 + */ + public function getLDAPEmailField($uid); + + /** + * Get the LDAP attribute name for the type of association betweeen users and groups + * @param string $gid group id + * @return string the configuration, one of: 'memberUid', 'uniqueMember', 'member', 'gidNumber' + * @throws \Exception if group id was not found in LDAP + * @since 13.0.0 + */ + public function getLDAPGroupMemberAssoc($gid); + }