* This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ namespace Test\User; use OC\Session\Memory; use OC\User\User; /** * @group DB * @package Test\User */ class Session extends \Test\TestCase { /** @var \OC\Authentication\Token\DefaultTokenProvider */ protected $defaultProvider; protected function setUp() { parent::setUp(); $this->defaultProvider = $this->getMockBuilder('\OC\Authentication\Token\DefaultTokenProvider') ->disableOriginalConstructor() ->getMock(); } public function testGetUser() { $token = new \OC\Authentication\Token\DefaultToken(); $expectedUser = new User('foo', null); $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->at(0)) ->method('get') ->with('user_id') ->will($this->returnValue($expectedUser->getUID())); $manager = $this->getMockBuilder('\OC\User\Manager') ->disableOriginalConstructor() ->getMock(); $this->defaultProvider->expects($this->once()) ->method('getToken') ->will($this->returnValue($token)); // TODO: check passed session id once it's mockable $session->expects($this->at(1)) ->method('last_login_check') ->will($this->returnValue(null)); // No check has been run yet $this->defaultProvider->expects($this->once()) ->method('getPassword') // TODO: check passed UID and session id once it's mockable ->will($this->returnValue('password123')); $manager->expects($this->once()) ->method('checkPassword') ->with($expectedUser->getUID(), 'password123') ->will($this->returnValue(true)); $session->expects($this->at(2)) ->method('set') ->with('last_login_check', $this->equalTo(time(), 10)); $session->expects($this->at(3)) ->method('get') ->with('last_token_update') ->will($this->returnValue(null)); // No check run so far $this->defaultProvider->expects($this->once()) ->method('updateToken') ->with($token); $session->expects($this->at(4)) ->method('set') ->with('last_token_update', $this->equalTo(time(), 10)); $manager->expects($this->any()) ->method('get') ->with($expectedUser->getUID()) ->will($this->returnValue($expectedUser)); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $user = $userSession->getUser(); $this->assertSame($expectedUser, $user); } public function isLoggedInData() { return [ [true], [false], ]; } /** * @dataProvider isLoggedInData */ public function testIsLoggedIn($isLoggedIn) { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $manager = $this->getMockBuilder('\OC\User\Manager') ->disableOriginalConstructor() ->getMock(); $userSession = $this->getMockBuilder('\OC\User\Session') ->setConstructorArgs([$manager, $session, $this->defaultProvider, [$this->defaultProvider]]) ->setMethods([ 'getUser' ]) ->getMock(); $user = new User('sepp', null); $userSession->expects($this->once()) ->method('getUser') ->will($this->returnValue($isLoggedIn ? $user : null)); $this->assertEquals($isLoggedIn, $userSession->isLoggedIn()); } 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('\Test\Util\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, $this->defaultProvider, [$this->defaultProvider]); $userSession->setUser($user); } public function testLoginValidPasswordEnabled() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->once()) ->method('regenerateId'); $session->expects($this->exactly(2)) ->method('set') ->with($this->callback(function ($key) { switch ($key) { case 'user_id': case 'loginname': return true; break; default: return false; break; } }, 'foo')); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(true)); $user->expects($this->any()) ->method('getUID') ->will($this->returnValue('foo')); $user->expects($this->once()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('checkPassword') ->with('foo', 'bar') ->will($this->returnValue($user)); $userSession = $this->getMockBuilder('\OC\User\Session') ->setConstructorArgs([$manager, $session, $this->defaultProvider, [$this->defaultProvider]]) ->setMethods([ 'prepareUserLogin' ]) ->getMock(); $userSession->expects($this->once()) ->method('prepareUserLogin'); $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'); $session->expects($this->once()) ->method('regenerateId'); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(false)); $user->expects($this->never()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('checkPassword') ->with('foo', 'bar') ->will($this->returnValue($user)); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $userSession->login('foo', 'bar'); } public function testLoginInvalidPassword() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->never()) ->method('set'); $session->expects($this->once()) ->method('regenerateId'); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->never()) ->method('isEnabled'); $user->expects($this->never()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('checkPassword') ->with('foo', 'bar') ->will($this->returnValue(false)); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $userSession->login('foo', 'bar'); } public function testLoginNonExisting() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->never()) ->method('set'); $session->expects($this->once()) ->method('regenerateId'); $manager = $this->getMock('\OC\User\Manager'); $backend = $this->getMock('\Test\Util\User\Dummy'); $manager->expects($this->once()) ->method('checkPassword') ->with('foo', 'bar') ->will($this->returnValue(false)); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $userSession->login('foo', 'bar'); } public function testRememberLoginValidToken() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->exactly(1)) ->method('set') ->with($this->callback(function ($key) { switch ($key) { case 'user_id': return true; default: return false; } }, 'foo')); $session->expects($this->once()) ->method('regenerateId'); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->any()) ->method('getUID') ->will($this->returnValue('foo')); $user->expects($this->once()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('get') ->with('foo') ->will($this->returnValue($user)); //prepare login token $token = 'goodToken'; \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); $userSession = $this->getMock( '\OC\User\Session', //override, otherwise tests will fail because of setcookie() array('setMagicInCookie'), //there are passed as parameters to the constructor array($manager, $session, $this->defaultProvider, [$this->defaultProvider])); $granted = $userSession->loginWithCookie('foo', $token); $this->assertSame($granted, true); } public function testRememberLoginInvalidToken() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->never()) ->method('set'); $session->expects($this->once()) ->method('regenerateId'); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->any()) ->method('getUID') ->will($this->returnValue('foo')); $user->expects($this->never()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('get') ->with('foo') ->will($this->returnValue($user)); //prepare login token $token = 'goodToken'; \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $granted = $userSession->loginWithCookie('foo', 'badToken'); $this->assertSame($granted, false); } public function testRememberLoginInvalidUser() { $session = $this->getMock('\OC\Session\Memory', array(), array('')); $session->expects($this->never()) ->method('set'); $session->expects($this->once()) ->method('regenerateId'); $managerMethods = get_class_methods('\OC\User\Manager'); //keep following methods intact in order to ensure hooks are //working $doNotMock = array('__construct', 'emit', 'listen'); foreach ($doNotMock as $methodName) { $i = array_search($methodName, $managerMethods, true); if ($i !== false) { unset($managerMethods[$i]); } } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->never()) ->method('getUID'); $user->expects($this->never()) ->method('updateLastLoginTimestamp'); $manager->expects($this->once()) ->method('get') ->with('foo') ->will($this->returnValue(null)); //prepare login token $token = 'goodToken'; \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); $userSession = new \OC\User\Session($manager, $session, $this->defaultProvider, [$this->defaultProvider]); $granted = $userSession->loginWithCookie('foo', $token); $this->assertSame($granted, false); } public function testActiveUserAfterSetSession() { $users = array( 'foo' => new User('foo', null), 'bar' => new User('bar', null) ); $manager = $this->getMockBuilder('\OC\User\Manager') ->disableOriginalConstructor() ->getMock(); $manager->expects($this->any()) ->method('get') ->will($this->returnCallback(function ($uid) use ($users) { return $users[$uid]; })); $session = new Memory(''); $session->set('user_id', 'foo'); $userSession = $this->getMockBuilder('\OC\User\Session') ->setConstructorArgs([$manager, $session, $this->defaultProvider, [$this->defaultProvider]]) ->setMethods([ 'validateSession' ]) ->getMock(); $userSession->expects($this->any()) ->method('validateSession'); $this->assertEquals($users['foo'], $userSession->getUser()); $session2 = new Memory(''); $session2->set('user_id', 'bar'); $userSession->setSession($session2); $this->assertEquals($users['bar'], $userSession->getUser()); } }