From 955bda1842986a6737c8d3b575b0cd3bb5a0e17d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 28 May 2013 23:46:57 +0200 Subject: [PATCH 01/22] New user management classes --- lib/user/backend.php | 22 +-- lib/user/dummy.php | 144 +++++++------- lib/user/manager.php | 189 +++++++++++++++++++ lib/user/session.php | 161 ++++++++++++++++ lib/user/user.php | 177 ++++++++++++++++++ tests/lib/user/backend.php | 99 ++++++++++ tests/lib/user/database.php | 44 +++++ tests/lib/user/dummy.php | 27 +++ tests/lib/user/manager.php | 304 ++++++++++++++++++++++++++++++ tests/lib/user/session.php | 155 +++++++++++++++ tests/lib/user/user.php | 364 ++++++++++++++++++++++++++++++++++++ 11 files changed, 1605 insertions(+), 81 deletions(-) create mode 100644 lib/user/manager.php create mode 100644 lib/user/session.php create mode 100644 lib/user/user.php create mode 100644 tests/lib/user/backend.php create mode 100644 tests/lib/user/database.php create mode 100644 tests/lib/user/dummy.php create mode 100644 tests/lib/user/manager.php create mode 100644 tests/lib/user/session.php create mode 100644 tests/lib/user/user.php diff --git a/lib/user/backend.php b/lib/user/backend.php index 93e8f17ca98..e9be08e429c 100644 --- a/lib/user/backend.php +++ b/lib/user/backend.php @@ -58,7 +58,7 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief Get all supported actions - * @returns bitwise-or'ed actions + * @return int bitwise-or'ed actions * * Returns the supported actions as int to be * compared with OC_USER_BACKEND_CREATE_USER etc. @@ -76,8 +76,8 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief Check if backend implements actions - * @param $actions bitwise-or'ed actions - * @returns boolean + * @param int $actions bitwise-or'ed actions + * @return boolean * * Returns the supported actions as int to be * compared with OC_USER_BACKEND_CREATE_USER etc. @@ -87,12 +87,12 @@ abstract class OC_User_Backend implements OC_User_Interface { } /** - * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false - * - * Deletes a user - */ + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ public function deleteUser( $uid ) { return false; } @@ -127,8 +127,8 @@ abstract class OC_User_Backend implements OC_User_Interface { /** * @brief get display name of the user - * @param $uid user ID of the user - * @return display name + * @param string $uid user ID of the user + * @return string display name */ public function getDisplayName($uid) { return $uid; diff --git a/lib/user/dummy.php b/lib/user/dummy.php index d63f60efbeb..b5b7a6c3c7a 100644 --- a/lib/user/dummy.php +++ b/lib/user/dummy.php @@ -1,114 +1,118 @@ . -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ /** * dummy user backend, does not keep state, only for testing use */ class OC_User_Dummy extends OC_User_Backend { - private $users=array(); + private $users = array(); + /** - * @brief Create a new user - * @param $uid The username of the user to create - * @param $password The password of the new user - * @returns true/false - * - * Creates a new user. Basic checking of username is done in OC_User - * itself, not in its subclasses. - */ + * @brief Create a new user + * @param string $uid The username of the user to create + * @param string $password The password of the new user + * @return bool + * + * Creates a new user. Basic checking of username is done in OC_User + * itself, not in its subclasses. + */ public function createUser($uid, $password) { - if(isset($this->users[$uid])) { + if (isset($this->users[$uid])) { return false; - }else{ - $this->users[$uid]=$password; + } else { + $this->users[$uid] = $password; return true; } } /** - * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false - * - * Deletes a user - */ - public function deleteUser( $uid ) { - if(isset($this->users[$uid])) { + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ + public function deleteUser($uid) { + if (isset($this->users[$uid])) { unset($this->users[$uid]); return true; - }else{ + } else { return false; } } /** - * @brief Set password - * @param $uid The username - * @param $password The new password - * @returns true/false - * - * Change the password of a user - */ + * @brief 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) { - if(isset($this->users[$uid])) { - $this->users[$uid]=$password; + if (isset($this->users[$uid])) { + $this->users[$uid] = $password; return true; - }else{ + } else { return false; } } /** - * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns string - * - * Check if the password is correct without logging in the user - * returns the user id or false - */ + * @brief Check if the password is correct + * @param string $uid The username + * @param string $password The password + * @return string + * + * Check if the password is correct without logging in the user + * returns the user id or false + */ public function checkPassword($uid, $password) { - if(isset($this->users[$uid])) { - return ($this->users[$uid]==$password); - }else{ + if (isset($this->users[$uid])) { + return ($this->users[$uid] == $password); + } else { return false; } } /** - * @brief Get a list of all users - * @returns array with all uids - * - * Get a list of all users. - */ + * @brief Get a list of all users + * @param string $search + * @param int $limit + * @param int $offset + * @return array with all uids + * + * Get a list of all users. + */ public function getUsers($search = '', $limit = null, $offset = null) { return array_keys($this->users); } /** - * @brief check if a user exists - * @param string $uid the username - * @return boolean - */ + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ public function userExists($uid) { return isset($this->users[$uid]); } diff --git a/lib/user/manager.php b/lib/user/manager.php new file mode 100644 index 00000000000..25e67ca36b5 --- /dev/null +++ b/lib/user/manager.php @@ -0,0 +1,189 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\User; + +use OC\Hooks\PublicEmitter; + +/** + * Class Manager + * + * Hooks available in scope \OC\User: + * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - preDelete(\OC\User\User $user) + * - postDelete(\OC\User\User $user) + * - preCreateUser(string $uid, string $password) + * - postCreateUser(\OC\User\User $user) + * + * @package OC\User + */ +class Manager extends PublicEmitter { + /** + * @var \OC_User_Backend[] $backends + */ + private $backends = array(); + + /** + * @param \OC_User_Backend $backend + */ + public function registerBackend($backend) { + $this->backends[] = $backend; + } + + /** + * @param \OC_User_Backend $backend + */ + public function removeBackend($backend) { + if (($i = array_search($backend, $this->backends)) !== false) { + unset($this->backends[$i]); + } + } + + public function clearBackends() { + $this->backends = array(); + } + + /** + * @param string $uid + * @return \OC\User\User + */ + public function get($uid) { + foreach ($this->backends as $backend) { + if ($backend->userExists($uid)) { + return new User($uid, $backend); + } + } + return null; + } + + /** + * @param string $uid + * @return bool + */ + public function userExists($uid) { + foreach ($this->backends as $backend) { + if ($backend->userExists($uid)) { + return true; + } + } + return false; + } + + /** + * search by user id + * + * @param string $pattern + * @param int $limit + * @param int $offset + * @return \OC\User\User[] + */ + public function search($pattern, $limit = null, $offset = null) { + $users = array(); + foreach ($this->backends as $backend) { + $backendUsers = $backend->getUsers($pattern, $limit, $offset); + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid) { + $users[] = new User($uid, $backend); + if (!is_null($limit)) { + $limit--; + } + if (!is_null($offset) and $offset > 0) { + $offset--; + } + + } + } + } + + usort($users, function ($a, $b) { + /** + * @var \OC\User\User $a + * @var \OC\User\User $b + */ + return strcmp($a->getUID(), $b->getUID()); + }); + return $users; + } + + /** + * search by displayName + * + * @param string $pattern + * @param int $limit + * @param int $offset + * @return \OC\User\User[] + */ + public function searchDisplayName($pattern, $limit = null, $offset = null) { + $users = array(); + foreach ($this->backends as $backend) { + $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); + if (is_array($backendUsers)) { + foreach ($backendUsers as $uid => $displayName) { + $users[] = new User($uid, $backend); + if (!is_null($limit)) { + $limit--; + } + if (!is_null($offset) and $offset > 0) { + $offset--; + } + + } + } + } + + usort($users, function ($a, $b) { + /** + * @var \OC\User\User $a + * @var \OC\User\User $b + */ + return strcmp($a->getDisplayName(), $b->getDisplayName()); + }); + return $users; + } + + /** + * @param string $uid + * @param string $password + * @throws \Exception + * @return bool | \OC\User\User the created user of false + */ + public function createUser($uid, $password) { + // Check the name for bad characters + // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" + if (preg_match('/[^a-zA-Z0-9 _\.@\-]/', $uid)) { + throw new \Exception('Only the following characters are allowed in a username:' + . ' "a-z", "A-Z", "0-9", and "_.@-"'); + } + // No empty username + if (trim($uid) == '') { + throw new \Exception('A valid username must be provided'); + } + // No empty password + if (trim($password) == '') { + throw new \Exception('A valid password must be provided'); + } + + // Check if user already exists + if ($this->userExists($uid)) { + throw new \Exception('The username is already being used'); + } + + $this->emit('\OC\User', 'preCreateUser', array($uid, $password)); + foreach ($this->backends as $backend) { + if ($backend->implementsActions(\OC_USER_BACKEND_CREATE_USER)) { + $backend->createUser($uid, $password); + $user = new User($uid, $backend); + $this->emit('\OC\User', 'postCreateUser', array($user)); + return $user; + } + } + return false; + } +} diff --git a/lib/user/session.php b/lib/user/session.php new file mode 100644 index 00000000000..b0fdcd3e850 --- /dev/null +++ b/lib/user/session.php @@ -0,0 +1,161 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\User; + +use OC\Hooks\Emitter; + +/** + * Class Session + * + * Hooks available in scope \OC\User: + * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword) + * - preDelete(\OC\User\User $user) + * - postDelete(\OC\User\User $user) + * - preCreateUser(string $uid, string $password) + * - postCreateUser(\OC\User\User $user) + * - preLogin(string $user, string $password) + * - postLogin(\OC\User\User $user) + * - logout() + * + * @package OC\User + */ +class Session implements Emitter { + /** + * @var \OC\User\Manager $manager + */ + private $manager; + + /** + * @var \OC\Session\Session $session + */ + private $session; + + /** + * @var \OC\User\User $activeUser + */ + protected $activeUser; + + /** + * @param \OC\User\Manager $manager + * @param \OC\Session\Session $session + */ + public function __construct($manager, $session) { + $this->manager = $manager; + $this->session = $session; + } + + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, $callback) { + $this->manager->listen($scope, $method, $callback); + } + + /** + * @param string $scope optional + * @param string $method optional + * @param callable $callback optional + */ + public function removeListener($scope = null, $method = null, $callback = null) { + $this->manager->removeListener($scope, $method, $callback); + } + + /** + * @return \OC\User\Manager + */ + public function getManager() { + return $this->manager; + } + + /** + * set the currently active user + * + * @param \OC\User\User $user + */ + public function setUser($user) { + if (is_null($user)) { + $this->session->remove('user_id'); + } else { + $this->session->set('user_id', $user->getUID()); + } + $this->activeUser = $user; + } + + /** + * get the current active user + * + * @return \OC\User\User + */ + public function getUser() { + if ($this->activeUser) { + return $this->activeUser; + } else { + $uid = $this->session->get('user_id'); + if ($uid) { + $this->activeUser = $this->manager->get($uid); + return $this->activeUser; + } else { + return null; + } + } + } + + public function login($uid, $password) { + $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); + $user = $this->manager->get($uid); + if ($user) { + $result = $user->checkPassword($password); + if ($result and $user->isEnabled()) { + $this->manager->emit('\OC\User', 'postLogin', array($user)); + $this->setUser($user); + return true; + } else { + return false; + } + } else { + return false; + } + } + + public function logout() { + $this->manager->emit('\OC\User', 'logout'); + $this->setUser(null); + $this->unsetMagicInCookie(); + } + + /** + * Set cookie value to use in next page load + * + * @param string $username username to be set + * @param string $token + */ + public function setMagicInCookie($username, $token) { + $secure_cookie = \OC_Config::getValue("forcessl", false); //TODO: DI for cookies and OC_Config + $expires = time() + \OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); + setcookie("oc_username", $username, $expires, OC::$WEBROOT, '', $secure_cookie); + setcookie("oc_token", $token, $expires, OC::$WEBROOT, '', $secure_cookie, true); + setcookie("oc_remember_login", true, $expires, OC::$WEBROOT, '', $secure_cookie); + } + + /** + * @brief Remove cookie for "remember username" + */ + public function unsetMagicInCookie() { + unset($_COOKIE["oc_username"]); //TODO: DI + unset($_COOKIE["oc_token"]); + unset($_COOKIE["oc_remember_login"]); + setcookie("oc_username", null, -1); + setcookie("oc_token", null, -1); + setcookie("oc_remember_login", null, -1); + } +} diff --git a/lib/user/user.php b/lib/user/user.php new file mode 100644 index 00000000000..095c37939a7 --- /dev/null +++ b/lib/user/user.php @@ -0,0 +1,177 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\User; + +use OC\Hooks\Emitter; + +class User { + /** + * @var string $uid + */ + private $uid; + + /** + * @var string $displayName + */ + private $displayName; + + /** + * @var \OC_User_Backend $backend + */ + private $backend; + + /** + * @var bool $enabled + */ + private $enabled; + + /** + * @var Emitter | Manager $emitter + */ + private $emitter; + + /** + * @param string $uid + * @param \OC_User_Backend $backend + * @param Emitter $emitter + */ + public function __construct($uid, $backend, $emitter = null) { + $this->uid = $uid; + if ($backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) { + $this->displayName = $backend->getDisplayName($uid); + } else { + $this->displayName = $uid; + } + $this->backend = $backend; + $this->emitter = $emitter; + $enabled = \OC_Preferences::getValue($uid, 'core', 'enabled', 'true'); //TODO: DI for OC_Preferences + $this->enabled = ($enabled === 'true'); + } + + /** + * @return string + */ + public function getUID() { + return $this->uid; + } + + /** + * @return string + */ + public function getDisplayName() { + return $this->displayName; + } + + /** + * @param string $displayName + * @return bool + */ + public function setDisplayName($displayName) { + if ($this->canChangeDisplayName()) { + $this->displayName = $displayName; + $this->backend->setDisplayName($this->uid, $displayName); + return true; + } else { + return false; + } + } + + /** + * @return bool + */ + public function delete() { + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'preDelete', array($this)); + } + $result = $this->backend->deleteUser($this->uid); + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'postDelete', array($this)); + } + return !($result === false); + } + + /** + * @param $password + * @return bool + */ + public function checkPassword($password) { + if ($this->backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) { + $result = $this->backend->checkPassword($this->uid, $password); + if ($result !== false) { + $this->uid = $result; + } + return !($result === false); + } else { + return false; + } + } + + /** + * @param string $password + * @param string $recoveryPassword for the encryption app to reset encryption keys + * @return bool + */ + public function setPassword($password, $recoveryPassword) { + if ($this->backend->implementsActions(\OC_USER_BACKEND_SET_PASSWORD)) { + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword)); + } + $result = $this->backend->setPassword($this->uid, $password); + if ($this->emitter) { + $this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword)); + } + return !($result === false); + } else { + return false; + } + } + + /** + * get the users home folder to mount + * + * @return string + */ + public function getHome() { + if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME)) { + return $this->backend->getHome($this->uid); + } + return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented + } + + /** + * @return bool + */ + public function canChangePassword() { + return $this->backend->implementsActions(\OC_USER_BACKEND_SET_PASSWORD); + } + + /** + * @return bool + */ + public function canChangeDisplayName() { + return $this->backend->implementsActions(\OC_USER_BACKEND_SET_DISPLAYNAME); + } + + /** + * @return bool + */ + public function isEnabled() { + return $this->enabled; + } + + /** + * @param bool $enabled + */ + public function setEnabled($enabled) { + $this->enabled = $enabled; + $enabled = ($enabled) ? 'true' : 'false'; + \OC_Preferences::setValue($this->uid, 'core', 'enabled', $enabled); + } +} diff --git a/tests/lib/user/backend.php b/tests/lib/user/backend.php new file mode 100644 index 00000000000..40674424c96 --- /dev/null +++ b/tests/lib/user/backend.php @@ -0,0 +1,99 @@ +. +* +*/ + +/** + * Abstract class to provide the basis of backend-specific unit test classes. + * + * All subclasses MUST assign a backend property in setUp() which implements + * user operations (add, remove, etc.). Test methods in this class will then be + * run on each separate subclass and backend therein. + * + * For an example see /tests/lib/user/dummy.php + */ + +abstract class Test_User_Backend extends PHPUnit_Framework_TestCase { + /** + * @var OC_User_Backend $backend + */ + protected $backend; + + /** + * get a new unique user name + * test cases can override this in order to clean up created user + * @return array + */ + public function getUser() { + return uniqid('test_'); + } + + public function testAddRemove() { + //get the number of groups we start with, in case there are exising groups + $startCount=count($this->backend->getUsers()); + + $name1=$this->getUser(); + $name2=$this->getUser(); + $this->backend->createUser($name1, ''); + $count=count($this->backend->getUsers())-$startCount; + $this->assertEquals(1, $count); + $this->assertTrue((array_search($name1, $this->backend->getUsers())!==false)); + $this->assertFalse((array_search($name2, $this->backend->getUsers())!==false)); + $this->backend->createUser($name2, ''); + $count=count($this->backend->getUsers())-$startCount; + $this->assertEquals(2, $count); + $this->assertTrue((array_search($name1, $this->backend->getUsers())!==false)); + $this->assertTrue((array_search($name2, $this->backend->getUsers())!==false)); + + $this->backend->deleteUser($name2); + $count=count($this->backend->getUsers())-$startCount; + $this->assertEquals(1, $count); + $this->assertTrue((array_search($name1, $this->backend->getUsers())!==false)); + $this->assertFalse((array_search($name2, $this->backend->getUsers())!==false)); + } + + public function testLogin() { + $name1=$this->getUser(); + $name2=$this->getUser(); + + $this->assertFalse($this->backend->userExists($name1)); + $this->assertFalse($this->backend->userExists($name2)); + + $this->backend->createUser($name1, 'pass1'); + $this->backend->createUser($name2, 'pass2'); + + $this->assertTrue($this->backend->userExists($name1)); + $this->assertTrue($this->backend->userExists($name2)); + + $this->assertTrue($this->backend->checkPassword($name1, 'pass1')); + $this->assertTrue($this->backend->checkPassword($name2, 'pass2')); + + $this->assertFalse($this->backend->checkPassword($name1, 'pass2')); + $this->assertFalse($this->backend->checkPassword($name2, 'pass1')); + + $this->assertFalse($this->backend->checkPassword($name1, 'dummy')); + $this->assertFalse($this->backend->checkPassword($name2, 'foobar')); + + $this->backend->setPassword($name1, 'newpass1'); + $this->assertFalse($this->backend->checkPassword($name1, 'pass1')); + $this->assertTrue($this->backend->checkPassword($name1, 'newpass1')); + $this->assertFalse($this->backend->checkPassword($name2, 'newpass1')); + } +} diff --git a/tests/lib/user/database.php b/tests/lib/user/database.php new file mode 100644 index 00000000000..fe7d87c44de --- /dev/null +++ b/tests/lib/user/database.php @@ -0,0 +1,44 @@ +. +* +*/ + +class Test_User_Database extends Test_User_Backend { + /** + * get a new unique user name + * test cases can override this in order to clean up created user + * @return array + */ + public function getUser() { + $user=uniqid('test_'); + $this->users[]=$user; + return $user; + } + + public function setUp() { + $this->backend=new OC_User_Dummy(); + } + + public function tearDown() { + foreach($this->users as $user) { + $this->backend->deleteUser($user); + } + } +} diff --git a/tests/lib/user/dummy.php b/tests/lib/user/dummy.php new file mode 100644 index 00000000000..e417fd97603 --- /dev/null +++ b/tests/lib/user/dummy.php @@ -0,0 +1,27 @@ +. +* +*/ + +class Test_User_Dummy extends Test_User_Backend { + public function setUp() { + $this->backend=new OC_User_Dummy(); + } +} diff --git a/tests/lib/user/manager.php b/tests/lib/user/manager.php new file mode 100644 index 00000000000..bc49f6db4b2 --- /dev/null +++ b/tests/lib/user/manager.php @@ -0,0 +1,304 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\User; + +class Manager extends \PHPUnit_Framework_TestCase { + public function testUserExistsSingleBackendExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $this->assertTrue($manager->userExists('foo')); + } + + public function testUserExistsSingleBackendNotExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $this->assertFalse($manager->userExists('foo')); + } + + public function testUserExistsNoBackends() { + $manager = new \OC\User\Manager(); + + $this->assertFalse($manager->userExists('foo')); + } + + public function testUserExistsTwoBackendsSecondExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + */ + $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + */ + $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend1); + $manager->registerBackend($backend2); + + $this->assertTrue($manager->userExists('foo')); + } + + public function testUserExistsTwoBackendsFirstExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + */ + $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + */ + $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2->expects($this->never()) + ->method('userExists'); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend1); + $manager->registerBackend($backend2); + + $this->assertTrue($manager->userExists('foo')); + } + + public function testGetOneBackendExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $this->assertEquals('foo', $manager->get('foo')->getUID()); + } + + public function testGetOneBackendNotExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $this->assertEquals(null, $manager->get('foo')); + } + + public function testSearchOneBackend() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('getUsers') + ->with($this->equalTo('fo')) + ->will($this->returnValue(array('foo', 'afoo'))); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $result = $manager->search('fo'); + $this->assertEquals(2, count($result)); + $this->assertEquals('afoo', $result[0]->getUID()); + $this->assertEquals('foo', $result[1]->getUID()); + } + + public function testSearchTwoBackendLimitOffset() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + */ + $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1->expects($this->once()) + ->method('getUsers') + ->with($this->equalTo('fo'), $this->equalTo(3), $this->equalTo(1)) + ->will($this->returnValue(array('foo1', 'foo2'))); + + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + */ + $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2->expects($this->once()) + ->method('getUsers') + ->with($this->equalTo('fo'), $this->equalTo(1), $this->equalTo(0)) + ->will($this->returnValue(array('foo3'))); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend1); + $manager->registerBackend($backend2); + + $result = $manager->search('fo', 3, 1); + $this->assertEquals(3, count($result)); + $this->assertEquals('foo1', $result[0]->getUID()); + $this->assertEquals('foo2', $result[1]->getUID()); + $this->assertEquals('foo3', $result[2]->getUID()); + } + + public function testCreateUserSingleBackendNotExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $backend->expects($this->once()) + ->method('createUser') + ->with($this->equalTo('foo'), $this->equalTo('bar')); + + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $user = $manager->createUser('foo', 'bar'); + $this->assertEquals('foo', $user->getUID()); + } + + /** + * @expectedException \Exception + */ + public function testCreateUserSingleBackendExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $backend->expects($this->never()) + ->method('createUser'); + + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $manager->createUser('foo', 'bar'); + } + + public function testCreateUserSingleBackendNotSupported() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $backend->expects($this->never()) + ->method('createUser'); + + $backend->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $this->assertFalse($manager->createUser('foo', 'bar')); + } + + public function testCreateUserNoBackends() { + $manager = new \OC\User\Manager(); + + $this->assertFalse($manager->createUser('foo', 'bar')); + } + + /** + * @expectedException \Exception + */ + public function testCreateUserTwoBackendExists() { + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + */ + $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $backend1->expects($this->never()) + ->method('createUser'); + + $backend1->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(false)); + + /** + * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + */ + $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $backend2->expects($this->never()) + ->method('createUser'); + + $backend2->expects($this->once()) + ->method('userExists') + ->with($this->equalTo('foo')) + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend1); + $manager->registerBackend($backend2); + + $manager->createUser('foo', 'bar'); + } +} diff --git a/tests/lib/user/session.php b/tests/lib/user/session.php new file mode 100644 index 00000000000..274e9e2831e --- /dev/null +++ b/tests/lib/user/session.php @@ -0,0 +1,155 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\User; + +class Session extends \PHPUnit_Framework_TestCase { + public function testGetUser() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->once()) + ->method('get') + ->with('user_id') + ->will($this->returnValue('foo')); + + $backend = $this->getMock('OC_User_Dummy'); + $backend->expects($this->once()) + ->method('userExists') + ->with('foo') + ->will($this->returnValue(true)); + + $manager = new \OC\User\Manager(); + $manager->registerBackend($backend); + + $userSession = new \OC\User\Session($manager, $session); + $user = $userSession->getUser(); + $this->assertEquals('foo', $user->getUID()); + } + + public function testSetUser() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->once()) + ->method('set') + ->with('user_id', 'foo'); + + $manager = $this->getMock('\OC\User\Manager'); + + $backend = $this->getMock('OC_User_Dummy'); + + $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('foo')); + + $userSession = new \OC\User\Session($manager, $session); + $userSession->setUser($user); + } + + public function testLoginValidPasswordEnabled() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->once()) + ->method('set') + ->with('user_id', 'foo'); + + $manager = $this->getMock('\OC\User\Manager'); + + $backend = $this->getMock('OC_User_Dummy'); + + $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); + $user->expects($this->once()) + ->method('checkPassword') + ->with('bar') + ->will($this->returnValue(true)); + $user->expects($this->once()) + ->method('isEnabled') + ->will($this->returnValue(true)); + $user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('foo')); + + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($user)); + + $userSession = new \OC\User\Session($manager, $session); + $userSession->login('foo', 'bar'); + $this->assertEquals($user, $userSession->getUser()); + } + + public function testLoginValidPasswordDisabled() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->never()) + ->method('set'); + + $manager = $this->getMock('\OC\User\Manager'); + + $backend = $this->getMock('OC_User_Dummy'); + + $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); + $user->expects($this->once()) + ->method('checkPassword') + ->with('bar') + ->will($this->returnValue(true)); + $user->expects($this->once()) + ->method('isEnabled') + ->will($this->returnValue(false)); + + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($user)); + + $userSession = new \OC\User\Session($manager, $session); + $userSession->login('foo', 'bar'); + } + + public function testLoginInValidPassword() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->never()) + ->method('set'); + + $manager = $this->getMock('\OC\User\Manager'); + + $backend = $this->getMock('OC_User_Dummy'); + + $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); + $user->expects($this->once()) + ->method('checkPassword') + ->with('bar') + ->will($this->returnValue(false)); + $user->expects($this->never()) + ->method('isEnabled'); + + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($user)); + + $userSession = new \OC\User\Session($manager, $session); + $userSession->login('foo', 'bar'); + } + + public function testLoginNonExisting() { + $session = $this->getMock('\OC\Session\Memory', array(), array('')); + $session->expects($this->never()) + ->method('set'); + + $manager = $this->getMock('\OC\User\Manager'); + + $backend = $this->getMock('OC_User_Dummy'); + + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue(null)); + + $userSession = new \OC\User\Session($manager, $session); + $userSession->login('foo', 'bar'); + } +} diff --git a/tests/lib/user/user.php b/tests/lib/user/user.php new file mode 100644 index 00000000000..b0d170cbfc5 --- /dev/null +++ b/tests/lib/user/user.php @@ -0,0 +1,364 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\User; + +use OC\Hooks\PublicEmitter; + +class User extends \PHPUnit_Framework_TestCase { + public function testDisplayName() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Backend'); + $backend->expects($this->once()) + ->method('getDisplayName') + ->with($this->equalTo('foo')) + ->will($this->returnValue('Foo')); + + $backend->expects($this->any()) + ->method('implementsActions') + ->with($this->equalTo(\OC_USER_BACKEND_GET_DISPLAYNAME)) + ->will($this->returnValue(true)); + + $user = new \OC\User\User('foo', $backend); + $this->assertEquals('Foo', $user->getDisplayName()); + } + + public function testDisplayNameNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Backend'); + $backend->expects($this->never()) + ->method('getDisplayName'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->with($this->equalTo(\OC_USER_BACKEND_GET_DISPLAYNAME)) + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertEquals('foo', $user->getDisplayName()); + } + + public function testSetPassword() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('setPassword') + ->with($this->equalTo('foo'), $this->equalTo('bar')); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_SET_PASSWORD) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->setPassword('bar','')); + } + + public function testSetPasswordNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->never()) + ->method('setPassword'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertFalse($user->setPassword('bar','')); + } + + public function testDelete() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('deleteUser') + ->with($this->equalTo('foo')); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->delete()); + } + + public function testCheckPassword() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('checkPassword') + ->with($this->equalTo('foo'), $this->equalTo('bar')) + ->will($this->returnValue(true)); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_CHECK_PASSWORD) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->checkPassword('bar')); + } + + public function testCheckPasswordNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->never()) + ->method('checkPassword'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertFalse($user->checkPassword('bar')); + } + + public function testGetHome() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('getHome') + ->with($this->equalTo('foo')) + ->will($this->returnValue('/home/foo')); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_GET_HOME) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend); + $this->assertEquals('/home/foo', $user->getHome()); + } + + public function testGetHomeNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->never()) + ->method('getHome'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertEquals(\OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/foo', $user->getHome()); + } + + public function testCanChangePassword() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_SET_PASSWORD) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->canChangePassword()); + } + + public function testCanChangePasswordNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertFalse($user->canChangePassword()); + } + + public function testCanChangeDisplayName() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_SET_DISPLAYNAME) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->canChangeDisplayName()); + } + + public function testCanChangeDisplayNameNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $user = new \OC\User\User('foo', $backend); + $this->assertFalse($user->canChangeDisplayName()); + } + + public function testSetDisplayNameSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Database'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_SET_DISPLAYNAME) { + return true; + } else { + return false; + } + })); + + $backend->expects($this->once()) + ->method('setDisplayName') + ->with('foo','Foo'); + + $user = new \OC\User\User('foo', $backend); + $this->assertTrue($user->setDisplayName('Foo')); + $this->assertEquals('Foo',$user->getDisplayName()); + } + + public function testSetDisplayNameNotSupported() { + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Database'); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + return false; + })); + + $backend->expects($this->never()) + ->method('setDisplayName'); + + $user = new \OC\User\User('foo', $backend); + $this->assertFalse($user->setDisplayName('Foo')); + $this->assertEquals('foo',$user->getDisplayName()); + } + + public function testSetPasswordHooks() { + $hooksCalled = 0; + $test = $this; + + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('setPassword'); + + /** + * @param \OC\User\User $user + * @param string $password + */ + $hook = function ($user, $password) use ($test, &$hooksCalled) { + $hooksCalled++; + $test->assertEquals('foo', $user->getUID()); + $test->assertEquals('bar', $password); + }; + + $emitter = new PublicEmitter(); + $emitter->listen('\OC\User', 'preSetPassword', $hook); + $emitter->listen('\OC\User', 'postSetPassword', $hook); + + $backend->expects($this->any()) + ->method('implementsActions') + ->will($this->returnCallback(function ($actions) { + if ($actions === \OC_USER_BACKEND_SET_PASSWORD) { + return true; + } else { + return false; + } + })); + + $user = new \OC\User\User('foo', $backend, $emitter); + + $user->setPassword('bar',''); + $this->assertEquals(2, $hooksCalled); + } + + public function testDeleteHooks() { + $hooksCalled = 0; + $test = $this; + + /** + * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend + */ + $backend = $this->getMock('\OC_User_Dummy'); + $backend->expects($this->once()) + ->method('deleteUser'); + + /** + * @param \OC\User\User $user + */ + $hook = function ($user) use ($test, &$hooksCalled) { + $hooksCalled++; + $test->assertEquals('foo', $user->getUID()); + }; + + $emitter = new PublicEmitter(); + $emitter->listen('\OC\User', 'preDelete', $hook); + $emitter->listen('\OC\User', 'postDelete', $hook); + + $user = new \OC\User\User('foo', $backend, $emitter); + $this->assertTrue($user->delete()); + $this->assertEquals(2, $hooksCalled); + } +} From 4b688db612239be2bf554183858aaaa0a11c46a3 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 29 May 2013 00:32:10 +0200 Subject: [PATCH 02/22] implement old user api on top of the new one --- lib/user.php | 499 +++++++++++++++++++-------------------------------- 1 file changed, 180 insertions(+), 319 deletions(-) diff --git a/lib/user.php b/lib/user.php index 1dde87a1339..cebae2493f3 100644 --- a/lib/user.php +++ b/lib/user.php @@ -37,28 +37,42 @@ * logout() */ class OC_User { - // The backend used for user management + public static $userSession = null; + + private static function getUserSession() { + if (!self::$userSession) { + $manager = new \OC\User\Manager(); + self::$userSession = new \OC\User\Session($manager, \OC::$session); + } + return self::$userSession; + } + + private static function getManager() { + return self::getUserSession()->getManager(); + } + + private static $_backends = array(); + private static $_usedBackends = array(); private static $_setupedBackends = array(); - // Backends available (except database) - private static $_backends = array(); - /** * @brief registers backend - * @param $name name of the backend - * @returns true/false + * @param string $backend name of the backend + * @deprecated Add classes by calling useBackend with a class instance instead + * @return bool * * Makes a list of backends that can be used by other modules */ - public static function registerBackend( $backend ) { + public static function registerBackend($backend) { self::$_backends[] = $backend; return true; } /** * @brief gets available backends + * @deprecated * @returns array of backends * * Returns the names of all backends. @@ -69,6 +83,7 @@ class OC_User { /** * @brief gets used backends + * @deprecated * @returns array of backends * * Returns the names of all used backends. @@ -79,33 +94,36 @@ class OC_User { /** * @brief Adds the backend to the list of used backends - * @param $backend default: database The backend to use for user managment - * @returns true/false + * @param string | OC_User_Backend $backend default: database The backend to use for user management + * @return bool * * Set the User Authentication Module */ - public static function useBackend( $backend = 'database' ) { - if($backend instanceof OC_User_Interface) { - OC_Log::write('core', 'Adding user backend instance of '.get_class($backend).'.', OC_Log::DEBUG); - self::$_usedBackends[get_class($backend)]=$backend; + public static function useBackend($backend = 'database') { + if ($backend instanceof OC_User_Interface) { + OC_Log::write('core', 'Adding user backend instance of ' . get_class($backend) . '.', OC_Log::DEBUG); + self::$_usedBackends[get_class($backend)] = $backend; + self::getManager()->registerBackend($backend); } else { // You'll never know what happens - if( null === $backend OR !is_string( $backend )) { + if (null === $backend OR !is_string($backend)) { $backend = 'database'; } // Load backend - switch( $backend ) { + switch ($backend) { case 'database': case 'mysql': case 'sqlite': - OC_Log::write('core', 'Adding user backend '.$backend.'.', OC_Log::DEBUG); + OC_Log::write('core', 'Adding user backend ' . $backend . '.', OC_Log::DEBUG); self::$_usedBackends[$backend] = new OC_User_Database(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); break; default: - OC_Log::write('core', 'Adding default user backend '.$backend.'.', OC_Log::DEBUG); + OC_Log::write('core', 'Adding default user backend ' . $backend . '.', OC_Log::DEBUG); $className = 'OC_USER_' . strToUpper($backend); self::$_usedBackends[$backend] = new $className(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); break; } } @@ -116,121 +134,73 @@ class OC_User { * remove all used backends */ public static function clearBackends() { - self::$_usedBackends=array(); + self::$_usedBackends = array(); + self::getManager()->clearBackends(); } /** * setup the configured backends in config.php */ public static function setupBackends() { - $backends=OC_Config::getValue('user_backends', array()); - foreach($backends as $i=>$config) { - $class=$config['class']; - $arguments=$config['arguments']; - if(class_exists($class)) { - if(array_search($i, self::$_setupedBackends)===false) { + $backends = OC_Config::getValue('user_backends', array()); + foreach ($backends as $i => $config) { + $class = $config['class']; + $arguments = $config['arguments']; + if (class_exists($class)) { + if (array_search($i, self::$_setupedBackends) === false) { // make a reflection object $reflectionObj = new ReflectionClass($class); // use Reflection to create a new instance, using the $args $backend = $reflectionObj->newInstanceArgs($arguments); self::useBackend($backend); - $_setupedBackends[]=$i; + $_setupedBackends[] = $i; } else { - OC_Log::write('core', 'User backend '.$class.' already initialized.', OC_Log::DEBUG); + OC_Log::write('core', 'User backend ' . $class . ' already initialized.', OC_Log::DEBUG); } } else { - OC_Log::write('core', 'User backend '.$class.' not found.', OC_Log::ERROR); + OC_Log::write('core', 'User backend ' . $class . ' not found.', OC_Log::ERROR); } } } /** * @brief Create a new user - * @param $uid The username of the user to create - * @param $password The password of the new user - * @returns true/false + * @param string $uid The username of the user to create + * @param string $password The password of the new user + * @throws Exception + * @return bool true/false * * Creates a new user. Basic checking of username is done in OC_User * itself, not in its subclasses. * * Allowed characters in the username are: "a-z", "A-Z", "0-9" and "_.@-" */ - public static function createUser( $uid, $password ) { - // Check the name for bad characters - // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" - if( preg_match( '/[^a-zA-Z0-9 _\.@\-]/', $uid )) { - throw new Exception('Only the following characters are allowed in a username:' - .' "a-z", "A-Z", "0-9", and "_.@-"'); - } - // No empty username - if(trim($uid) == '') { - throw new Exception('A valid username must be provided'); - } - // No empty password - if(trim($password) == '') { - throw new Exception('A valid password must be provided'); - } - - // Check if user already exists - if( self::userExistsForCreation($uid) ) { - throw new Exception('The username is already being used'); - } - - - $run = true; - OC_Hook::emit( "OC_User", "pre_createUser", array( "run" => &$run, "uid" => $uid, "password" => $password )); - - if( $run ) { - //create the user in the first backend that supports creating users - foreach(self::$_usedBackends as $backend) { - if(!$backend->implementsActions(OC_USER_BACKEND_CREATE_USER)) - continue; - - $backend->createUser($uid, $password); - OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => $uid, "password" => $password )); - - return self::userExists($uid); - } - } - return false; + public static function createUser($uid, $password) { + self::getManager()->createUser($uid, $password); } /** * @brief delete a user - * @param $uid The username of the user to delete - * @returns true/false + * @param string $uid The username of the user to delete + * @return bool * * Deletes a user */ - public static function deleteUser( $uid ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_deleteUser", array( "run" => &$run, "uid" => $uid )); + public static function deleteUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->delete(); - if( $run ) { - //delete the user from all backends - foreach(self::$_usedBackends as $backend) { - $backend->deleteUser($uid); - } - if (self::userExists($uid)) { - return false; - } // We have to delete the user from all groups - foreach( OC_Group::getUserGroups( $uid ) as $i ) { - OC_Group::removeFromGroup( $uid, $i ); + foreach (OC_Group::getUserGroups($uid) as $i) { + OC_Group::removeFromGroup($uid, $i); } // Delete the user's keys in preferences OC_Preferences::deleteUser($uid); // Delete user files in /data/ - OC_Helper::rmdirr(OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/'.$uid.'/'); - - // Emit and exit - OC_Hook::emit( "OC_User", "post_deleteUser", array( "uid" => $uid )); - return true; - } - else{ - return false; + OC_Helper::rmdirr(OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid . '/'); } } @@ -238,75 +208,51 @@ class OC_User { * @brief Try to login a user * @param $uid The username of the user to log in * @param $password The password of the user - * @returns true/false + * @return bool * * Log in a user and regenerate a new session - if the password is ok */ - public static function login( $uid, $password ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid, "password" => $password)); - - if( $run ) { - $uid = self::checkPassword( $uid, $password ); - $enabled = self::isEnabled($uid); - if($uid && $enabled) { - session_regenerate_id(true); - self::setUserId($uid); - self::setDisplayName($uid); - OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>$password )); - return true; - } - } - return false; + public static function login($uid, $password) { + return self::getUserSession()->login($uid, $password); } /** * @brief Sets user id for session and triggers emit */ public static function setUserId($uid) { - \OC::$session->set('user_id', $uid); + $user = self::getManager()->get($uid); + self::getUserSession()->setUser($user); } /** * @brief Sets user display name for session */ public static function setDisplayName($uid, $displayName = null) { - $result = false; - if ($displayName ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { - if($backend->userExists($uid)) { - $result |= $backend->setDisplayName($uid, $displayName); - } - } - } + if (is_null($displayName)) { + $displayName = $uid; + } + $user = self::getManager()->get($uid); + if ($user) { + return $user->setDisplayName($displayName); } else { - $displayName = self::determineDisplayName($uid); - $result = true; + return false; } - if (OC_User::getUser() === $uid) { - \OC::$session->set('display_name', $displayName); - } - return $result; } /** * @brief get display name * @param $uid The username - * @returns string display name or uid if no display name is defined + * @return string display name or uid if no display name is defined * */ - private static function determineDisplayName( $uid ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) { - $result=$backend->getDisplayName( $uid ); - if($result) { - return $result; - } - } + private static function determineDisplayName($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->getDisplayName(); + } else { + return $uid; } - return $uid; } /** @@ -315,10 +261,7 @@ class OC_User { * Logout, destroys session */ public static function logout() { - OC_Hook::emit( "OC_User", "logout", array()); - session_unset(); - session_destroy(); - OC_User::unsetMagicInCookie(); + self::getUserSession()->logout(); } /** @@ -328,23 +271,21 @@ class OC_User { * Checks if the user is logged in */ public static function isLoggedIn() { - if( \OC::$session->get('user_id')) { + if (\OC::$session->get('user_id')) { OC_App::loadApps(array('authentication')); self::setupBackends(); - if (self::userExists(\OC::$session->get('user_id')) ) { - return true; - } + return self::userExists(\OC::$session->get('user_id')); } return false; } /** * @brief Check if the user is an admin user - * @param $uid uid of the admin - * @returns bool + * @param string $uid uid of the admin + * @return bool */ public static function isAdminUser($uid) { - if(OC_Group::inGroup($uid, 'admin' )) { + if (OC_Group::inGroup($uid, 'admin')) { return true; } return false; @@ -356,32 +297,34 @@ class OC_User { * @return string uid or false */ public static function getUser() { - if( \OC::$session->get('user_id') ) { - return \OC::$session->get('user_id'); - } - else{ + $user = self::getUserSession()->getUser(); + if ($user) { + return $user->getUID(); + } else { return false; } } /** * @brief get the display name of the user currently logged in. - * @return string uid or false + * @retur string uid or false */ - public static function getDisplayName($user=null) { - if ( $user ) { + public static function getDisplayName($user = null) { + if ($user) { return self::determineDisplayName($user); - } else if( \OC::$session->get('display_name') ) { - return \OC::$session->get('display_name'); - } - else{ - return false; + } else { + $user = self::getUserSession()->getUser(); + if ($user) { + return $user->getDisplayName(); + } else { + return false; + } } } /** * @brief Autogenerate a password - * @returns string + * @return string * * generates a password */ @@ -391,91 +334,51 @@ class OC_User { /** * @brief Set password - * @param $uid The username - * @param $password The new password - * @param $recoveryPassword for the encryption app to reset encryption keys - * @returns true/false + * @param string $uid The username + * @param string $password The new password + * @param string $recoveryPassword for the encryption app to reset encryption keys + * @return bool * * Change the password of a user */ - public static function setPassword( $uid, $password, $recoveryPassword = null ) { - $run = true; - OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password, "recoveryPassword" => $recoveryPassword )); - - if( $run ) { - $success = false; - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) { - if($backend->userExists($uid)) { - $success |= $backend->setPassword($uid, $password); - } - } - } - // invalidate all login cookies - OC_Preferences::deleteApp($uid, 'login_token'); - OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password, "recoveryPassword" => $recoveryPassword )); - return $success; - } - else{ + public static function setPassword($uid, $password, $recoveryPassword = null) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->setPassword($password, $recoveryPassword); + } else { return false; } } /** * @brief Check whether user can change his password - * @param $uid The username - * @returns true/false + * @param string $uid The username + * @return bool * * Check whether a specified user can change his password */ public static function canUserChangePassword($uid) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) { - if($backend->userExists($uid)) { - return true; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangePassword(); + } else { + return false; } - return false; } /** * @brief Check whether user can change his display name - * @param $uid The username - * @returns true/false + * @param string $uid The username + * @return bool * * Check whether a specified user can change his display name */ public static function canUserChangeDisplayName($uid) { - if (OC_Config::getValue('allow_user_to_change_display_name', true)) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { - if($backend->userExists($uid)) { - return true; - } - } - } - } - return false; - } - - /** - * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns string - * - * Check if the password is correct without logging in the user - * returns the user id or false - */ - public static function checkPassword( $uid, $password ) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_CHECK_PASSWORD)) { - $result=$backend->checkPassword( $uid, $password ); - if($result) { - return $result; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangeDisplayName(); + } else { + return false; } } @@ -483,20 +386,37 @@ class OC_User { * @brief Check if the password is correct * @param string $uid The username * @param string $password The password - * @returns string + * @return bool + * + * Check if the password is correct without logging in the user + * returns the user id or false + */ + public static function checkPassword($uid, $password) { + $user = self::getManager()->get($uid); + if ($user) { + if ($user->checkPassword($password)) { + return $user->getUID(); + } else { + return false; + } + } else { + return false; + } + } + + /** + * @param string $uid The username + * @return string * * returns the path to the users home directory */ public static function getHome($uid) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_GET_HOME) && $backend->userExists($uid)) { - $result=$backend->getHome($uid); - if($result) { - return $result; - } - } + $user = self::getManager()->get($uid); + if ($user) { + return $user->getHome(); + } else { + return OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid; } - return OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/' . $uid; } /** @@ -506,152 +426,93 @@ class OC_User { * Get a list of all users. */ public static function getUsers($search = '', $limit = null, $offset = null) { - $users = array(); - foreach (self::$_usedBackends as $backend) { - $backendUsers = $backend->getUsers($search, $limit, $offset); - if (is_array($backendUsers)) { - $users = array_merge($users, $backendUsers); - } + $users = self::getManager()->search($search, $limit, $offset); + $uids = array(); + foreach ($users as $user) { + $uids[] = $user->getUID(); } - asort($users); - return $users; + return $uids; } /** * @brief Get a list of all users display name - * @returns associative array with all display names (value) and corresponding uids (key) + * @param string $search + * @param int $limit + * @param int $offset + * @return array associative array with all display names (value) and corresponding uids (key) * * Get a list of all display names and user ids. */ public static function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = array(); - foreach (self::$_usedBackends as $backend) { - $backendDisplayNames = $backend->getDisplayNames($search, $limit, $offset); - if (is_array($backendDisplayNames)) { - $displayNames = $displayNames + $backendDisplayNames; - } + $users = self::getManager()->searchDisplayName($search, $limit, $offset); + foreach ($users as $user) { + $displayNames[$user->getUID()] = $user->getDisplayName(); } - asort($displayNames); return $displayNames; } /** * @brief check if a user exists * @param string $uid the username - * @param string $excludingBackend (default none) * @return boolean */ - public static function userExists($uid, $excludingBackend=null) { - foreach(self::$_usedBackends as $backend) { - if (!is_null($excludingBackend) && !strcmp(get_class($backend), $excludingBackend)) { - OC_Log::write('OC_User', $excludingBackend . 'excluded from user existance check.', OC_Log::DEBUG); - continue; - } - $result=$backend->userExists($uid); - if($result===true) { - return true; - } - } - return false; + public static function userExists($uid) { + return self::getManager()->userExists($uid); } - public static function userExistsForCreation($uid) { - foreach(self::$_usedBackends as $backend) { - if(!$backend->hasUserListings()) - continue; - - $result=$backend->userExists($uid); - if($result===true) { - return true; - } - } - return false; - } - /** * disables a user + * * @param string $userid the user to disable */ public static function disableUser($userid) { - $sql = "INSERT INTO `*PREFIX*preferences` (`userid`, `appid`, `configkey`, `configvalue`) VALUES(?, ?, ?, ?)"; - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( OC_DB::isError($result) ) { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); - } - } else { - OC_Log::write('OC_User', 'could not disable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + $user = self::getManager()->get($userid); + if ($user) { + $user->setEnabled(false); } } /** * enable a user + * * @param string $userid */ public static function enableUser($userid) { - $sql = 'DELETE FROM `*PREFIX*preferences`' - ." WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?"; - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( OC_DB::isError($result) ) { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); - } - } else { - OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + $user = self::getManager()->get($userid); + if ($user) { + $user->setEnabled(true); } } /** * checks if a user is enabled + * * @param string $userid * @return bool */ public static function isEnabled($userid) { - $sql = 'SELECT `userid` FROM `*PREFIX*preferences`' - .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?'; - if (OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { //FIXME oracle hack - $sql = 'SELECT `userid` FROM `*PREFIX*preferences`' - .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND to_char(`configvalue`) = ?'; - } - $stmt = OC_DB::prepare($sql); - if ( ! OC_DB::isError($stmt) ) { - $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); - if ( ! OC_DB::isError($result) ) { - return $result->numRows() ? false : true; - } else { - OC_Log::write('OC_User', - 'could not check if enabled: '. OC_DB::getErrorMessage($result), - OC_Log::ERROR); - } + $user = self::getManager()->get($userid); + if ($user) { + return $user->isEnabled(); } else { - OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); + return false; } - return false; } /** * @brief Set cookie value to use in next page load * @param string $username username to be set + * @param string $token */ public static function setMagicInCookie($username, $token) { - $secure_cookie = OC_Config::getValue("forcessl", false); - $expires = time() + OC_Config::getValue('remember_login_cookie_lifetime', 60*60*24*15); - setcookie("oc_username", $username, $expires, OC::$WEBROOT, '', $secure_cookie); - setcookie("oc_token", $token, $expires, OC::$WEBROOT, '', $secure_cookie, true); - setcookie("oc_remember_login", true, $expires, OC::$WEBROOT, '', $secure_cookie); + self::getUserSession()->setMagicInCookie($username, $token); } /** * @brief Remove cookie for "remember username" */ public static function unsetMagicInCookie() { - unset($_COOKIE["oc_username"]); - unset($_COOKIE["oc_token"]); - unset($_COOKIE["oc_remember_login"]); - setcookie("oc_username", null, -1); - setcookie("oc_token", null, -1); - setcookie("oc_remember_login", null, -1); + self::getUserSession()->unsetMagicInCookie(); } } From 198655f109a40074643c516e24c0bd8aef6d7cd7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 29 May 2013 00:47:44 +0200 Subject: [PATCH 03/22] fix User->setHome when the backend action fails --- lib/user/user.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/user/user.php b/lib/user/user.php index 095c37939a7..fb97ff1a6d8 100644 --- a/lib/user/user.php +++ b/lib/user/user.php @@ -139,8 +139,8 @@ class User { * @return string */ public function getHome() { - if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME)) { - return $this->backend->getHome($this->uid); + if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) { + return $home; } return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented } From 3e7e2c8a5c5eb51d04302520f1367125c98644bd Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 29 May 2013 00:47:55 +0200 Subject: [PATCH 04/22] fix setting getting active userid --- lib/user.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/user.php b/lib/user.php index cebae2493f3..efae4f9aa36 100644 --- a/lib/user.php +++ b/lib/user.php @@ -220,8 +220,7 @@ class OC_User { * @brief Sets user id for session and triggers emit */ public static function setUserId($uid) { - $user = self::getManager()->get($uid); - self::getUserSession()->setUser($user); + OC::$session->set('user_id', $uid); } /** @@ -297,9 +296,9 @@ class OC_User { * @return string uid or false */ public static function getUser() { - $user = self::getUserSession()->getUser(); - if ($user) { - return $user->getUID(); + $uid = OC::$session->get('user_id'); + if (!is_null($uid)) { + return $uid; } else { return false; } From 8320f41dbe463020423c3fe8d2368bc8d415750a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 29 May 2013 01:05:49 +0200 Subject: [PATCH 05/22] Emit leacgy OC_User hooks --- lib/user.php | 31 +++++++++++++++++++++++++++++-- lib/user/manager.php | 12 ++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/user.php b/lib/user.php index efae4f9aa36..cab7bee5c00 100644 --- a/lib/user.php +++ b/lib/user.php @@ -30,8 +30,8 @@ * post_createUser(uid, password) * pre_deleteUser(&run, uid) * post_deleteUser(uid) - * pre_setPassword(&run, uid, password) - * post_setPassword(uid, password) + * pre_setPassword(&run, uid, password, recoveryPassword) + * post_setPassword(uid, password, recoveryPassword) * pre_login(&run, uid, password) * post_login(uid) * logout() @@ -43,6 +43,33 @@ class OC_User { if (!self::$userSession) { $manager = new \OC\User\Manager(); self::$userSession = new \OC\User\Session($manager, \OC::$session); + self::$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { + \OC_Hook::emit('OC_User', 'pre_createUser', array("run" => true, "uid" => $uid, "password" => $password)); + }); + self::$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) { + \OC_Hook::emit('OC_User', 'post_createUser', array("uid" => $user->getUID(), "password" => $password)); + }); + self::$userSession->listen('\OC\User', 'preDelete', function ($user) { + \OC_Hook::emit('OC_User', 'pre_deleteUser', array("run" => true, "uid" => $user->getUID())); + }); + self::$userSession->listen('\OC\User', 'postDelete', function ($user) { + \OC_Hook::emit('OC_User', 'post_deleteUser', array("uid" => $user->getUID())); + }); + self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) { + OC_Hook::emit("OC_User", "pre_setPassword", array("run" => &$run, "uid" => $user->getUID(), "password" => $password, "recoveryPassword" => $recoveryPassword)); + }); + self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) { + OC_Hook::emit("OC_User", "post_setPassword", array("run" => &$run, "uid" => $user->getUID(), "password" => $password, "recoveryPassword" => $recoveryPassword)); + }); + self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { + \OC_Hook::emit('OC_User', 'pre_login', array("run" => true, "uid" => $uid, "password" => $password)); + }); + self::$userSession->listen('\OC\User', 'preDeleteUser', function ($user, $password) { + \OC_Hook::emit('OC_User', 'post_login', array("run" => true, "uid" => $user->getUID(), "password" => $password)); + }); + self::$userSession->listen('\OC\User', 'logout', function () { + \OC_Hook::emit('OC_User', 'logout', array()); + }); } return self::$userSession; } diff --git a/lib/user/manager.php b/lib/user/manager.php index 25e67ca36b5..260d0d32dea 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -20,7 +20,7 @@ use OC\Hooks\PublicEmitter; * - preDelete(\OC\User\User $user) * - postDelete(\OC\User\User $user) * - preCreateUser(string $uid, string $password) - * - postCreateUser(\OC\User\User $user) + * - postCreateUser(\OC\User\User $user, string $password) * * @package OC\User */ @@ -57,7 +57,7 @@ class Manager extends PublicEmitter { public function get($uid) { foreach ($this->backends as $backend) { if ($backend->userExists($uid)) { - return new User($uid, $backend); + return new User($uid, $backend, $this); } } return null; @@ -90,7 +90,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getUsers($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid) { - $users[] = new User($uid, $backend); + $users[] = new User($uid, $backend, $this); if (!is_null($limit)) { $limit--; } @@ -126,7 +126,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid => $displayName) { - $users[] = new User($uid, $backend); + $users[] = new User($uid, $backend, $this); if (!is_null($limit)) { $limit--; } @@ -179,8 +179,8 @@ class Manager extends PublicEmitter { foreach ($this->backends as $backend) { if ($backend->implementsActions(\OC_USER_BACKEND_CREATE_USER)) { $backend->createUser($uid, $password); - $user = new User($uid, $backend); - $this->emit('\OC\User', 'postCreateUser', array($user)); + $user = new User($uid, $backend, $this); + $this->emit('\OC\User', 'postCreateUser', array($user, $password)); return $user; } } From a8fb8033192d2a1129955989a0150058b3490883 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 31 May 2013 17:31:27 +0200 Subject: [PATCH 06/22] cache instances of \OC\User\User --- lib/user/manager.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/user/manager.php b/lib/user/manager.php index 260d0d32dea..a4639c3f2cc 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -30,6 +30,8 @@ class Manager extends PublicEmitter { */ private $backends = array(); + private $cachedUsers = array(); + /** * @param \OC_User_Backend $backend */ @@ -55,9 +57,13 @@ class Manager extends PublicEmitter { * @return \OC\User\User */ public function get($uid) { + if (isset($this->cachedUsers[$uid])) { + return $this->cachedUsers[$uid]; + } foreach ($this->backends as $backend) { if ($backend->userExists($uid)) { - return new User($uid, $backend, $this); + $this->cachedUsers[$uid] = new User($uid, $backend, $this); + return $this->cachedUsers[$uid]; } } return null; @@ -90,7 +96,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getUsers($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid) { - $users[] = new User($uid, $backend, $this); + $users[] = $this->get($uid); if (!is_null($limit)) { $limit--; } @@ -126,7 +132,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid => $displayName) { - $users[] = new User($uid, $backend, $this); + $users[] = $this->get($uid); if (!is_null($limit)) { $limit--; } @@ -159,7 +165,7 @@ class Manager extends PublicEmitter { // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" if (preg_match('/[^a-zA-Z0-9 _\.@\-]/', $uid)) { throw new \Exception('Only the following characters are allowed in a username:' - . ' "a-z", "A-Z", "0-9", and "_.@-"'); + . ' "a-z", "A-Z", "0-9", and "_.@-"'); } // No empty username if (trim($uid) == '') { @@ -179,7 +185,7 @@ class Manager extends PublicEmitter { foreach ($this->backends as $backend) { if ($backend->implementsActions(\OC_USER_BACKEND_CREATE_USER)) { $backend->createUser($uid, $password); - $user = new User($uid, $backend, $this); + $user = $this->get($uid); $this->emit('\OC\User', 'postCreateUser', array($user, $password)); return $user; } From f00844a003a7d08588a56fcee6914f5e1d885ea3 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 31 May 2013 17:42:51 +0200 Subject: [PATCH 07/22] fix caching of user objects --- lib/user/manager.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/user/manager.php b/lib/user/manager.php index a4639c3f2cc..3b6d4bcfe55 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -32,6 +32,16 @@ class Manager extends PublicEmitter { private $cachedUsers = array(); + public function __construct() { + $cachedUsers = $this->cachedUsers; + $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) { + $i = array_search($user, $cachedUsers); + if ($i !== false) { + unset($cachedUsers[$i]); + } + }); + } + /** * @param \OC_User_Backend $backend */ @@ -62,13 +72,20 @@ class Manager extends PublicEmitter { } foreach ($this->backends as $backend) { if ($backend->userExists($uid)) { - $this->cachedUsers[$uid] = new User($uid, $backend, $this); - return $this->cachedUsers[$uid]; + return $this->getUserObject($uid, $backend); } } return null; } + protected function getUserObject($uid, $backend) { + if (isset($this->cachedUsers[$uid])) { + return $this->cachedUsers[$uid]; + } + $this->cachedUsers[$uid] = new User($uid, $backend, $this); + return $this->cachedUsers[$uid]; + } + /** * @param string $uid * @return bool @@ -96,7 +113,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getUsers($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid) { - $users[] = $this->get($uid); + $users[] = $this->getUserObject($uid, $backend); if (!is_null($limit)) { $limit--; } @@ -132,7 +149,7 @@ class Manager extends PublicEmitter { $backendUsers = $backend->getDisplayNames($pattern, $limit, $offset); if (is_array($backendUsers)) { foreach ($backendUsers as $uid => $displayName) { - $users[] = $this->get($uid); + $users[] = $this->getUserObject($uid, $backend); if (!is_null($limit)) { $limit--; } @@ -185,7 +202,7 @@ class Manager extends PublicEmitter { foreach ($this->backends as $backend) { if ($backend->implementsActions(\OC_USER_BACKEND_CREATE_USER)) { $backend->createUser($uid, $password); - $user = $this->get($uid); + $user = $this->getUserObject($uid, $backend); $this->emit('\OC\User', 'postCreateUser', array($user, $password)); return $user; } From 473f3c6916b6c2033a564f6540b93ed99e748a30 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 31 May 2013 18:18:13 +0200 Subject: [PATCH 08/22] fix typo --- lib/user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/user.php b/lib/user.php index cab7bee5c00..cd29eb7efdb 100644 --- a/lib/user.php +++ b/lib/user.php @@ -333,7 +333,7 @@ class OC_User { /** * @brief get the display name of the user currently logged in. - * @retur string uid or false + * @return string uid or false */ public static function getDisplayName($user = null) { if ($user) { From cdb2f559a82e3280c546cf9f1de6a0ae225e3f94 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 31 May 2013 19:58:31 +0200 Subject: [PATCH 09/22] Fix postLogin hook --- lib/user.php | 2 +- lib/user/session.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/user.php b/lib/user.php index cd29eb7efdb..7e5b70c5330 100644 --- a/lib/user.php +++ b/lib/user.php @@ -64,7 +64,7 @@ class OC_User { self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { \OC_Hook::emit('OC_User', 'pre_login', array("run" => true, "uid" => $uid, "password" => $password)); }); - self::$userSession->listen('\OC\User', 'preDeleteUser', function ($user, $password) { + self::$userSession->listen('\OC\User', 'postLogin', function ($user, $password) { \OC_Hook::emit('OC_User', 'post_login', array("run" => true, "uid" => $user->getUID(), "password" => $password)); }); self::$userSession->listen('\OC\User', 'logout', function () { diff --git a/lib/user/session.php b/lib/user/session.php index b0fdcd3e850..fcbebee8f88 100644 --- a/lib/user/session.php +++ b/lib/user/session.php @@ -116,7 +116,7 @@ class Session implements Emitter { if ($user) { $result = $user->checkPassword($password); if ($result and $user->isEnabled()) { - $this->manager->emit('\OC\User', 'postLogin', array($user)); + $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); $this->setUser($user); return true; } else { From d85a10ebc544455b55f0ba86bc3d8f7bcd4187ee Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 31 May 2013 20:55:05 +0200 Subject: [PATCH 10/22] fix broken tests --- apps/files_encryption/tests/share.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 6d92881ceb0..816bc709f26 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -534,7 +534,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // some hacking to simulate public link $GLOBALS['app'] = 'files_sharing'; $GLOBALS['fileOwner'] = \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1; - \OC_User::setUserId(''); + \OC_User::setUserId(false); // get file contents $retrievedCryptedFile = file_get_contents('crypt://' . $this->filename); From b840de4e0125cec430dd1d9b49371fe5d4f6c1e7 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 31 May 2013 21:30:13 +0200 Subject: [PATCH 11/22] user should set into session before postLogin hook otherwise it will break not only the files_encryption app --- lib/user/session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/user/session.php b/lib/user/session.php index fcbebee8f88..f4a9c8382a1 100644 --- a/lib/user/session.php +++ b/lib/user/session.php @@ -116,8 +116,8 @@ class Session implements Emitter { if ($user) { $result = $user->checkPassword($password); if ($result and $user->isEnabled()) { - $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); $this->setUser($user); + $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); return true; } else { return false; From e430f442b50b43d085dac2f68b1c5ff3dd1236f7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 31 May 2013 22:51:16 +0200 Subject: [PATCH 12/22] use single quotes --- lib/user.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/user.php b/lib/user.php index 7e5b70c5330..bdd944ee183 100644 --- a/lib/user.php +++ b/lib/user.php @@ -44,28 +44,28 @@ class OC_User { $manager = new \OC\User\Manager(); self::$userSession = new \OC\User\Session($manager, \OC::$session); self::$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { - \OC_Hook::emit('OC_User', 'pre_createUser', array("run" => true, "uid" => $uid, "password" => $password)); + \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password)); }); self::$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) { - \OC_Hook::emit('OC_User', 'post_createUser', array("uid" => $user->getUID(), "password" => $password)); + \OC_Hook::emit('OC_User', 'post_createUser', array('uid' => $user->getUID(), 'password' => $password)); }); self::$userSession->listen('\OC\User', 'preDelete', function ($user) { - \OC_Hook::emit('OC_User', 'pre_deleteUser', array("run" => true, "uid" => $user->getUID())); + \OC_Hook::emit('OC_User', 'pre_deleteUser', array('run' => true, 'uid' => $user->getUID())); }); self::$userSession->listen('\OC\User', 'postDelete', function ($user) { - \OC_Hook::emit('OC_User', 'post_deleteUser', array("uid" => $user->getUID())); + \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID())); }); self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) { - OC_Hook::emit("OC_User", "pre_setPassword", array("run" => &$run, "uid" => $user->getUID(), "password" => $password, "recoveryPassword" => $recoveryPassword)); + OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => &$run, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) { - OC_Hook::emit("OC_User", "post_setPassword", array("run" => &$run, "uid" => $user->getUID(), "password" => $password, "recoveryPassword" => $recoveryPassword)); + OC_Hook::emit('OC_User', 'post_setPassword', array('run' => &$run, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { - \OC_Hook::emit('OC_User', 'pre_login', array("run" => true, "uid" => $uid, "password" => $password)); + \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password)); }); self::$userSession->listen('\OC\User', 'postLogin', function ($user, $password) { - \OC_Hook::emit('OC_User', 'post_login', array("run" => true, "uid" => $user->getUID(), "password" => $password)); + \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password)); }); self::$userSession->listen('\OC\User', 'logout', function () { \OC_Hook::emit('OC_User', 'logout', array()); @@ -227,7 +227,7 @@ class OC_User { OC_Preferences::deleteUser($uid); // Delete user files in /data/ - OC_Helper::rmdirr(OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid . '/'); + OC_Helper::rmdirr(OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid . '/'); } } @@ -441,7 +441,7 @@ class OC_User { if ($user) { return $user->getHome(); } else { - return OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid; + return OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid; } } From 82fd15706eeaf6e3770985cdf1aff86a1996f2e2 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 1 Jun 2013 00:34:46 +0200 Subject: [PATCH 13/22] fix undefined variables --- lib/user.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/user.php b/lib/user.php index bdd944ee183..5f8a4cbfce2 100644 --- a/lib/user.php +++ b/lib/user.php @@ -56,10 +56,10 @@ class OC_User { \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID())); }); self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) { - OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => &$run, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); + OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) { - OC_Hook::emit('OC_User', 'post_setPassword', array('run' => &$run, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); + OC_Hook::emit('OC_User', 'post_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password)); From 2c69403fd64adc8b5418ce3c719934a352c89035 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 1 Jun 2013 00:35:16 +0200 Subject: [PATCH 14/22] fix namespacing error --- lib/user/session.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/user/session.php b/lib/user/session.php index f4a9c8382a1..5406275170f 100644 --- a/lib/user/session.php +++ b/lib/user/session.php @@ -142,9 +142,9 @@ class Session implements Emitter { public function setMagicInCookie($username, $token) { $secure_cookie = \OC_Config::getValue("forcessl", false); //TODO: DI for cookies and OC_Config $expires = time() + \OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); - setcookie("oc_username", $username, $expires, OC::$WEBROOT, '', $secure_cookie); - setcookie("oc_token", $token, $expires, OC::$WEBROOT, '', $secure_cookie, true); - setcookie("oc_remember_login", true, $expires, OC::$WEBROOT, '', $secure_cookie); + setcookie("oc_username", $username, $expires, \OC::$WEBROOT, '', $secure_cookie); + setcookie("oc_token", $token, $expires, \OC::$WEBROOT, '', $secure_cookie, true); + setcookie("oc_remember_login", true, $expires, \OC::$WEBROOT, '', $secure_cookie); } /** From 3e00a3603cadf4e9e4b3c87bba0ef604077146fd Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Sat, 1 Jun 2013 00:49:06 +0200 Subject: [PATCH 15/22] adding PHPDoc comment to getManager() adding PHPDoc comment for $user within the hooks callbacks fixing PHPDoc comment on isLoggedIn() --- lib/user.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/user.php b/lib/user.php index 5f8a4cbfce2..a8b642a1630 100644 --- a/lib/user.php +++ b/lib/user.php @@ -47,24 +47,30 @@ class OC_User { \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password)); }); self::$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) { + /** @var $user \OC\User\User */ \OC_Hook::emit('OC_User', 'post_createUser', array('uid' => $user->getUID(), 'password' => $password)); }); self::$userSession->listen('\OC\User', 'preDelete', function ($user) { + /** @var $user \OC\User\User */ \OC_Hook::emit('OC_User', 'pre_deleteUser', array('run' => true, 'uid' => $user->getUID())); }); self::$userSession->listen('\OC\User', 'postDelete', function ($user) { + /** @var $user \OC\User\User */ \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID())); }); self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) { + /** @var $user \OC\User\User */ OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) { + /** @var $user \OC\User\User */ OC_Hook::emit('OC_User', 'post_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword)); }); self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password)); }); self::$userSession->listen('\OC\User', 'postLogin', function ($user, $password) { + /** @var $user \OC\User\User */ \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password)); }); self::$userSession->listen('\OC\User', 'logout', function () { @@ -74,6 +80,9 @@ class OC_User { return self::$userSession; } + /** + * @return \OC\User\Manager + */ private static function getManager() { return self::getUserSession()->getManager(); } @@ -292,7 +301,7 @@ class OC_User { /** * @brief Check if the user is logged in - * @returns true/false + * @returns bool * * Checks if the user is logged in */ From 00b4bfcbf56e29c905355fc8b4fea71b4075c8ee Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:15:42 +0200 Subject: [PATCH 16/22] User: remove determineDisplayName --- lib/user.php | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/user.php b/lib/user.php index a8b642a1630..a57ee5b13ca 100644 --- a/lib/user.php +++ b/lib/user.php @@ -274,22 +274,6 @@ class OC_User { } } - - /** - * @brief get display name - * @param $uid The username - * @return string display name or uid if no display name is defined - * - */ - private static function determineDisplayName($uid) { - $user = self::getManager()->get($uid); - if ($user) { - return $user->getDisplayName(); - } else { - return $uid; - } - } - /** * @brief Logs the current user out and kills all the session data * @@ -342,11 +326,17 @@ class OC_User { /** * @brief get the display name of the user currently logged in. + * @param string $uid * @return string uid or false */ - public static function getDisplayName($user = null) { - if ($user) { - return self::determineDisplayName($user); + public static function getDisplayName($uid = null) { + if ($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->getDisplayName(); + } else { + return $uid; + } } else { $user = self::getUserSession()->getUser(); if ($user) { From fbe3213fec12263c8c6ffa9967fcb3ee983dc189 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:17:03 +0200 Subject: [PATCH 17/22] User: consisten variable naming --- lib/user.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/user.php b/lib/user.php index a57ee5b13ca..503ac3f7493 100644 --- a/lib/user.php +++ b/lib/user.php @@ -489,10 +489,10 @@ class OC_User { /** * disables a user * - * @param string $userid the user to disable + * @param string $uid the user to disable */ - public static function disableUser($userid) { - $user = self::getManager()->get($userid); + public static function disableUser($uid) { + $user = self::getManager()->get($uid); if ($user) { $user->setEnabled(false); } @@ -501,10 +501,10 @@ class OC_User { /** * enable a user * - * @param string $userid + * @param string $uid */ - public static function enableUser($userid) { - $user = self::getManager()->get($userid); + public static function enableUser($uid) { + $user = self::getManager()->get($uid); if ($user) { $user->setEnabled(true); } @@ -513,11 +513,11 @@ class OC_User { /** * checks if a user is enabled * - * @param string $userid + * @param string $uid * @return bool */ - public static function isEnabled($userid) { - $user = self::getManager()->get($userid); + public static function isEnabled($uid) { + $user = self::getManager()->get($uid); if ($user) { return $user->isEnabled(); } else { From 1a4021a0fe0a5b3b9242109b2de441d30dfb5235 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:19:01 +0200 Subject: [PATCH 18/22] User: return backend result --- lib/user/user.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/user/user.php b/lib/user/user.php index fb97ff1a6d8..05d5a0935b4 100644 --- a/lib/user/user.php +++ b/lib/user/user.php @@ -76,8 +76,7 @@ class User { public function setDisplayName($displayName) { if ($this->canChangeDisplayName()) { $this->displayName = $displayName; - $this->backend->setDisplayName($this->uid, $displayName); - return true; + return $this->backend->setDisplayName($this->uid, $displayName); } else { return false; } From eb2a1e0f8a9514530702cbb049a309ad3ee75938 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:33:56 +0200 Subject: [PATCH 19/22] move phpdoc comments --- lib/user/manager.php | 20 +++++++++++++++++++- lib/user/session.php | 14 +++++++++++++- lib/user/user.php | 20 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/user/manager.php b/lib/user/manager.php index 3b6d4bcfe55..9adf66c825c 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -43,6 +43,8 @@ class Manager extends PublicEmitter { } /** + * register a user backend + * * @param \OC_User_Backend $backend */ public function registerBackend($backend) { @@ -50,6 +52,8 @@ class Manager extends PublicEmitter { } /** + * remove a user backend + * * @param \OC_User_Backend $backend */ public function removeBackend($backend) { @@ -58,16 +62,21 @@ class Manager extends PublicEmitter { } } + /** + * remove all user backends + */ public function clearBackends() { $this->backends = array(); } /** + * get a user by user id + * * @param string $uid * @return \OC\User\User */ public function get($uid) { - if (isset($this->cachedUsers[$uid])) { + if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends return $this->cachedUsers[$uid]; } foreach ($this->backends as $backend) { @@ -78,6 +87,13 @@ class Manager extends PublicEmitter { return null; } + /** + * get or construct the user object + * + * @param string $uid + * @param \OC_User_Backend $backend + * @return \OC\User\User + */ protected function getUserObject($uid, $backend) { if (isset($this->cachedUsers[$uid])) { return $this->cachedUsers[$uid]; @@ -87,6 +103,8 @@ class Manager extends PublicEmitter { } /** + * check if a user exists + * * @param string $uid * @return bool */ diff --git a/lib/user/session.php b/lib/user/session.php index 5406275170f..cf93d9593af 100644 --- a/lib/user/session.php +++ b/lib/user/session.php @@ -71,6 +71,8 @@ class Session implements Emitter { } /** + * get the manager object + * * @return \OC\User\Manager */ public function getManager() { @@ -110,6 +112,13 @@ class Session implements Emitter { } } + /** + * try to login with the provided credentials + * + * @param string $uid + * @param string $password + * @return bool + */ public function login($uid, $password) { $this->manager->emit('\OC\User', 'preLogin', array($uid, $password)); $user = $this->manager->get($uid); @@ -127,6 +136,9 @@ class Session implements Emitter { } } + /** + * logout the user from the session + */ public function logout() { $this->manager->emit('\OC\User', 'logout'); $this->setUser(null); @@ -148,7 +160,7 @@ class Session implements Emitter { } /** - * @brief Remove cookie for "remember username" + * Remove cookie for "remember username" */ public function unsetMagicInCookie() { unset($_COOKIE["oc_username"]); //TODO: DI diff --git a/lib/user/user.php b/lib/user/user.php index 05d5a0935b4..1d52b90e811 100644 --- a/lib/user/user.php +++ b/lib/user/user.php @@ -56,6 +56,8 @@ class User { } /** + * get the user id + * * @return string */ public function getUID() { @@ -63,6 +65,8 @@ class User { } /** + * get the displayname for the user, if no specific displayname is set it will fallback to the user id + * * @return string */ public function getDisplayName() { @@ -70,6 +74,8 @@ class User { } /** + * set the displayname for the user + * * @param string $displayName * @return bool */ @@ -83,6 +89,8 @@ class User { } /** + * Delete the user + * * @return bool */ public function delete() { @@ -97,6 +105,8 @@ class User { } /** + * Check if the password is valid for the user + * * @param $password * @return bool */ @@ -113,6 +123,8 @@ class User { } /** + * Set the password of the user + * * @param string $password * @param string $recoveryPassword for the encryption app to reset encryption keys * @return bool @@ -145,6 +157,8 @@ class User { } /** + * check if the backend supports changing passwords + * * @return bool */ public function canChangePassword() { @@ -152,6 +166,8 @@ class User { } /** + * check if the backend supports changing display names + * * @return bool */ public function canChangeDisplayName() { @@ -159,6 +175,8 @@ class User { } /** + * check if the user is enabled + * * @return bool */ public function isEnabled() { @@ -166,6 +184,8 @@ class User { } /** + * set the enabled status for the user + * * @param bool $enabled */ public function setEnabled($enabled) { From 83fbdc903f324dc2a789f5b8ebedb020f7727d89 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:39:34 +0200 Subject: [PATCH 20/22] cast result to bool --- lib/user/user.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/user/user.php b/lib/user/user.php index 1d52b90e811..f9466b71499 100644 --- a/lib/user/user.php +++ b/lib/user/user.php @@ -82,7 +82,8 @@ class User { public function setDisplayName($displayName) { if ($this->canChangeDisplayName()) { $this->displayName = $displayName; - return $this->backend->setDisplayName($this->uid, $displayName); + $result = $this->backend->setDisplayName($this->uid, $displayName); + return $result !== false; } else { return false; } From 2a82964830e79e0af7a66027cc885174f9954f4d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 13:46:05 +0200 Subject: [PATCH 21/22] use caching for userExists --- lib/user/manager.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/user/manager.php b/lib/user/manager.php index 9adf66c825c..07ebed83971 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -66,6 +66,7 @@ class Manager extends PublicEmitter { * remove all user backends */ public function clearBackends() { + $this->cachedUsers = array(); $this->backends = array(); } @@ -109,12 +110,8 @@ class Manager extends PublicEmitter { * @return bool */ public function userExists($uid) { - foreach ($this->backends as $backend) { - if ($backend->userExists($uid)) { - return true; - } - } - return false; + $user = $this->get($uid); + return ($user !== null); } /** From 0ce2b2708c7d587e51fdf0bdb5b852863d2b0424 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 3 Jun 2013 14:19:17 +0200 Subject: [PATCH 22/22] also clear cached users when removing a single backend --- lib/user/manager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/user/manager.php b/lib/user/manager.php index 07ebed83971..d17cdf1a200 100644 --- a/lib/user/manager.php +++ b/lib/user/manager.php @@ -57,6 +57,7 @@ class Manager extends PublicEmitter { * @param \OC_User_Backend $backend */ public function removeBackend($backend) { + $this->cachedUsers = array(); if (($i = array_search($backend, $this->backends)) !== false) { unset($this->backends[$i]); }