diff options
author | Lukas Reschke <lukas@owncloud.com> | 2015-10-23 17:26:54 +0200 |
---|---|---|
committer | Lukas Reschke <lukas@owncloud.com> | 2015-10-23 17:30:47 +0200 |
commit | cddc9abc06fbe35e5e21a736678ae647ca72d31a (patch) | |
tree | 9b7f92ce7d6fca7b3339f7d30bca8a719dcfa713 /apps/dav | |
parent | 0aaef4c2993f6fd37136904142ed58986b5d8f27 (diff) | |
download | nextcloud-server-cddc9abc06fbe35e5e21a736678ae647ca72d31a.tar.gz nextcloud-server-cddc9abc06fbe35e5e21a736678ae647ca72d31a.zip |
Add tests for Sabre Auth plugin + make getCurrentUser compatible
Diffstat (limited to 'apps/dav')
-rw-r--r-- | apps/dav/appinfo/v1/webdav.php | 5 | ||||
-rw-r--r-- | apps/dav/lib/connector/sabre/auth.php | 59 | ||||
-rw-r--r-- | apps/dav/tests/unit/connector/sabre/auth.php | 356 |
3 files changed, 399 insertions, 21 deletions
diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php index 610230fc816..f28736f1f01 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -44,7 +44,10 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory( ); // Backends -$authBackend = new \OCA\DAV\Connector\Sabre\Auth(); +$authBackend = new \OCA\DAV\Connector\Sabre\Auth( + \OC::$server->getSession(), + \OC::$server->getUserSession() +); $requestUri = \OC::$server->getRequest()->getRequestUri(); $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, function() { diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php index 2e52a179d29..39a7df31b7f 100644 --- a/apps/dav/lib/connector/sabre/auth.php +++ b/apps/dav/lib/connector/sabre/auth.php @@ -30,6 +30,8 @@ namespace OCA\DAV\Connector\Sabre; use Exception; +use OCP\ISession; +use OCP\IUserSession; use Sabre\DAV\Auth\Backend\AbstractBasic; use Sabre\DAV\Exception\NotAuthenticated; use Sabre\DAV\Exception\ServiceUnavailable; @@ -37,6 +39,21 @@ use Sabre\DAV\Exception\ServiceUnavailable; class Auth extends AbstractBasic { const DAV_AUTHENTICATED = 'AUTHENTICATED_TO_DAV_BACKEND'; + /** @var ISession */ + private $session; + /** @var IUserSession */ + private $userSession; + + /** + * @param ISession $session + * @param IUserSession $userSession + */ + public function __construct(ISession $session, + IUserSession $userSession) { + $this->session = $session; + $this->userSession = $userSession; + } + /** * Whether the user has initially authenticated via DAV * @@ -49,8 +66,8 @@ class Auth extends AbstractBasic { * @return bool */ protected function isDavAuthenticated($username) { - return !is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED)) && - \OC::$server->getSession()->get(self::DAV_AUTHENTICATED) === $username; + return !is_null($this->session->get(self::DAV_AUTHENTICATED)) && + $this->session->get(self::DAV_AUTHENTICATED) === $username; } /** @@ -64,24 +81,21 @@ class Auth extends AbstractBasic { * @return bool */ protected function validateUserPass($username, $password) { - if (\OC_User::isLoggedIn() && - $this->isDavAuthenticated(\OC_User::getUser()) + if ($this->userSession->isLoggedIn() && + $this->isDavAuthenticated($this->userSession->getUser()->getUID()) ) { - \OC_Util::setupFS(\OC_User::getUser()); - \OC::$server->getSession()->close(); + \OC_Util::setupFS($this->userSession->getUser()->getUID()); + $this->session->close(); return true; } else { \OC_Util::setUpFS(); //login hooks may need early access to the filesystem - if(\OC_User::login($username, $password)) { - // make sure we use ownCloud's internal username here - // and not the HTTP auth supplied one, see issue #14048 - $ocUser = \OC_User::getUser(); - \OC_Util::setUpFS($ocUser); - \OC::$server->getSession()->set(self::DAV_AUTHENTICATED, $ocUser); - \OC::$server->getSession()->close(); + if($this->userSession->login($username, $password)) { + \OC_Util::setUpFS($this->userSession->getUser()->getUID()); + $this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID()); + $this->session->close(); return true; } else { - \OC::$server->getSession()->close(); + $this->session->close(); return false; } } @@ -95,10 +109,15 @@ class Auth extends AbstractBasic { * @return string|null */ public function getCurrentUser() { - $user = \OC_User::getUser(); - if($user && $this->isDavAuthenticated($user)) { + $user = $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null; + if($user !== null && $this->isDavAuthenticated($user)) { return $user; } + + if($user !== null && is_null($this->session->get(self::DAV_AUTHENTICATED))) { + return $user; + } + return null; } @@ -114,9 +133,9 @@ class Auth extends AbstractBasic { * @param string $realm * @return bool * @throws ServiceUnavailable + * @throws NotAuthenticated */ public function authenticate(\Sabre\DAV\Server $server, $realm) { - try { $result = $this->auth($server, $realm); return $result; @@ -136,12 +155,12 @@ class Auth extends AbstractBasic { */ private function auth(\Sabre\DAV\Server $server, $realm) { if (\OC_User::handleApacheAuth() || - (\OC_User::isLoggedIn() && is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED))) + ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED))) ) { - $user = \OC_User::getUser(); + $user = $this->userSession->getUser()->getUID(); \OC_Util::setupFS($user); $this->currentUser = $user; - \OC::$server->getSession()->close(); + $this->session->close(); return true; } diff --git a/apps/dav/tests/unit/connector/sabre/auth.php b/apps/dav/tests/unit/connector/sabre/auth.php new file mode 100644 index 00000000000..0466f3aab77 --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/auth.php @@ -0,0 +1,356 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ +namespace Tests\Connector\Sabre; + +use Test\TestCase; +use OCP\ISession; +use OCP\IUserSession; + +/** + * Class Auth + * + * @package OCA\DAV\Connector\Sabre + */ +class Auth extends TestCase { + /** @var ISession */ + private $session; + /** @var \OCA\DAV\Connector\Sabre\Auth */ + private $auth; + /** @var IUserSession */ + private $userSession; + + public function setUp() { + parent::setUp(); + $this->session = $this->getMockBuilder('\OCP\ISession') + ->disableOriginalConstructor()->getMock(); + $this->userSession = $this->getMockBuilder('\OCP\IUserSession') + ->disableOriginalConstructor()->getMock(); + $this->auth = new \OCA\DAV\Connector\Sabre\Auth($this->session, $this->userSession); + } + + public function testIsDavAuthenticatedWithoutDavSession() { + $this->session + ->expects($this->once()) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + + $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testIsDavAuthenticatedWithWrongDavSession() { + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + + $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testIsDavAuthenticatedWithCorrectDavSession() { + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + + $this->assertTrue($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testValidateUserPassOfAlreadyDAVAuthenticatedUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassOfInvalidDAVAuthenticatedUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(3)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->exactly(3)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('MyTestUser', 'MyTestPassword') + ->will($this->returnValue(true)); + $this->session + ->expects($this->once()) + ->method('set') + ->with('AUTHENTICATED_TO_DAV_BACKEND', 'MyTestUser'); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassWithInvalidPassword() { + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(false)); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('MyTestUser', 'MyTestPassword') + ->will($this->returnValue(false)); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testGetCurrentUserWithoutBeingLoggedIn() { + $this->assertSame(null, $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithValidDAVLogin() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + + $this->assertSame('MyTestUser', $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithoutAnyDAVLogin() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + + $this->assertSame('MyTestUser', $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithWrongDAVUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyWrongDavUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(3)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + + $this->assertSame(null, $this->auth->getCurrentUser()); + } + + public function testAuthenticateAlreadyLoggedIn() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->session + ->expects($this->once()) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyWrongDavUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->auth->authenticate($server, 'TestRealm')); + } + + /** + * @expectedException \Sabre\DAV\Exception\NotAuthenticated + * @expectedExceptionMessage No basic authentication headers were found + */ + public function testAuthenticateNoBasicAuthenticateHeadersProvided() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->auth->authenticate($server, 'TestRealm'); + } + + public function testAuthenticateValidCredentials() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest + ->expects($this->once()) + ->method('getHeader') + ->with('Authorization') + ->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ=')); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('username', 'password') + ->will($this->returnValue(true)); + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->assertTrue($this->auth->authenticate($server, 'TestRealm')); + } + + /** + * @expectedException \Sabre\DAV\Exception\NotAuthenticated + * @expectedExceptionMessage Username or password does not match + */ + public function testAuthenticateInvalidCredentials() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest + ->expects($this->once()) + ->method('getHeader') + ->with('Authorization') + ->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ=')); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('username', 'password') + ->will($this->returnValue(false)); + $this->auth->authenticate($server, 'TestRealm'); + } +} |