mirror of
https://github.com/nextcloud/server.git
synced 2026-04-15 22:11:17 -04:00
Split mapping from Access and Helper classes into it's own. Fully test them, too.
remove unused methods split mapping methods off from Access class fix DB query handling move 'clear mapping' methods from static helper to new mapping class add tests test directly with DB finishing tests and fix return value from setDNbyUUID add corresponding class for groups and make abstract test class neutral. helper tests is now obsolete as the tested functions were moved to the new mapper class. add missing info to PHPDoc add unmap method fix namespaces fix test inheritance PHPDoc and a small code restructure for scrutinizer, no effective changes PostgreSQL does not accept LIMIT in DELETE queries phpdoc fixes, no code changes
This commit is contained in:
parent
87e3e29250
commit
ec0f80fee9
15 changed files with 574 additions and 283 deletions
|
|
@ -21,15 +21,27 @@
|
|||
*
|
||||
*/
|
||||
|
||||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
use OCA\User_LDAP\Mapping\GroupMapping;
|
||||
|
||||
// Check user and app status
|
||||
OCP\JSON::checkAdminUser();
|
||||
OCP\JSON::checkAppEnabled('user_ldap');
|
||||
OCP\JSON::callCheck();
|
||||
|
||||
$subject = $_POST['ldap_clear_mapping'];
|
||||
if(\OCA\user_ldap\lib\Helper::clearMapping($subject)) {
|
||||
OCP\JSON::success();
|
||||
} else {
|
||||
$l = \OC::$server->getL10N('user_ldap');
|
||||
OCP\JSON::error(array('message' => $l->t('Failed to clear the mappings.')));
|
||||
$mapping = null;
|
||||
if($subject === 'user') {
|
||||
$mapping = new UserMapping(\OC::$server->getDatabaseConnection());
|
||||
} else if($subject === 'group') {
|
||||
$mapping = new GroupMapping(\OC::$server->getDatabaseConnection());
|
||||
}
|
||||
try {
|
||||
if(is_null($mapping) || !$mapping->clear()) {
|
||||
$l = \OC::$server->getL10N('user_ldap');
|
||||
throw new \Exception($l->t('Failed to clear the mappings.'));
|
||||
}
|
||||
OCP\JSON::success();
|
||||
} catch (\Exception $e) {
|
||||
OCP\JSON::error(array('message' => $e->getMessage()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ if(count($configPrefixes) === 1) {
|
|||
new \OCP\Image());
|
||||
$connector = new OCA\user_ldap\lib\Connection($ldapWrapper, $configPrefixes[0]);
|
||||
$ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper, $userManager);
|
||||
$dbc = \OC::$server->getDatabaseConnection();
|
||||
$ldapAccess->setUserMapper(new OCA\User_LDAP\Mapping\UserMapping($dbc));
|
||||
$ldapAccess->setGroupMapper(new OCA\User_LDAP\Mapping\GroupMapping($dbc));
|
||||
$userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess);
|
||||
$groupBackend = new OCA\user_ldap\GROUP_LDAP($ldapAccess);
|
||||
} else if(count($configPrefixes) > 1) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
namespace OCA\user_ldap\lib;
|
||||
|
||||
use OCA\User_LDAP\Mapping\AbstractMapping;
|
||||
|
||||
/**
|
||||
* Class Access
|
||||
* @package OCA\user_ldap\lib
|
||||
|
|
@ -47,6 +49,16 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
*/
|
||||
protected $lastCookie = '';
|
||||
|
||||
/**
|
||||
* @var AbstractMapping $userMapper
|
||||
*/
|
||||
protected $userMapper;
|
||||
|
||||
/**
|
||||
* @var AbstractMapping $userMapper
|
||||
*/
|
||||
protected $groupMapper;
|
||||
|
||||
public function __construct(Connection $connection, ILDAPWrapper $ldap,
|
||||
user\Manager $userManager) {
|
||||
parent::__construct($ldap);
|
||||
|
|
@ -55,6 +67,22 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
$this->userManager->setLdapAccess($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the User Mapper
|
||||
* @param AbstractMapping $mapper
|
||||
*/
|
||||
public function setUserMapper(AbstractMapping $mapper) {
|
||||
$this->userMapper = $mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the Group Mapper
|
||||
* @param AbstractMapping $mapper
|
||||
*/
|
||||
public function setGroupMapper(AbstractMapping $mapper) {
|
||||
$this->groupMapper = $mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
|
@ -235,32 +263,13 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
return $domainDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* gives back the database table for the query
|
||||
* @param bool $isUser
|
||||
* @return string
|
||||
*/
|
||||
private function getMapTable($isUser) {
|
||||
if($isUser) {
|
||||
return '*PREFIX*ldap_user_mapping';
|
||||
} else {
|
||||
return '*PREFIX*ldap_group_mapping';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the LDAP DN for the given internal ownCloud name of the group
|
||||
* @param string $name the ownCloud name in question
|
||||
* @return string with the LDAP DN on success, otherwise false
|
||||
* @return string|false LDAP DN on success, otherwise false
|
||||
*/
|
||||
public function groupname2dn($name) {
|
||||
$dn = $this->ocname2dn($name, false);
|
||||
|
||||
if($dn) {
|
||||
return $dn;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $this->groupMapper->getDNbyName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -269,50 +278,32 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
* @return string with the LDAP DN on success, otherwise false
|
||||
*/
|
||||
public function username2dn($name) {
|
||||
$dn = $this->ocname2dn($name, true);
|
||||
$fdn = $this->userMapper->getDNbyName($name);
|
||||
|
||||
//Check whether the DN belongs to the Base, to avoid issues on multi-
|
||||
//server setups
|
||||
if($dn && $this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) {
|
||||
return $dn;
|
||||
if(is_string($fdn) && $this->isDNPartOfBase($fdn, $this->connection->ldapBaseUsers)) {
|
||||
return $fdn;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the LDAP DN for the given internal ownCloud name
|
||||
* @param string $name the ownCloud name in question
|
||||
* @param boolean $isUser is it a user? otherwise group
|
||||
* @return string with the LDAP DN on success, otherwise false
|
||||
*/
|
||||
private function ocname2dn($name, $isUser) {
|
||||
$table = $this->getMapTable($isUser);
|
||||
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `ldap_dn`
|
||||
FROM `'.$table.'`
|
||||
WHERE `owncloud_name` = ?
|
||||
');
|
||||
|
||||
$record = $query->execute(array($name))->fetchOne();
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the internal ownCloud name for the given LDAP DN of the group, false on DN outside of search DN or failure
|
||||
* @param string $dn the dn of the group object
|
||||
* @param string $fdn the dn of the group object
|
||||
* @param string $ldapName optional, the display name of the object
|
||||
* @return string with the name to use in ownCloud, false on DN outside of search DN
|
||||
*/
|
||||
public function dn2groupname($dn, $ldapName = null) {
|
||||
public function dn2groupname($fdn, $ldapName = null) {
|
||||
//To avoid bypassing the base DN settings under certain circumstances
|
||||
//with the group support, check whether the provided DN matches one of
|
||||
//the given Bases
|
||||
if(!$this->isDNPartOfBase($dn, $this->connection->ldapBaseGroups)) {
|
||||
if(!$this->isDNPartOfBase($fdn, $this->connection->ldapBaseGroups)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->dn2ocname($dn, $ldapName, false);
|
||||
return $this->dn2ocname($fdn, $ldapName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -321,15 +312,15 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
* @param string $ldapName optional, the display name of the object
|
||||
* @return string with with the name to use in ownCloud
|
||||
*/
|
||||
public function dn2username($dn, $ldapName = null) {
|
||||
public function dn2username($fdn, $ldapName = null) {
|
||||
//To avoid bypassing the base DN settings under certain circumstances
|
||||
//with the group support, check whether the provided DN matches one of
|
||||
//the given Bases
|
||||
if(!$this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) {
|
||||
if(!$this->isDNPartOfBase($fdn, $this->connection->ldapBaseUsers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->dn2ocname($dn, $ldapName, true);
|
||||
return $this->dn2ocname($fdn, $ldapName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -339,50 +330,39 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
* @param bool $isUser optional, whether it is a user object (otherwise group assumed)
|
||||
* @return string with with the name to use in ownCloud
|
||||
*/
|
||||
public function dn2ocname($dn, $ldapName = null, $isUser = true) {
|
||||
$table = $this->getMapTable($isUser);
|
||||
public function dn2ocname($fdn, $ldapName = null, $isUser = true) {
|
||||
if($isUser) {
|
||||
$fncFindMappedName = 'findMappedUser';
|
||||
$mapper = $this->userMapper;
|
||||
$nameAttribute = $this->connection->ldapUserDisplayName;
|
||||
} else {
|
||||
$fncFindMappedName = 'findMappedGroup';
|
||||
$mapper = $this->groupMapper;
|
||||
$nameAttribute = $this->connection->ldapGroupDisplayName;
|
||||
}
|
||||
|
||||
//let's try to retrieve the ownCloud name from the mappings table
|
||||
$ocName = $this->$fncFindMappedName($dn);
|
||||
if($ocName) {
|
||||
$ocName = $mapper->getNameByDN($fdn);
|
||||
if(is_string($ocName)) {
|
||||
return $ocName;
|
||||
}
|
||||
|
||||
//second try: get the UUID and check if it is known. Then, update the DN and return the name.
|
||||
$uuid = $this->getUUID($dn, $isUser);
|
||||
if($uuid) {
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `owncloud_name`
|
||||
FROM `'.$table.'`
|
||||
WHERE `directory_uuid` = ?
|
||||
');
|
||||
$component = $query->execute(array($uuid))->fetchOne();
|
||||
if($component) {
|
||||
$query = \OCP\DB::prepare('
|
||||
UPDATE `'.$table.'`
|
||||
SET `ldap_dn` = ?
|
||||
WHERE `directory_uuid` = ?
|
||||
');
|
||||
$query->execute(array($dn, $uuid));
|
||||
return $component;
|
||||
$uuid = $this->getUUID($fdn, $isUser);
|
||||
if(is_string($uuid)) {
|
||||
$ocName = $mapper->getNameByUUID($uuid);
|
||||
if(is_string($ocName)) {
|
||||
$mapper->setDNbyUUID($fdn, $uuid);
|
||||
return $ocName;
|
||||
}
|
||||
} else {
|
||||
//If the UUID can't be detected something is foul.
|
||||
\OCP\Util::writeLog('user_ldap', 'Cannot determine UUID for '.$dn.'. Skipping.', \OCP\Util::INFO);
|
||||
\OCP\Util::writeLog('user_ldap', 'Cannot determine UUID for '.$fdn.'. Skipping.', \OCP\Util::INFO);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(is_null($ldapName)) {
|
||||
$ldapName = $this->readAttribute($dn, $nameAttribute);
|
||||
$ldapName = $this->readAttribute($fdn, $nameAttribute);
|
||||
if(!isset($ldapName[0]) && empty($ldapName[0])) {
|
||||
\OCP\Util::writeLog('user_ldap', 'No or empty name for '.$dn.'.', \OCP\Util::INFO);
|
||||
\OCP\Util::writeLog('user_ldap', 'No or empty name for '.$fdn.'.', \OCP\Util::INFO);
|
||||
return false;
|
||||
}
|
||||
$ldapName = $ldapName[0];
|
||||
|
|
@ -390,8 +370,8 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
|
||||
if($isUser) {
|
||||
$usernameAttribute = $this->connection->ldapExpertUsernameAttr;
|
||||
if(!emptY($usernameAttribute)) {
|
||||
$username = $this->readAttribute($dn, $usernameAttribute);
|
||||
if(!empty($usernameAttribute)) {
|
||||
$username = $this->readAttribute($fdn, $usernameAttribute);
|
||||
$username = $username[0];
|
||||
} else {
|
||||
$username = $uuid;
|
||||
|
|
@ -409,7 +389,7 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
$this->connection->setConfiguration(array('ldapCacheTTL' => 0));
|
||||
if(($isUser && !\OCP\User::userExists($intName))
|
||||
|| (!$isUser && !\OC_Group::groupExists($intName))) {
|
||||
if($this->mapComponent($dn, $intName, $isUser)) {
|
||||
if($mapper->map($fdn, $intName, $uuid)) {
|
||||
$this->connection->setConfiguration(array('ldapCacheTTL' => $originalTTL));
|
||||
return $intName;
|
||||
}
|
||||
|
|
@ -417,12 +397,12 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
$this->connection->setConfiguration(array('ldapCacheTTL' => $originalTTL));
|
||||
|
||||
$altName = $this->createAltInternalOwnCloudName($intName, $isUser);
|
||||
if($this->mapComponent($dn, $altName, $isUser)) {
|
||||
if(is_string($altName) && $mapper->map($fdn, $altName, $uuid)) {
|
||||
return $altName;
|
||||
}
|
||||
|
||||
//if everything else did not help..
|
||||
\OCP\Util::writeLog('user_ldap', 'Could not create unique name for '.$dn.'.', \OCP\Util::INFO);
|
||||
\OCP\Util::writeLog('user_ldap', 'Could not create unique name for '.$fdn.'.', \OCP\Util::INFO);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -448,46 +428,6 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
return $this->ldap2ownCloudNames($ldapGroups, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dn
|
||||
* @return bool|string
|
||||
*/
|
||||
private function findMappedUser($dn) {
|
||||
static $query = null;
|
||||
if(is_null($query)) {
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `owncloud_name`
|
||||
FROM `'.$this->getMapTable(true).'`
|
||||
WHERE `ldap_dn` = ?'
|
||||
);
|
||||
}
|
||||
$res = $query->execute(array($dn))->fetchOne();
|
||||
if($res) {
|
||||
return $res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dn
|
||||
* @return bool|string
|
||||
*/
|
||||
private function findMappedGroup($dn) {
|
||||
static $query = null;
|
||||
if(is_null($query)) {
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `owncloud_name`
|
||||
FROM `'.$this->getMapTable(false).'`
|
||||
WHERE `ldap_dn` = ?'
|
||||
);
|
||||
}
|
||||
$res = $query->execute(array($dn))->fetchOne();
|
||||
if($res) {
|
||||
return $res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ldapObjects
|
||||
* @param bool $isUsers
|
||||
|
|
@ -571,17 +511,7 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
* "Developers"
|
||||
*/
|
||||
private function _createAltInternalOwnCloudNameForGroups($name) {
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `owncloud_name`
|
||||
FROM `'.$this->getMapTable(false).'`
|
||||
WHERE `owncloud_name` LIKE ?
|
||||
');
|
||||
|
||||
$usedNames = array();
|
||||
$res = $query->execute(array($name.'_%'));
|
||||
while($row = $res->fetchRow()) {
|
||||
$usedNames[] = $row['owncloud_name'];
|
||||
}
|
||||
$usedNames = $this->groupMapper->getNamesBySearch($name.'_%');
|
||||
if(!($usedNames) || count($usedNames) === 0) {
|
||||
$lastNo = 1; //will become name_2
|
||||
} else {
|
||||
|
|
@ -625,92 +555,6 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
return $altName;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all known groups from the mappings table
|
||||
* @return array with the results
|
||||
*
|
||||
* retrieves all known groups from the mappings table
|
||||
*/
|
||||
private function mappedGroups() {
|
||||
return $this->mappedComponents(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all known users from the mappings table
|
||||
* @return array with the results
|
||||
*
|
||||
* retrieves all known users from the mappings table
|
||||
*/
|
||||
private function mappedUsers() {
|
||||
return $this->mappedComponents(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $isUsers
|
||||
* @return array
|
||||
*/
|
||||
private function mappedComponents($isUsers) {
|
||||
$table = $this->getMapTable($isUsers);
|
||||
|
||||
$query = \OCP\DB::prepare('
|
||||
SELECT `ldap_dn`, `owncloud_name`
|
||||
FROM `'. $table . '`'
|
||||
);
|
||||
|
||||
return $query->execute()->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* inserts a new user or group into the mappings table
|
||||
* @param string $dn the record in question
|
||||
* @param string $ocName the name to use in ownCloud
|
||||
* @param bool $isUser is it a user or a group?
|
||||
* @return bool true on success, false otherwise
|
||||
*
|
||||
* inserts a new user or group into the mappings table
|
||||
*/
|
||||
private function mapComponent($dn, $ocName, $isUser = true) {
|
||||
$table = $this->getMapTable($isUser);
|
||||
|
||||
$sqlAdjustment = '';
|
||||
$dbType = \OC::$server->getConfig()->getSystemValue('dbtype', null);
|
||||
if($dbType === 'mysql' || $dbType == 'oci') {
|
||||
$sqlAdjustment = 'FROM DUAL';
|
||||
}
|
||||
|
||||
$insert = \OCP\DB::prepare('
|
||||
INSERT INTO `'.$table.'` (`ldap_dn`, `owncloud_name`, `directory_uuid`)
|
||||
SELECT ?,?,?
|
||||
'.$sqlAdjustment.'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM `'.$table.'`
|
||||
WHERE `ldap_dn` = ?
|
||||
OR `owncloud_name` = ?)
|
||||
');
|
||||
|
||||
//feed the DB
|
||||
$insRows = $insert->execute(array($dn, $ocName,
|
||||
$this->getUUID($dn, $isUser), $dn,
|
||||
$ocName));
|
||||
|
||||
if(\OCP\DB::isError($insRows)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($insRows === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($isUser) {
|
||||
//make sure that email address is retrieved prior to login, so user
|
||||
//will be notified when something is shared with him
|
||||
$this->userManager->get($ocName)->update();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filter
|
||||
* @param string|string[] $attr
|
||||
|
|
@ -1305,7 +1149,7 @@ class Access extends LDAPUtility implements user\IUserTools {
|
|||
/**
|
||||
* @param string $dn
|
||||
* @param bool $isUser
|
||||
* @return array|bool|false
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getUUID($dn, $isUser = true) {
|
||||
if($isUser) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace OCA\user_ldap\lib;
|
|||
* @property string ldapUserFilter
|
||||
* @property string ldapUserDisplayName
|
||||
* @property boolean hasPagedResultSupport
|
||||
* @property string[] ldapBaseUsers
|
||||
*/
|
||||
class Connection extends LDAPUtility {
|
||||
private $ldapConnectionRes = null;
|
||||
|
|
|
|||
|
|
@ -141,33 +141,6 @@ class Helper {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate's the given mapping table
|
||||
*
|
||||
* @param string $mapping either 'user' or 'group'
|
||||
* @return bool true on success, false otherwise
|
||||
*/
|
||||
static public function clearMapping($mapping) {
|
||||
if($mapping === 'user') {
|
||||
$table = '`*PREFIX*ldap_user_mapping`';
|
||||
} else if ($mapping === 'group') {
|
||||
$table = '`*PREFIX*ldap_group_mapping`';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$connection = \OC_DB::getConnection();
|
||||
$sql = $connection->getDatabasePlatform()->getTruncateTableSQL($table);
|
||||
$query = \OCP\DB::prepare($sql);
|
||||
$res = $query->execute();
|
||||
|
||||
if(\OCP\DB::isError($res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts the domain from a given URL
|
||||
* @param string $url the URL
|
||||
|
|
|
|||
201
apps/user_ldap/lib/mapping/abstractmapping.php
Normal file
201
apps/user_ldap/lib/mapping/abstractmapping.php
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\User_LDAP\Mapping;
|
||||
|
||||
/**
|
||||
* Class AbstractMapping
|
||||
* @package OCA\User_LDAP\Mapping
|
||||
*/
|
||||
abstract class AbstractMapping {
|
||||
/**
|
||||
* @var \OCP\IDBConnection $dbc
|
||||
*/
|
||||
protected $dbc;
|
||||
|
||||
/**
|
||||
* returns the DB table name which holds the mappings
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getTableName();
|
||||
|
||||
/**
|
||||
* @param \OCP\IDBConnection $dbc
|
||||
*/
|
||||
public function __construct(\OCP\IDBConnection $dbc) {
|
||||
$this->dbc = $dbc;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a provided string represents an exisiting table col
|
||||
* @param string $col
|
||||
* @return bool
|
||||
*/
|
||||
public function isColNameValid($col) {
|
||||
switch($col) {
|
||||
case 'ldap_dn':
|
||||
case 'owncloud_name':
|
||||
case 'directory_uuid':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of one column based on a provided value of another column
|
||||
* @param string $fetchCol
|
||||
* @param string $compareCol
|
||||
* @param string $search
|
||||
* @throws \Exception
|
||||
* @return string|false
|
||||
*/
|
||||
protected function getXbyY($fetchCol, $compareCol, $search) {
|
||||
if(!$this->isColNameValid($fetchCol)) {
|
||||
//this is used internally only, but we don't want to risk
|
||||
//having SQL injection at all.
|
||||
throw new \Exception('Invalid Column Name');
|
||||
}
|
||||
$query = $this->dbc->prepare('
|
||||
SELECT `' . $fetchCol . '`
|
||||
FROM `'. $this->getTableName() .'`
|
||||
WHERE `' . $compareCol . '` = ?
|
||||
');
|
||||
|
||||
$res = $query->execute(array($search));
|
||||
if($res !== false) {
|
||||
return $query->fetchColumn();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a DELETE or UPDATE query to the database.
|
||||
* @param \Doctrine\DBAL\Driver\Statement $query
|
||||
* @param array $parameters
|
||||
* @return bool true if at least one row was modified, false otherwise
|
||||
*/
|
||||
protected function modify($query, $parameters) {
|
||||
$result = $query->execute($parameters);
|
||||
return ($result === true && $query->rowCount() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LDAP DN based on the provided name.
|
||||
* Replaces Access::ocname2dn
|
||||
* @param string $name
|
||||
* @return string|false
|
||||
*/
|
||||
public function getDNByName($name) {
|
||||
return $this->getXbyY('ldap_dn', 'owncloud_name', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the DN based on the given UUID
|
||||
* @param string $fdn
|
||||
* @param string $uuid
|
||||
* @return bool
|
||||
*/
|
||||
public function setDNbyUUID($fdn, $uuid) {
|
||||
$query = $this->dbc->prepare('
|
||||
UPDATE `' . $this->getTableName() . '`
|
||||
SET `ldap_dn` = ?
|
||||
WHERE `directory_uuid` = ?
|
||||
');
|
||||
|
||||
return $this->modify($query, array($fdn, $uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name based on the provided LDAP DN.
|
||||
* @param string $fdn
|
||||
* @return string|false
|
||||
*/
|
||||
public function getNameByDN($fdn) {
|
||||
return $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches mapped names by the giving string in the name column
|
||||
* @param string $search
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNamesBySearch($search) {
|
||||
$query = $this->dbc->prepare('
|
||||
SELECT `owncloud_name`
|
||||
FROM `'. $this->getTableName() .'`
|
||||
WHERE `owncloud_name` LIKE ?
|
||||
');
|
||||
|
||||
$res = $query->execute(array($search));
|
||||
$names = array();
|
||||
if($res !== false) {
|
||||
while($row = $query->fetch()) {
|
||||
$names[] = $row['owncloud_name'];
|
||||
}
|
||||
}
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name based on the provided LDAP DN.
|
||||
* @param string $uuid
|
||||
* @return string|false
|
||||
*/
|
||||
public function getNameByUUID($uuid) {
|
||||
return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* attempts to map the given entry
|
||||
* @param string $fdn fully distinguished name (from LDAP)
|
||||
* @param string $name
|
||||
* @param string $uuid a unique identifier as used in LDAP
|
||||
* @return bool
|
||||
*/
|
||||
public function map($fdn, $name, $uuid) {
|
||||
$row = array(
|
||||
'ldap_dn' => $fdn,
|
||||
'owncloud_name' => $name,
|
||||
'directory_uuid' => $uuid
|
||||
);
|
||||
|
||||
try {
|
||||
$result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
|
||||
// insertIfNotExist returns values as int
|
||||
return (bool)$result;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a mapping based on the owncloud_name of the entry
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function unmap($name) {
|
||||
$query = $this->dbc->prepare('
|
||||
DELETE FROM `'. $this->getTableName() .'`
|
||||
WHERE `owncloud_name` = ?');
|
||||
|
||||
return $this->modify($query, array($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate's the mapping table
|
||||
* @return bool
|
||||
*/
|
||||
public function clear() {
|
||||
$sql = $this->dbc
|
||||
->getDatabasePlatform()
|
||||
->getTruncateTableSQL('`' . $this->getTableName() . '`');
|
||||
return $this->dbc->prepare($sql)->execute();
|
||||
}
|
||||
}
|
||||
25
apps/user_ldap/lib/mapping/groupmapping.php
Normal file
25
apps/user_ldap/lib/mapping/groupmapping.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\User_LDAP\Mapping;
|
||||
|
||||
/**
|
||||
* Class UserMapping
|
||||
* @package OCA\User_LDAP\Mapping
|
||||
*/
|
||||
class GroupMapping extends AbstractMapping {
|
||||
|
||||
/**
|
||||
* returns the DB table name which holds the mappings
|
||||
* @return string
|
||||
*/
|
||||
protected function getTableName() {
|
||||
return '*PREFIX*ldap_group_mapping';
|
||||
}
|
||||
|
||||
}
|
||||
25
apps/user_ldap/lib/mapping/usermapping.php
Normal file
25
apps/user_ldap/lib/mapping/usermapping.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\User_LDAP\Mapping;
|
||||
|
||||
/**
|
||||
* Class UserMapping
|
||||
* @package OCA\User_LDAP\Mapping
|
||||
*/
|
||||
class UserMapping extends AbstractMapping {
|
||||
|
||||
/**
|
||||
* returns the DB table name which holds the mappings
|
||||
* @return string
|
||||
*/
|
||||
protected function getTableName() {
|
||||
return '*PREFIX*ldap_user_mapping';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
namespace OCA\user_ldap\lib;
|
||||
|
||||
use OCA\user_ldap\lib\Access;
|
||||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
use OCA\User_LDAP\Mapping\GroupMapping;
|
||||
|
||||
abstract class Proxy {
|
||||
static private $accesses = array();
|
||||
|
|
@ -45,17 +47,23 @@ abstract class Proxy {
|
|||
static $fs;
|
||||
static $log;
|
||||
static $avatarM;
|
||||
static $userMap;
|
||||
static $groupMap;
|
||||
if(is_null($fs)) {
|
||||
$ocConfig = \OC::$server->getConfig();
|
||||
$fs = new FilesystemHelper();
|
||||
$log = new LogWrapper();
|
||||
$avatarM = \OC::$server->getAvatarManager();
|
||||
$userMap = new UserMapping(\OC::$server->getDatabaseConnection());
|
||||
$groupMap = new GroupMapping(\OC::$server->getDatabaseConnection());
|
||||
}
|
||||
$userManager =
|
||||
new user\Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image());
|
||||
$connector = new Connection($this->ldap, $configPrefix);
|
||||
self::$accesses[$configPrefix] =
|
||||
new Access($connector, $this->ldap, $userManager);
|
||||
$access = new Access($connector, $this->ldap, $userManager);
|
||||
$access->setUserMapper($userMap);
|
||||
$access->setGroupMapper($groupMap);
|
||||
self::$accesses[$configPrefix] = $access;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Thomas Müller
|
||||
* @copyright 2014 Thomas Müller deepdiver@owncloud.com
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\user_ldap\tests;
|
||||
|
||||
use OCA\user_ldap\lib\Helper;
|
||||
|
||||
class Test_Helper extends \Test\TestCase {
|
||||
|
||||
public function testTableTruncate() {
|
||||
|
||||
$statement = \OCP\DB::prepare('INSERT INTO `*PREFIX*ldap_user_mapping` (`ldap_dn`, `owncloud_name`, `directory_uuid`) VALUES (?, ?, ?)');
|
||||
$statement->execute(array('db01', 'oc1', '000-0000-0000'));
|
||||
$statement->execute(array('db02', 'oc2', '000-0000-0001'));
|
||||
|
||||
$statement = \OCP\DB::prepare('SELECT count(*) FROM `*PREFIX*ldap_user_mapping`');
|
||||
$result = $statement->execute();
|
||||
$this->assertEquals(2, $result->fetchOne());
|
||||
|
||||
Helper::clearMapping('user');
|
||||
|
||||
$result = $statement->execute();
|
||||
$this->assertEquals(0, $result->fetchOne());
|
||||
}
|
||||
}
|
||||
194
apps/user_ldap/tests/mapping/abstractmappingtest.php
Normal file
194
apps/user_ldap/tests/mapping/abstractmappingtest.php
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\user_ldap\tests\mapping;
|
||||
|
||||
abstract class AbstractMappingTest extends \Test\TestCase {
|
||||
abstract public function getMapper(\OCP\IDBConnection $dbMock);
|
||||
|
||||
/**
|
||||
* kiss test on isColNameValid
|
||||
*/
|
||||
public function testIsColNameValid() {
|
||||
$dbMock = $this->getMock('\OCP\IDBConnection');
|
||||
$mapper = $this->getMapper($dbMock);
|
||||
|
||||
$this->assertTrue($mapper->isColNameValid('ldap_dn'));
|
||||
$this->assertFalse($mapper->isColNameValid('foobar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array of test entries with dn, name and uuid as keys
|
||||
* @return array
|
||||
*/
|
||||
protected function getTestData() {
|
||||
$data = array(
|
||||
array(
|
||||
'dn' => 'uid=foobar,dc=example,dc=org',
|
||||
'name' => 'Foobar',
|
||||
'uuid' => '1111-AAAA-1234-CDEF',
|
||||
),
|
||||
array(
|
||||
'dn' => 'uid=barfoo,dc=example,dc=org',
|
||||
'name' => 'Barfoo',
|
||||
'uuid' => '2222-BBBB-1234-CDEF',
|
||||
),
|
||||
array(
|
||||
'dn' => 'uid=barabara,dc=example,dc=org',
|
||||
'name' => 'BaraBara',
|
||||
'uuid' => '3333-CCCC-1234-CDEF',
|
||||
)
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* calls map() on the given mapper and asserts result for true
|
||||
* @param \OCA\User_LDAP\Mapping\AbstractMapping $mapper
|
||||
* @param array $data
|
||||
*/
|
||||
protected function mapEntries($mapper, $data) {
|
||||
foreach($data as $entry) {
|
||||
$done = $mapper->map($entry['dn'], $entry['name'], $entry['uuid']);
|
||||
$this->assertTrue($done);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initalizes environment for a test run and returns an array with
|
||||
* test objects. Preparing environment means that all mappings are cleared
|
||||
* first and then filled with test entries.
|
||||
* @return array 0 = \OCA\User_LDAP\Mapping\AbstractMapping, 1 = array of
|
||||
* users or groups
|
||||
*/
|
||||
private function initTest() {
|
||||
$dbc = \OC::$server->getDatabaseConnection();
|
||||
$mapper = $this->getMapper($dbc);
|
||||
$data = $this->getTestData();
|
||||
// make sure DB is pristine, then fill it with test entries
|
||||
$mapper->clear();
|
||||
$this->mapEntries($mapper, $data);
|
||||
|
||||
return array($mapper, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* tests map() method with input that should result in not-mapping.
|
||||
* Hint: successful mapping is tested inherently with mapEntries().
|
||||
*/
|
||||
public function testMap() {
|
||||
list($mapper, $data) = $this->initTest();
|
||||
|
||||
// test that mapping will not happen when it shall not
|
||||
$paramKeys = array('', 'dn', 'name', 'uuid');
|
||||
foreach($paramKeys as $key) {
|
||||
$failEntry = $data[0];
|
||||
if(!empty($key)) {
|
||||
$failEntry[$key] = 'do-not-get-mapped';
|
||||
}
|
||||
$isMapped = $mapper->map($failEntry['dn'], $failEntry['name'], $failEntry['uuid']);
|
||||
$this->assertFalse($isMapped);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tests unmap() for both successfuly and not successful removing of
|
||||
* mapping entries
|
||||
*/
|
||||
public function testUnmap() {
|
||||
list($mapper, $data) = $this->initTest();
|
||||
|
||||
foreach($data as $entry) {
|
||||
$result = $mapper->unmap($entry['name']);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
$result = $mapper->unmap('notAnEntry');
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* tests getDNByName(), getNameByDN() and getNameByUUID() for successful
|
||||
* and unsuccessful requests.
|
||||
*/
|
||||
public function testGetMethods() {
|
||||
list($mapper, $data) = $this->initTest();
|
||||
|
||||
foreach($data as $entry) {
|
||||
$fdn = $mapper->getDNByName($entry['name']);
|
||||
$this->assertSame($fdn, $entry['dn']);
|
||||
}
|
||||
$fdn = $mapper->getDNByName('nosuchname');
|
||||
$this->assertFalse($fdn);
|
||||
|
||||
foreach($data as $entry) {
|
||||
$name = $mapper->getNameByDN($entry['dn']);
|
||||
$this->assertSame($name, $entry['name']);
|
||||
}
|
||||
$name = $mapper->getNameByDN('nosuchdn');
|
||||
$this->assertFalse($name);
|
||||
|
||||
foreach($data as $entry) {
|
||||
$name = $mapper->getNameByUUID($entry['uuid']);
|
||||
$this->assertSame($name, $entry['name']);
|
||||
}
|
||||
$name = $mapper->getNameByUUID('nosuchuuid');
|
||||
$this->assertFalse($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* tests getNamesBySearch() for successful and unsuccessful requests.
|
||||
*/
|
||||
public function testSearch() {
|
||||
list($mapper,) = $this->initTest();
|
||||
|
||||
$names = $mapper->getNamesBySearch('%oo%');
|
||||
$this->assertTrue(is_array($names));
|
||||
$this->assertSame(2, count($names));
|
||||
$this->assertTrue(in_array('Foobar', $names));
|
||||
$this->assertTrue(in_array('Barfoo', $names));
|
||||
$names = $mapper->getNamesBySearch('nada');
|
||||
$this->assertTrue(is_array($names));
|
||||
$this->assertSame(0, count($names));
|
||||
}
|
||||
|
||||
/**
|
||||
* tests setDNbyUUID() for successful and unsuccessful update.
|
||||
*/
|
||||
public function testSetMethod() {
|
||||
list($mapper, $data) = $this->initTest();
|
||||
|
||||
$newDN = 'uid=modified,dc=example,dc=org';
|
||||
$done = $mapper->setDNbyUUID($newDN, $data[0]['uuid']);
|
||||
$this->assertTrue($done);
|
||||
$fdn = $mapper->getDNByName($data[0]['name']);
|
||||
$this->assertSame($fdn, $newDN);
|
||||
|
||||
$newDN = 'uid=notme,dc=example,dc=org';
|
||||
$done = $mapper->setDNbyUUID($newDN, 'iamnothere');
|
||||
$this->assertFalse($done);
|
||||
$name = $mapper->getNameByDN($newDN);
|
||||
$this->assertFalse($name);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* tests clear() for successful update.
|
||||
*/
|
||||
public function testClear() {
|
||||
list($mapper, $data) = $this->initTest();
|
||||
|
||||
$done = $mapper->clear();
|
||||
$this->assertTrue($done);
|
||||
foreach($data as $entry) {
|
||||
$name = $mapper->getNameByUUID($entry['uuid']);
|
||||
$this->assertFalse($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
apps/user_ldap/tests/mapping/groupmapping.php
Normal file
17
apps/user_ldap/tests/mapping/groupmapping.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\user_ldap\tests\mapping;
|
||||
|
||||
use OCA\User_LDAP\Mapping\GroupMapping;
|
||||
|
||||
class Test_GroupMapping extends AbstractMappingTest {
|
||||
public function getMapper(\OCP\IDBConnection $dbMock) {
|
||||
return new GroupMapping($dbMock);
|
||||
}
|
||||
}
|
||||
17
apps/user_ldap/tests/mapping/usermapping.php
Normal file
17
apps/user_ldap/tests/mapping/usermapping.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\user_ldap\tests\mapping;
|
||||
|
||||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
|
||||
class Test_UserMapping extends AbstractMappingTest {
|
||||
public function getMapper(\OCP\IDBConnection $dbMock) {
|
||||
return new UserMapping($dbMock);
|
||||
}
|
||||
}
|
||||
|
|
@ -142,6 +142,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
|
|||
* Insert a row if a matching row doesn't exists.
|
||||
* @param string $table. The table to insert into in the form '*PREFIX*tableName'
|
||||
* @param array $input. An array of fieldname/value pairs
|
||||
* @throws \OC\HintException
|
||||
* @return bool The return value from execute()
|
||||
*/
|
||||
public function insertIfNotExist($table, $input) {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ interface IDBConnection {
|
|||
* Insert a row if a matching row doesn't exists.
|
||||
* @param string $table The table name (will replace *PREFIX*) to perform the replace on.
|
||||
* @param array $input
|
||||
* @throws \OC\HintException
|
||||
*
|
||||
* The input array if in the form:
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue