diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index c2cd295523..a26c7709d4 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -26,8 +26,14 @@ OCP\App::registerAdmin('user_ldap', 'settings'); $configPrefixes = OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes(true); $ldapWrapper = new OCA\user_ldap\lib\LDAP(); if(count($configPrefixes) === 1) { + $ocConfig = \OC::$server->getConfig(); + $userManager = new OCA\user_ldap\lib\user\Manager($ocConfig, + new OCA\user_ldap\lib\FilesystemHelper(), + new OCA\user_ldap\lib\LogWrapper(), + \OC::$server->getAvatarManager(), + new \OCP\Image()); $connector = new OCA\user_ldap\lib\Connection($ldapWrapper, $configPrefixes[0]); - $ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper); + $ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper, $userManager); $userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess); $groupBackend = new OCA\user_ldap\GROUP_LDAP($ldapAccess); } else if(count($configPrefixes) > 1) { diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 78de14f4ee..d488d2da12 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -27,20 +27,21 @@ namespace OCA\user_ldap\lib; * Class Access * @package OCA\user_ldap\lib */ -class Access extends LDAPUtility { +class Access extends LDAPUtility implements user\IUserTools { public $connection; + public $userManager; //never ever check this var directly, always use getPagedSearchResultState protected $pagedSearchedSuccessful; protected $cookies = array(); - /** - * @param Connection $connection - * @param ILDAPWrapper $ldap - */ - public function __construct(Connection $connection, ILDAPWrapper $ldap) { + + public function __construct(Connection $connection, ILDAPWrapper $ldap, + user\Manager $userManager) { parent::__construct($ldap); $this->connection = $connection; + $this->userManager = $userManager; + $this->userManager->setLdapAccess($this); } /** @@ -50,10 +51,18 @@ class Access extends LDAPUtility { return ($this->connection instanceof Connection); } + /** + * returns the Connection instance + * @return \OCA\user_ldap\lib\Connection + */ + public function getConnection() { + return $this->connection; + } + /** * reads a given attribute for an LDAP record identified by a DN - * @param string $dn the record in question - * @param string $attr the attribute that shall be retrieved + * @param $dn the record in question + * @param $attr the attribute that shall be retrieved * if empty, just check the record's existence * @param string $filter * @return array|false an array of values on success or an empty @@ -626,6 +635,12 @@ class Access extends LDAPUtility { 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; } diff --git a/apps/user_ldap/lib/filesystemhelper.php b/apps/user_ldap/lib/filesystemhelper.php new file mode 100644 index 0000000000..abf0e8a7b5 --- /dev/null +++ b/apps/user_ldap/lib/filesystemhelper.php @@ -0,0 +1,46 @@ +. + * + */ + +namespace OCA\user_ldap\lib; + +/** + * @brief wraps around static ownCloud core methods + */ +class FilesystemHelper { + + /** + * @brief states whether the filesystem was loaded + * @return bool + */ + public function isLoaded() { + return \OC\Files\Filesystem::$loaded; + } + + /** + * @brief initializes the filesystem for the given user + * @param string the ownCloud username of the user + */ + public function setup($uid) { + \OC_Util::setupFS($uid); + } +} diff --git a/apps/user_ldap/lib/logwrapper.php b/apps/user_ldap/lib/logwrapper.php new file mode 100644 index 0000000000..4826cb0358 --- /dev/null +++ b/apps/user_ldap/lib/logwrapper.php @@ -0,0 +1,39 @@ +. + * + */ + +namespace OCA\user_ldap\lib; + +/** + * @brief wraps around static ownCloud core methods + */ +class LogWrapper { + protected $app = 'user_ldap'; + + /** + * @brief states whether the filesystem was loaded + * @return bool + */ + public function log($msg, $level) { + \OCP\Util::writeLog($this->app, $msg, $level); + } +} diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php index d15d1ae861..73a52a7ddd 100644 --- a/apps/user_ldap/lib/proxy.php +++ b/apps/user_ldap/lib/proxy.php @@ -41,8 +41,21 @@ abstract class Proxy { * @param string $configPrefix */ private function addAccess($configPrefix) { + static $ocConfig; + static $fs; + static $log; + static $avatarM; + if(is_null($fs)) { + $ocConfig = \OC::$server->getConfig(); + $fs = new FilesystemHelper(); + $log = new LogWrapper(); + $avatarM = \OC::$server->getAvatarManager(); + } + $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); + self::$accesses[$configPrefix] = + new Access($connector, $this->ldap, $userManager); } /** diff --git a/apps/user_ldap/lib/user/iusertools.php b/apps/user_ldap/lib/user/iusertools.php new file mode 100644 index 0000000000..e409f3afed --- /dev/null +++ b/apps/user_ldap/lib/user/iusertools.php @@ -0,0 +1,40 @@ +. + * + */ + +namespace OCA\user_ldap\lib\user; + +/** + * IUserTools + * + * defines methods that are required by User class for LDAP interaction + */ +interface IUserTools { + public function getConnection(); + + public function readAttribute($dn, $attr, $filter = 'objectClass=*'); + + public function dn2username($dn, $ldapname = null); + + public function username2dn($name); + +} diff --git a/apps/user_ldap/lib/user/manager.php b/apps/user_ldap/lib/user/manager.php new file mode 100644 index 0000000000..6c635518d9 --- /dev/null +++ b/apps/user_ldap/lib/user/manager.php @@ -0,0 +1,167 @@ +. + * + */ + +namespace OCA\user_ldap\lib\user; + +use OCA\user_ldap\lib\user\IUserTools; +use OCA\user_ldap\lib\user\User; +use OCA\user_ldap\lib\LogWrapper; +use OCA\user_ldap\lib\FilesystemHelper; + +/** + * Manager + * + * upon request, returns an LDAP user object either by creating or from run-time + * cache + */ +class Manager { + /** + * @var IUserTools + */ + protected $access; + /** + * @var \OCP\IConfig + */ + protected $ocConfig; + /** + * @var FilesystemHelper + */ + protected $ocFilesystem; + /** + * @var LogWrapper + */ + protected $ocLog; + /** + * @var \OCP\Image + */ + protected $image; + /** + * @param \OCP\IAvatarManager + */ + protected $avatarManager; + /** + * @var string[][] + */ + protected $users = array( + 'byDN' => array(), + 'byUid' => array(), + ); + + /** + * @brief Constructor + * @param \OCP\IConfig respectively an instance that provides the methods + * setUserValue and getUserValue as implemented in \OCP\Config + * @param \OCA\user_ldap\lib\FilesystemHelper object that gives access to + * necessary functions from the OC filesystem + * @param \OCA\user_ldap\lib\LogWrapper + * @param \OCP\IAvatarManager + * @param \OCP\Image an empty image instance + * @throws Exception when the methods mentioned above do not exist + */ + public function __construct(\OCP\IConfig $ocConfig, + FilesystemHelper $ocFilesystem, LogWrapper $ocLog, + \OCP\IAvatarManager $avatarManager, \OCP\Image $image) { + + if(!method_exists($ocConfig, 'setUserValue') + || !method_exists($ocConfig, 'getUserValue')) { + throw new \Exception('Invalid ownCloud User Config object'); + } + $this->ocConfig = $ocConfig; + $this->ocFilesystem = $ocFilesystem; + $this->ocLog = $ocLog; + $this->avatarManager = $avatarManager; + $this->image = $image; + } + + /** + * @brief binds manager to an instance of IUserTools (implemented by + * Access). It needs to be assigned first before the manager can be used. + * @param IUserTools + */ + public function setLdapAccess(IUserTools $access) { + $this->access = $access; + } + + /** + * @brief creates an instance of User and caches (just runtime) it in the + * property array + * @param string the DN of the user + * @param string the internal (owncloud) username + * @return \OCA\user_ldap\lib\User + */ + private function createAndCache($dn, $uid) { + $this->checkAccess(); + $user = new User($uid, $dn, $this->access, $this->ocConfig, + $this->ocFilesystem, clone $this->image, $this->ocLog, + $this->avatarManager); + $users['byDN'][$dn] = $user; + $users['byUid'][$uid] = $user; + return $user; + } + + /** + * @brief checks whether the Access instance has been set + * @throws Exception if Access has not been set + * @return null + */ + private function checkAccess() { + if(is_null($this->access)) { + throw new \Exception('LDAP Access instance must be set first'); + } + } + + /** + * @brief returns a User object by it's DN or ownCloud username + * @param string the DN or username of the user + * @return \OCA\user_ldap\lib\User | null + */ + public function get($id) { + $this->checkAccess(); + if(isset($this->users['byDN'][$id])) { + return $this->users['byDN'][$id]; + } else if(isset($this->users['byUid'][$id])) { + return $this->users['byUid'][$id]; + } + + if(strpos(mb_strtolower($id, 'UTF-8'), 'dc=') === false) { + //most likely a uid + $dn = $this->access->username2dn($id); + if($dn !== false) { + return $this->createAndCache($dn, $id); + } + } else { + //so it's a DN + $uid = $this->access->dn2username($id); + if($uid !== false) { + return $this->createAndCache($id, $uid); + } + } + //either funny uid or invalid. Assume funny to be on the safe side. + $dn = $this->access->username2dn($id); + if($dn !== false) { + return $this->createAndCache($dn, $id); + } + return null; + } + +} diff --git a/apps/user_ldap/lib/user/user.php b/apps/user_ldap/lib/user/user.php new file mode 100644 index 0000000000..d4d2294307 --- /dev/null +++ b/apps/user_ldap/lib/user/user.php @@ -0,0 +1,324 @@ +. + * + */ + +namespace OCA\user_ldap\lib\user; + +use OCA\user_ldap\lib\user\IUserTools; +use OCA\user_ldap\lib\Connection; +use OCA\user_ldap\lib\FilesystemHelper; +use OCA\user_ldap\lib\LogWrapper; + +/** + * User + * + * represents an LDAP user, gets and holds user-specific information from LDAP + */ +class User { + /** + * @var IUserTools + */ + protected $access; + /** + * @var Connection + */ + protected $connection; + /** + * @var \OCP\IConfig + */ + protected $config; + /** + * @var FilesystemHelper + */ + protected $fs; + /** + * @var \OCP\Image + */ + protected $image; + /** + * @var LogWrapper + */ + protected $log; + /** + * @var \OCP\IAvatarManager + */ + protected $avatarManager; + + /** + * @var string + */ + protected $dn; + /** + * @var string + */ + protected $uid; + /** + * @var string[] + */ + protected $refreshedFeatures = array(); + /** + * @var string + */ + protected $avatarImage; + + /** + * DB config keys for user preferences + */ + const USER_PREFKEY_FIRSTLOGIN = 'firstLoginAccomplished'; + const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh'; + + /** + * @brief constructor, make sure the subclasses call this one! + * @param string the internal username + * @param string the LDAP DN + * @param IUserTools $access an instance that implements IUserTools for + * LDAP interaction + * @param \OCP\Config + * @param FilesystemHelper + * @param \OCP\Image any empty instance + * @param LogWrapper + * @param \OCP\IAvatarManager + */ + public function __construct($username, $dn, IUserTools $access, + \OCP\IConfig $config, FilesystemHelper $fs, \OCP\Image $image, + LogWrapper $log, \OCP\IAvatarManager $avatarManager) { + + $this->access = $access; + $this->connection = $access->getConnection(); + $this->config = $config; + $this->fs = $fs; + $this->dn = $dn; + $this->uid = $username; + $this->image = $image; + $this->log = $log; + $this->avatarManager = $avatarManager; + } + + /** + * @brief updates properties like email, quota or avatar provided by LDAP + * @return null + */ + public function update() { + if(is_null($this->dn)) { + return null; + } + + $hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap', + self::USER_PREFKEY_FIRSTLOGIN, 0); + + if($this->needsRefresh()) { + $this->updateEmail(); + $this->updateQuota(); + if($hasLoggedIn !== 0) { + //we do not need to try it, when the user has not been logged in + //before, because the file system will not be ready. + $this->updateAvatar(); + //in order to get an avatar as soon as possible, mark the user + //as refreshed only when updating the avatar did happen + $this->markRefreshTime(); + } + } + } + + /** + * @brief returns the LDAP DN of the user + * @return string + */ + public function getDN() { + return $this->dn; + } + + /** + * @brief returns the ownCloud internal username of the user + * @return string + */ + public function getUsername() { + return $this->uid; + } + + /** + * @brief reads the image from LDAP that shall be used as Avatar + * @return string data (provided by LDAP) | false + */ + public function getAvatarImage() { + if(!is_null($this->avatarImage)) { + return $this->avatarImage; + } + + $this->avatarImage = false; + $attributes = array('jpegPhoto', 'thumbnailPhoto'); + foreach($attributes as $attribute) { + $result = $this->access->readAttribute($this->dn, $attribute); + if($result !== false && is_array($result) && isset($result[0])) { + $this->avatarImage = $result[0]; + break; + } + } + + return $this->avatarImage; + } + + /** + * @brief marks the user as having logged in at least once + * @return null + */ + public function markLogin() { + $this->config->setUserValue( + $this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1); + } + + /** + * @brief marks the time when user features like email have been updated + * @return null + */ + private function markRefreshTime() { + $this->config->setUserValue( + $this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time()); + } + + /** + * @brief checks whether user features needs to be updated again by + * comparing the difference of time of the last refresh to now with the + * desired interval + * @return bool + */ + private function needsRefresh() { + $lastChecked = $this->config->getUserValue($this->uid, 'user_ldap', + self::USER_PREFKEY_LASTREFRESH, 0); + + //TODO make interval configurable + if((time() - intval($lastChecked)) < 86400 ) { + return false; + } + return true; + } + + /** + * @brief checks whether an update method specified by feature was run + * already. If not, it will marked like this, because it is expected that + * the method will be run, when false is returned. + * @param string email | quota | avatar (can be extended) + * @return bool + */ + private function wasRefreshed($feature) { + if(isset($this->refreshedFeatures[$feature])) { + return true; + } + $this->refreshedFeatures[$feature] = 1; + return false; + } + + /** + * @brief fetches the email from LDAP and stores it as ownCloud user value + * @return null + */ + public function updateEmail() { + if($this->wasRefreshed('email')) { + return; + } + + $email = null; + $emailAttribute = $this->connection->ldapEmailAttribute; + if(!empty($emailAttribute)) { + $aEmail = $this->access->readAttribute($this->dn, $emailAttribute); + if($aEmail && (count($aEmail) > 0)) { + $email = $aEmail[0]; + } + if(!is_null($email)) { + $this->config->setUserValue( + $this->uid, 'settings', 'email', $email); + } + } + } + + /** + * @brief fetches the quota from LDAP and stores it as ownCloud user value + * @return null + */ + public function updateQuota() { + if($this->wasRefreshed('quota')) { + return; + } + + $quota = null; + $quotaDefault = $this->connection->ldapQuotaDefault; + $quotaAttribute = $this->connection->ldapQuotaAttribute; + if(!empty($quotaDefault)) { + $quota = $quotaDefault; + } + if(!empty($quotaAttribute)) { + $aQuota = $this->access->readAttribute($this->dn, $quotaAttribute); + + if($aQuota && (count($aQuota) > 0)) { + $quota = $aQuota[0]; + } + } + if(!is_null($quota)) { + $this->config->setUserValue($this->uid, 'files', 'quota', $quota); + } + } + + /** + * @brief attempts to get an image from LDAP and sets it as ownCloud avatar + * @return null + */ + public function updateAvatar() { + if($this->wasRefreshed('avatar')) { + return; + } + $avatarImage = $this->getAvatarImage(); + if($avatarImage === false) { + //not set, nothing left to do; + return; + } + $this->image->loadFromBase64(base64_encode($avatarImage)); + $this->setOwnCloudAvatar(); + } + + /** + * @brief sets an image as ownCloud avatar + * @return null + */ + private function setOwnCloudAvatar() { + if(!$this->image->valid()) { + $this->log->log('user_ldap', 'jpegPhoto data invalid for '.$this->dn, + \OCP\Util::ERROR); + return; + } + //make sure it is a square and not bigger than 128x128 + $size = min(array($this->image->width(), $this->image->height(), 128)); + if(!$this->image->centerCrop($size)) { + $this->log->log('user_ldap', + 'croping image for avatar failed for '.$this->dn, + \OCP\Util::ERROR); + return; + } + + if(!$this->fs->isLoaded()) { + $this->fs->setup($this->uid); + } + + $avatar = $this->avatarManager->getAvatar($this->uid); + $avatar->set($this->image); + } + +} diff --git a/apps/user_ldap/tests/access.php b/apps/user_ldap/tests/access.php index 9beb2b9733..8ead5d6848 100644 --- a/apps/user_ldap/tests/access.php +++ b/apps/user_ldap/tests/access.php @@ -30,30 +30,39 @@ class Test_Access extends \PHPUnit_Framework_TestCase { private function getConnecterAndLdapMock() { static $conMethods; static $accMethods; + static $umMethods; if(is_null($conMethods) || is_null($accMethods)) { $conMethods = get_class_methods('\OCA\user_ldap\lib\Connection'); $accMethods = get_class_methods('\OCA\user_ldap\lib\Access'); + $umMethods = get_class_methods('\OCA\user_ldap\lib\user\Manager'); } $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); $connector = $this->getMock('\OCA\user_ldap\lib\Connection', $conMethods, array($lw, null, null)); + $um = $this->getMock('\OCA\user_ldap\lib\user\Manager', + $umMethods, array( + $this->getMock('\OCP\IConfig'), + $this->getMock('\OCA\user_ldap\lib\FilesystemHelper'), + $this->getMock('\OCA\user_ldap\lib\LogWrapper'), + $this->getMock('\OCP\IAvatarManager'), + $this->getMock('\OCP\Image'))); - return array($lw, $connector); + return array($lw, $connector, $um); } public function testEscapeFilterPartValidChars() { - list($lw, $con) = $this->getConnecterAndLdapMock(); - $access = new Access($con, $lw); + list($lw, $con, $um) = $this->getConnecterAndLdapMock(); + $access = new Access($con, $lw, $um); $input = 'okay'; $this->assertTrue($input === $access->escapeFilterPart($input)); } public function testEscapeFilterPartEscapeWildcard() { - list($lw, $con) = $this->getConnecterAndLdapMock(); - $access = new Access($con, $lw); + list($lw, $con, $um) = $this->getConnecterAndLdapMock(); + $access = new Access($con, $lw, $um); $input = '*'; $expected = '\\\\*'; @@ -61,8 +70,8 @@ class Test_Access extends \PHPUnit_Framework_TestCase { } public function testEscapeFilterPartEscapeWildcard2() { - list($lw, $con) = $this->getConnecterAndLdapMock(); - $access = new Access($con, $lw); + list($lw, $con, $um) = $this->getConnecterAndLdapMock(); + $access = new Access($con, $lw, $um); $input = 'foo*bar'; $expected = 'foo\\\\*bar'; diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php index ecbd42319e..1184fe1e82 100644 --- a/apps/user_ldap/tests/group_ldap.php +++ b/apps/user_ldap/tests/group_ldap.php @@ -42,9 +42,16 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase { $connector = $this->getMock('\OCA\user_ldap\lib\Connection', $conMethods, array($lw, null, null)); + $um = new \OCA\user_ldap\lib\user\Manager( + $this->getMock('\OCP\IConfig'), + $this->getMock('\OCA\user_ldap\lib\FilesystemHelper'), + $this->getMock('\OCA\user_ldap\lib\LogWrapper'), + $this->getMock('\OCP\IAvatarManager'), + $this->getMock('\OCP\Image') + ); $access = $this->getMock('\OCA\user_ldap\lib\Access', $accMethods, - array($connector, $lw)); + array($connector, $lw, $um)); return $access; } @@ -112,4 +119,4 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase { $this->assertSame(2, $users); } -} \ No newline at end of file +} diff --git a/apps/user_ldap/tests/user/user.php b/apps/user_ldap/tests/user/user.php new file mode 100644 index 0000000000..b66a923726 --- /dev/null +++ b/apps/user_ldap/tests/user/user.php @@ -0,0 +1,680 @@ +. +* +*/ + +namespace OCA\user_ldap\tests; + +use OCA\user_ldap\lib\user\User; + +class Test_User_User extends \PHPUnit_Framework_TestCase { + + private function getTestInstances() { + $access = $this->getMock('\OCA\user_ldap\lib\user\IUserTools'); + $config = $this->getMock('\OCP\IConfig'); + $filesys = $this->getMock('\OCA\user_ldap\lib\FilesystemHelper'); + $log = $this->getMock('\OCA\user_ldap\lib\LogWrapper'); + $avaMgr = $this->getMock('\OCP\IAvatarManager'); + $image = $this->getMock('\OCP\Image'); + + return array($access, $config, $filesys, $image, $log, $avaMgr); + } + + private function getAdvancedMocks($cfMock, $fsMock, $logMock, $avaMgr) { + static $conMethods; + static $accMethods; + static $umMethods; + + if(is_null($conMethods) || is_null($accMethods)) { + $conMethods = get_class_methods('\OCA\user_ldap\lib\Connection'); + $accMethods = get_class_methods('\OCA\user_ldap\lib\Access'); + //getConnection shall not be replaced + unset($accMethods[array_search('getConnection', $accMethods)]); + $umMethods = get_class_methods('\OCA\user_ldap\lib\user\Manager'); + } + $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); + $im = $this->getMock('\OCP\Image'); + $um = $this->getMock('\OCA\user_ldap\lib\user\Manager', + $umMethods, array($cfMock, $fsMock, $logMock, $avaMgr, $im)); + $connector = $this->getMock('\OCA\user_ldap\lib\Connection', + $conMethods, array($lw, null, null)); + $access = $this->getMock('\OCA\user_ldap\lib\Access', + $accMethods, array($connector, $lw, $um)); + + return array($access, $connector); + } + + public function testGetDNandUsername() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $this->assertSame($dn, $user->getDN()); + $this->assertSame($uid, $user->getUsername()); + } + + public function testUpdateEmailProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->once()) + ->method('__get') + ->with($this->equalTo('ldapEmailAttribute')) + ->will($this->returnValue('email')); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('email')) + ->will($this->returnValue(array('alice@foo.bar'))); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), $this->equalTo('settings'), + $this->equalTo('email'), + $this->equalTo('alice@foo.bar')) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateEmail(); + } + + public function testUpdateEmailNotProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->once()) + ->method('__get') + ->with($this->equalTo('ldapEmailAttribute')) + ->will($this->returnValue('email')); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('email')) + ->will($this->returnValue(false)); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateEmail(); + } + + public function testUpdateEmailNotConfigured() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->once()) + ->method('__get') + ->with($this->equalTo('ldapEmailAttribute')) + ->will($this->returnValue('')); + + $access->expects($this->never()) + ->method('readAttribute'); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateEmail(); + } + + public function testUpdateQuotaAllProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('23 GB')); + + $connection->expects($this->at(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaAttribute')) + ->will($this->returnValue('myquota')); + + $connection->expects($this->exactly(2)) + ->method('__get'); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('myquota')) + ->will($this->returnValue(array('42 GB'))); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), + $this->equalTo('files'), + $this->equalTo('quota'), + $this->equalTo('42 GB')) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota(); + } + + public function testUpdateQuotaDefaultProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('23 GB')); + + $connection->expects($this->at(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaAttribute')) + ->will($this->returnValue('myquota')); + + $connection->expects($this->exactly(2)) + ->method('__get'); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('myquota')) + ->will($this->returnValue(false)); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), + $this->equalTo('files'), + $this->equalTo('quota'), + $this->equalTo('23 GB')) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota(); + } + + public function testUpdateQuotaIndividualProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('')); + + $connection->expects($this->at(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaAttribute')) + ->will($this->returnValue('myquota')); + + $connection->expects($this->exactly(2)) + ->method('__get'); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('myquota')) + ->will($this->returnValue(array('23 GB'))); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), + $this->equalTo('files'), + $this->equalTo('quota'), + $this->equalTo('23 GB')) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota(); + } + + public function testUpdateQuotaNoneProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('')); + + $connection->expects($this->at(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaAttribute')) + ->will($this->returnValue('myquota')); + + $connection->expects($this->exactly(2)) + ->method('__get'); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('myquota')) + ->will($this->returnValue(false)); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota(); + } + + public function testUpdateQuotaNoneConfigured() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('')); + + $connection->expects($this->at(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaAttribute')) + ->will($this->returnValue('')); + + $connection->expects($this->exactly(2)) + ->method('__get'); + + $access->expects($this->never()) + ->method('readAttribute'); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota(); + } + + //the testUpdateAvatar series also implicitely tests getAvatarImage + public function testUpdateAvatarJpegPhotoProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('jpegPhoto')) + ->will($this->returnValue(array('this is a photo'))); + + $image->expects($this->once()) + ->method('valid') + ->will($this->returnValue(true)); + $image->expects($this->once()) + ->method('width') + ->will($this->returnValue(128)); + $image->expects($this->once()) + ->method('height') + ->will($this->returnValue(128)); + $image->expects($this->once()) + ->method('centerCrop') + ->will($this->returnValue(true)); + + $filesys->expects($this->once()) + ->method('isLoaded') + ->will($this->returnValue(true)); + + $avatar = $this->getMock('\OCP\IAvatar'); + $avatar->expects($this->once()) + ->method('set') + ->with($this->isInstanceOf($image)); + + $avaMgr->expects($this->once()) + ->method('getAvatar') + ->with($this->equalTo('alice')) + ->will($this->returnValue($avatar)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateAvatar(); + } + + public function testUpdateAvatarThumbnailPhotoProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $access->expects($this->at(0)) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('jpegPhoto')) + ->will($this->returnValue(false)); + + $access->expects($this->at(1)) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('thumbnailPhoto')) + ->will($this->returnValue(array('this is a photo'))); + + $access->expects($this->exactly(2)) + ->method('readAttribute'); + + $image->expects($this->once()) + ->method('valid') + ->will($this->returnValue(true)); + $image->expects($this->once()) + ->method('width') + ->will($this->returnValue(128)); + $image->expects($this->once()) + ->method('height') + ->will($this->returnValue(128)); + $image->expects($this->once()) + ->method('centerCrop') + ->will($this->returnValue(true)); + + $filesys->expects($this->once()) + ->method('isLoaded') + ->will($this->returnValue(true)); + + $avatar = $this->getMock('\OCP\IAvatar'); + $avatar->expects($this->once()) + ->method('set') + ->with($this->isInstanceOf($image)); + + $avaMgr->expects($this->once()) + ->method('getAvatar') + ->with($this->equalTo('alice')) + ->will($this->returnValue($avatar)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateAvatar(); + } + + public function testUpdateAvatarNotProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $access->expects($this->at(0)) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('jpegPhoto')) + ->will($this->returnValue(false)); + + $access->expects($this->at(1)) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('thumbnailPhoto')) + ->will($this->returnValue(false)); + + $access->expects($this->exactly(2)) + ->method('readAttribute'); + + $image->expects($this->never()) + ->method('valid'); + $image->expects($this->never()) + ->method('width'); + $image->expects($this->never()) + ->method('height'); + $image->expects($this->never()) + ->method('centerCrop'); + + $filesys->expects($this->never()) + ->method('isLoaded'); + + $avaMgr->expects($this->never()) + ->method('getAvatar'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateAvatar(); + } + + public function testUpdateBeforeFirstLogin() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $config->expects($this->at(0)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), + $this->equalTo(0)) + ->will($this->returnValue(0)); + + $config->expects($this->at(1)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_LASTREFRESH), + $this->equalTo(0)) + ->will($this->returnValue(0)); + + $config->expects($this->exactly(2)) + ->method('getUserValue'); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->update(); + } + + public function testUpdateAfterFirstLogin() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $config->expects($this->at(0)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), + $this->equalTo(0)) + ->will($this->returnValue(1)); + + $config->expects($this->at(1)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_LASTREFRESH), + $this->equalTo(0)) + ->will($this->returnValue(0)); + + $config->expects($this->exactly(2)) + ->method('getUserValue'); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_LASTREFRESH), + $this->anything()) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->update(); + } + + public function testUpdateNoRefresh() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr); + + $config->expects($this->at(0)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), + $this->equalTo(0)) + ->will($this->returnValue(1)); + + $config->expects($this->at(1)) + ->method('getUserValue') + ->with($this->equalTo('alice'), $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_LASTREFRESH), + $this->equalTo(0)) + ->will($this->returnValue(time())); + + $config->expects($this->exactly(2)) + ->method('getUserValue'); + + $config->expects($this->never()) + ->method('setUserValue'); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->update(); + } + + public function testMarkLogin() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), + $this->equalTo('user_ldap'), + $this->equalTo(User::USER_PREFKEY_FIRSTLOGIN), + $this->equalTo(1)) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->markLogin(); + } + + public function testGetAvatarImageProvided() { + list($access, $config, $filesys, $image, $log, $avaMgr) = + $this->getTestInstances(); + + $access->expects($this->once()) + ->method('readAttribute') + ->with($this->equalTo('uid=alice,dc=foo,dc=bar'), + $this->equalTo('jpegPhoto')) + ->will($this->returnValue(array('this is a photo'))); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $photo = $user->getAvatarImage(); + $this->assertSame('this is a photo', $photo); + //make sure readAttribute is not called again but the already fetched + //photo is returned + $photo = $user->getAvatarImage(); + } +} diff --git a/apps/user_ldap/tests/user_ldap.php b/apps/user_ldap/tests/user_ldap.php index 2535c34bcf..8787e02365 100644 --- a/apps/user_ldap/tests/user_ldap.php +++ b/apps/user_ldap/tests/user_ldap.php @@ -29,6 +29,7 @@ use \OCA\user_ldap\lib\ILDAPWrapper; class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { protected $backend; + protected $access; public function setUp() { \OC_User::clearBackends(); @@ -38,18 +39,35 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { private function getAccessMock() { static $conMethods; static $accMethods; + static $uMethods; if(is_null($conMethods) || is_null($accMethods)) { $conMethods = get_class_methods('\OCA\user_ldap\lib\Connection'); $accMethods = get_class_methods('\OCA\user_ldap\lib\Access'); + unset($accMethods[array_search('getConnection', $accMethods)]); + $uMethods = get_class_methods('\OCA\user_ldap\lib\user\User'); + unset($uMethods[array_search('getUsername', $uMethods)]); + unset($uMethods[array_search('getDN', $uMethods)]); + unset($uMethods[array_search('__construct', $uMethods)]); } $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); $connector = $this->getMock('\OCA\user_ldap\lib\Connection', $conMethods, array($lw, null, null)); + + $um = new \OCA\user_ldap\lib\user\Manager( + $this->getMock('\OCP\IConfig'), + $this->getMock('\OCA\user_ldap\lib\FilesystemHelper'), + $this->getMock('\OCA\user_ldap\lib\LogWrapper'), + $this->getMock('\OCP\IAvatarManager'), + $this->getMock('\OCP\Image') + ); + $access = $this->getMock('\OCA\user_ldap\lib\Access', $accMethods, - array($connector, $lw)); + array($connector, $lw, $um)); + + $um->setLdapAccess($access); return $access; } @@ -60,16 +78,16 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { ->will($this->returnCallback(function($uid) { switch ($uid) { case 'gunslinger': - return 'dnOfRoland'; + return 'dnOfRoland,dc=test'; break; case 'formerUser': - return 'dnOfFormerUser'; + return 'dnOfFormerUser,dc=test'; break; case 'newyorker': - return 'dnOfNewYorker'; + return 'dnOfNewYorker,dc=test'; break; case 'ladyofshadows': - return 'dnOfLadyOfShadows'; + return 'dnOfLadyOfShadows,dc=test'; break; default: return false; @@ -102,14 +120,14 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { ->method('fetchListOfUsers') ->will($this->returnCallback(function($filter) { if($filter === 'roland') { - return array('dnOfRoland'); + return array('dnOfRoland,dc=test'); } return array(); })); $access->expects($this->any()) ->method('dn2username') - ->with($this->equalTo('dnOfRoland')) + ->with($this->equalTo('dnOfRoland,dc=test')) ->will($this->returnValue('gunslinger')); $access->expects($this->any()) @@ -337,7 +355,7 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { $access->expects($this->any()) ->method('readAttribute') ->will($this->returnCallback(function($dn) { - if($dn === 'dnOfRoland') { + if($dn === 'dnOfRoland,dc=test') { return array(); } return false; @@ -365,7 +383,7 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { $access->expects($this->any()) ->method('readAttribute') ->will($this->returnCallback(function($dn) { - if($dn === 'dnOfRoland') { + if($dn === 'dnOfRoland,dc=test') { return array(); } return false; @@ -411,13 +429,13 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { ->method('readAttribute') ->will($this->returnCallback(function($dn, $attr) { switch ($dn) { - case 'dnOfRoland': + case 'dnOfRoland,dc=test': if($attr === 'testAttribute') { return array('/tmp/rolandshome/'); } return array(); break; - case 'dnOfLadyOfShadows': + case 'dnOfLadyOfShadows,dc=test': if($attr === 'testAttribute') { return array('susannah/'); } @@ -457,7 +475,7 @@ class Test_User_Ldap_Direct extends \PHPUnit_Framework_TestCase { ->method('readAttribute') ->will($this->returnCallback(function($dn, $attr) { switch ($dn) { - case 'dnOfRoland': + case 'dnOfRoland,dc=test': if($attr === 'displayname') { return array('Roland Deschain'); } diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index aece2ee9aa..9fa2a6b418 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -28,128 +28,19 @@ namespace OCA\user_ldap; use OCA\user_ldap\lib\BackendUtility; class USER_LDAP extends BackendUtility implements \OCP\UserInterface { - - private function updateQuota($dn) { - $quota = null; - $quotaDefault = $this->access->connection->ldapQuotaDefault; - $quotaAttribute = $this->access->connection->ldapQuotaAttribute; - if(!empty($quotaDefault)) { - $quota = $quotaDefault; - } - if(!empty($quotaAttribute)) { - $aQuota = $this->access->readAttribute($dn, $quotaAttribute); - - if($aQuota && (count($aQuota) > 0)) { - $quota = $aQuota[0]; - } - } - if(!is_null($quota)) { - \OCP\Config::setUserValue( $this->access->dn2username($dn), - 'files', - 'quota', - \OCP\Util::computerFileSize($quota)); - } - } - - private function updateEmail($dn) { - $email = null; - $emailAttribute = $this->access->connection->ldapEmailAttribute; - if(!empty($emailAttribute)) { - $aEmail = $this->access->readAttribute($dn, $emailAttribute); - if($aEmail && (count($aEmail) > 0)) { - $email = $aEmail[0]; - } - if(!is_null($email)) { - \OCP\Config::setUserValue( $this->access->dn2username($dn), - 'settings', - 'email', - $email); - } - } - } - - /** - * reads jpegPhoto and set is as avatar if available - * @param string $uid ownCloud user name - * @param string $dn the user's LDAP DN - * @return void - */ - private function updateAvatar($uid, $dn) { - $hasLoggedIn = \OCP\Config::getUserValue($uid, 'user_ldap', - 'firstLoginAccomplished', 0); - $lastChecked = \OCP\Config::getUserValue($uid, 'user_ldap', - 'lastJpegPhotoLookup', 0); - if(($hasLoggedIn !== '1') || (time() - intval($lastChecked)) < 86400 ) { - //update only once a day - return; - } - - $avatarImage = $this->getAvatarImage($uid, $dn); - if($avatarImage === false) { - //not set, nothing left to do; - return; - } - - $image = new \OCP\Image(); - $image->loadFromBase64(base64_encode($avatarImage)); - - if(!$image->valid()) { - \OCP\Util::writeLog('user_ldap', 'jpegPhoto data invalid for '.$dn, - \OCP\Util::ERROR); - return; - } - //make sure it is a square and not bigger than 128x128 - $size = min(array($image->width(), $image->height(), 128)); - if(!$image->centerCrop($size)) { - \OCP\Util::writeLog('user_ldap', - 'croping image for avatar failed for '.$dn, - \OCP\Util::ERROR); - return; - } - - if(!\OC\Files\Filesystem::$loaded) { - \OC_Util::setupFS($uid); - } - - $avatarManager = \OC::$server->getAvatarManager(); - $avatar = $avatarManager->getAvatar($uid); - $avatar->set($image); - } - /** * checks whether the user is allowed to change his avatar in ownCloud * @param string $uid the ownCloud user name * @return boolean either the user can or cannot */ public function canChangeAvatar($uid) { - $dn = $this->access->username2dn($uid); - if(!$dn) { + $user = $this->access->userManager->get($uid); + if(is_null($user)) { return false; } - if($this->getAvatarImage($uid, $dn) === false) { - //The user is allowed to change his avatar in ownCloud only if no - //avatar is provided by LDAP + if($user->getAvatarImage() === false) { return true; } - return false; - } - - /** - * reads the image from LDAP that shall be used as Avatar - * @param string $uid the ownCloud user name - * @param string $dn the user DN - * @return string data (provided by LDAP) | false - */ - private function getAvatarImage($uid, $dn) { - $attributes = array('jpegPhoto', 'thumbnailPhoto'); - foreach($attributes as $attribute) { - $result = $this->access->readAttribute($dn, $attribute); - \OCP\Config::setUserValue($uid, 'user_ldap', 'lastJpegPhotoLookup', - time()); - if($result !== false && is_array($result) && isset($result[0])) { - return $result[0]; - } - } return false; } @@ -174,25 +65,17 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { } $dn = $ldap_users[0]; - //do we have a username for him/her? - $ocname = $this->access->dn2username($dn); - - if($ocname) { - //update some settings, if necessary - $this->updateQuota($dn); - $this->updateEmail($dn); - + $user = $this->access->userManager->get($dn); + if($user->getUsername() !== false) { //are the credentials OK? if(!$this->access->areCredentialsValid($dn, $password)) { return false; } - \OCP\Config::setUserValue($ocname, 'user_ldap', - 'firstLoginAccomplished', 1); + $user->markLogin(); + $user->update(); - $this->updateAvatar($ocname, $dn); - //give back the display name - return $ocname; + return $user->getUsername(); } return false; @@ -249,13 +132,14 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { return $this->access->connection->getFromCache('userExists'.$uid); } //getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking. - $dn = $this->access->username2dn($uid); - if(!$dn) { + $user = $this->access->userManager->get($uid); + if(is_null($user)) { \OCP\Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '. $this->access->connection->ldapHost, \OCP\Util::DEBUG); $this->access->connection->writeToCache('userExists'.$uid, false); return false; } + $dn = $user->getDN(); //check if user really still exists by reading its entry if(!is_array($this->access->readAttribute($dn, ''))) { \OCP\Util::writeLog('user_ldap', 'LDAP says no user '.$dn.' on '. @@ -265,8 +149,7 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { } $this->access->connection->writeToCache('userExists'.$uid, true); - $this->updateQuota($dn); - $this->updateAvatar($uid, $dn); + $user->update(); return true; }