diff --git a/apps/user_webdavauth/appinfo/app.php b/apps/user_webdavauth/appinfo/app.php index 125f5f406547..00f65cd925ad 100644 --- a/apps/user_webdavauth/appinfo/app.php +++ b/apps/user_webdavauth/appinfo/app.php @@ -1,39 +1,28 @@ . -* -*/ - -require_once OC_App::getAppPath('user_webdavauth').'/user_webdavauth.php'; + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * @copyright 2014 Lukas Reschke lukas@owncloud.com + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ -OC_APP::registerAdmin('user_webdavauth', 'settings'); +namespace OCA\user_webdavauth\AppInfo; -OC_User::registerBackend("WEBDAVAUTH"); -OC_User::useBackend( "WEBDAVAUTH" ); +use OCA\user_webdavauth\USER_WEBDAVAUTH; +use OCP\Util; -OCP\Util::addTranslations('user_webdavauth'); - -// add settings page to navigation -$entry = array( - 'id' => "user_webdavauth_settings", - 'order'=>1, - 'href' => OC_Helper::linkTo( "user_webdavauth", "settings.php" ), - 'name' => 'WEBDAVAUTH' +$userBackend = new USER_WEBDAVAUTH( + \OC::$server->getConfig(), + \OC::$server->getDb(), + \OC::$server->getHTTPHelper(), + \OC::$server->getLogger(), + \OC::$server->getUserManager(), + \OC::$server->getServerRoot() ); +\OC_User::useBackend($userBackend); + +Util::addTranslations('user_webdavauth'); +\OC_APP::registerAdmin('user_webdavauth', 'settings'); diff --git a/apps/user_webdavauth/appinfo/database.xml b/apps/user_webdavauth/appinfo/database.xml new file mode 100644 index 000000000000..d862fdb545e6 --- /dev/null +++ b/apps/user_webdavauth/appinfo/database.xml @@ -0,0 +1,41 @@ + + + + *dbname* + true + false + utf8 + + + + *dbprefix*webdav_user_mapping + + + + + uid + text + true + 255 + + + + displayname + text + false + 255 + + + + webdav_uid + true + + uid + + + + + +
+ +
diff --git a/apps/user_webdavauth/appinfo/info.xml b/apps/user_webdavauth/appinfo/info.xml index abbf79131b5a..249286dbdffd 100644 --- a/apps/user_webdavauth/appinfo/info.xml +++ b/apps/user_webdavauth/appinfo/info.xml @@ -2,12 +2,12 @@ user_webdavauth WebDAV user backend - Authenticate users by a WebDAV call. You can use any WebDAV server, ownCloud server or other webserver to authenticate. It should return http 200 for right credentials and http 401 for wrong ones. + Authenticate users by a WebDAV call. You can use any WebDAV server, ownCloud server or other web server to authenticate. It should return a HTTP 2xx status code for correct credentials and a 4xx or 5xx for invalid ones. - Attention: This app is not compatible with the LDAP user and group backend. This app is not the webdav interface of ownCloud, if you don't understand what it does then do not enable it. + Attention: This app is not the WebDAV interface of ownCloud, if you don't understand what it does then do not enable it. AGPL Frank Karlitschek - 4.93 + 7.0 true diff --git a/apps/user_webdavauth/appinfo/version b/apps/user_webdavauth/appinfo/version index 238afc2b2796..4e0321ef5823 100644 --- a/apps/user_webdavauth/appinfo/version +++ b/apps/user_webdavauth/appinfo/version @@ -1 +1 @@ -1.1.0.1 +1.2.0.0 \ No newline at end of file diff --git a/apps/user_webdavauth/settings.php b/apps/user_webdavauth/settings.php index ae9cb7e4c921..900fbf687e23 100644 --- a/apps/user_webdavauth/settings.php +++ b/apps/user_webdavauth/settings.php @@ -1,24 +1,13 @@ . - * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ OC_Util::checkAdminUser(); @@ -28,12 +17,12 @@ OCP\JSON::callCheck(); if(isset($_POST['webdav_url'])) { - OC_CONFIG::setValue('user_webdavauth_url', strip_tags($_POST['webdav_url'])); + \OC::$server->getConfig()->setSystemValue('user_webdavauth_url', $_POST['webdav_url']); } } // fill template -$tmpl = new OC_Template( 'user_webdavauth', 'settings'); -$tmpl->assign( 'webdav_url', OC_Config::getValue( "user_webdavauth_url" )); +$tmpl = new OC_Template('user_webdavauth', 'settings'); +$tmpl->assign('webdav_url', \OC::$server->getConfig()->getSystemValue('user_webdavauth_url')); return $tmpl->fetchPage(); diff --git a/apps/user_webdavauth/templates/settings.php b/apps/user_webdavauth/templates/settings.php index a87c0ad159a8..181b2e42320b 100644 --- a/apps/user_webdavauth/templates/settings.php +++ b/apps/user_webdavauth/templates/settings.php @@ -1,7 +1,15 @@ +

t('WebDAV Authentication'));?>

-

- - -
t('The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials.')); ?> +

+ + + +
+ t('The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP status codes 2xx and 403 as valid credentials, and all other responses as invalid credentials.')); ?> +

diff --git a/apps/user_webdavauth/tests/user_webdavauthtest.php b/apps/user_webdavauth/tests/user_webdavauthtest.php new file mode 100644 index 000000000000..594d5e08eab4 --- /dev/null +++ b/apps/user_webdavauth/tests/user_webdavauthtest.php @@ -0,0 +1,513 @@ +config = $this->getMockBuilder('\OCP\IConfig') + ->disableOriginalConstructor()->getMock(); + $this->db = $this->getMockBuilder('\OCP\IDb') + ->disableOriginalConstructor()->getMock(); + $this->httpHelper = $this->getMockBuilder('\OC\HTTPHelper') + ->disableOriginalConstructor()->getMock(); + $this->logger = $this->getMockBuilder('\OCP\ILogger') + ->disableOriginalConstructor()->getMock(); + $this->userManager = $this->getMockBuilder('\OCP\IUserManager') + ->disableOriginalConstructor()->getMock(); + + $this->userWebDavAuth = new USER_WEBDAVAUTH( + $this->config, + $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ); + } + + public function urlProvider() + { + return array( + array(false, 'file://fo', 'user', 'password'), + array('http://lukas:test@dav.owncloud.org/testpoint/', 'http://dav.owncloud.org/testpoint/', 'lukas', 'test'), + array('https://lukas:test@dav.owncloud.org/testpoint/', 'HTTPS://DAV.OWNCLOUD.org/testpoint/', 'lukas', 'test'), + array('https://CrazyUserN%40me%2F%2A%2A%2A%2A%2F_%C3%A0a%C2%A3:CrazyP%40ssword%2F%2A%2A%2A%2A%2F_%C3%A0a%C2%A3@dav.owncloud.org/testpoint/', 'HTTPS://DAV.OWNCLOUD.org/testpoint/', 'CrazyUserN@me/****/_àa£', 'CrazyP@ssword/****/_àa£'), + ); + } + + /** + * @dataProvider urlProvider + * @param string $expected + * @param string $endpointUrl + * @param string $uid + * @param string $password + */ + public function testCreateAuthUrl($expected, $endpointUrl, $uid, $password) { + $this->assertSame($expected, \Test_Helper::invokePrivate($this->userWebDavAuth, 'createAuthUrl', [$endpointUrl, $uid, $password])); + } + + public function testCheckPasswordNotExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, + $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(false)); + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('user_webdavauth_url') + ->will($this->returnValue('http://dav.owncloud.org/testpoint/')); + $this->httpHelper->expects($this->once()) + ->method('getHeaders') + ->with('http://lukas:test1234@dav.owncloud.org/testpoint/') + ->will($this->returnValue(['HTTP/1.1 200 OK'])); + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('INSERT INTO `*PREFIX*webdav_user_mapping` (`uid`) VALUES (?)') + ->will($this->returnValue($this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock())); + + $this->assertEquals('lukas', $webDavAuth->checkPassword('lukas', 'test1234')); + } + public function testCheckPasswordCorrectExistingUserInAnotherBackend() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, + $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $this->userManager->expects($this->once()) + ->method('removeBackend'); + $this->userManager->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(true)); + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('user_webdavauth_url') + ->will($this->returnValue('http://dav.owncloud.org/testpoint/')); + $this->httpHelper->expects($this->once()) + ->method('getHeaders') + ->with('http://lukas:test1234@dav.owncloud.org/testpoint/') + ->will($this->returnValue(['HTTP/1.1 200 OK'])); + + $this->assertEquals(false, $webDavAuth->checkPassword('lukas', 'test1234')); + } + + public function testCheckPasswordCorrectExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, + $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $this->userManager->expects($this->once()) + ->method('removeBackend'); + $this->userManager->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(false)); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(true)); + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('user_webdavauth_url') + ->will($this->returnValue('http://dav.owncloud.org/testpoint/')); + $this->httpHelper->expects($this->once()) + ->method('getHeaders') + ->with('http://lukas:test1234@dav.owncloud.org/testpoint/') + ->will($this->returnValue(['HTTP/1.1 200 OK'])); + + $this->assertEquals('lukas', $webDavAuth->checkPassword('lukas', 'test1234')); + } + + public function testCheckPasswordIncorrect() { + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('user_webdavauth_url') + ->will($this->returnValue('http://dav.owncloud.org/testpoint/')); + $this->httpHelper->expects($this->once()) + ->method('getHeaders') + ->with('http://User%40Foobar.com%2F..%2F:%2F..%2FMy%40Password123%2F._%C3%A5%C3%A9@dav.owncloud.org/testpoint/') + ->will($this->returnValue(['HTTP/1.1 403 Forbidden'])); + + $this->assertEquals(false, $this->userWebDavAuth->checkPassword('User@Foobar.com/../', '/../My@Password123/._åé')); + } + + public function testGetHomeExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(true)); + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('datadirectory', '/var/www/owncloud/data') + ->will($this->returnArgument(1)); + + $this->assertSame('/var/www/owncloud/data/lukas', $webDavAuth->getHome('lukas')); + } + + public function testGetHomeNotExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('NotExisting') + ->will($this->returnValue(false)); + + $this->assertSame(false, $webDavAuth->getHome('NotExisting')); + } + + public function testSetDisplayNameExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('lukas') + ->will($this->returnValue(true)); + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute'); + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('UPDATE `*PREFIX*webdav_user_mapping` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)') + ->will($this->returnValue($query)); + + $this->assertSame(true, $webDavAuth->setDisplayName('lukas', 'Lukas Reschke')); + } + + public function testSetDisplayNameNotExistingUser() { + /** @var USER_WEBDAVAUTH $webDavAuth */ + $webDavAuth = $this->getMockBuilder('\OCA\user_webdavauth\USER_WEBDAVAUTH') + ->setConstructorArgs([ + $this->config, $this->db, + $this->httpHelper, + $this->logger, + $this->userManager, + '/var/www/owncloud' + ] + ) + ->setMethods(['userExists']) + ->getMock(); + $webDavAuth->expects($this->once()) + ->method('userExists') + ->with('NotExisting') + ->will($this->returnValue(false)); + + $this->assertSame(false, $webDavAuth->setDisplayName('NotExisting', 'DisplaynameToSet')); + } + + public function testCountUsers() { + $execute = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $execute->expects($this->once()) + ->method('fetchOne') + ->will($this->returnValue(5)); + + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($execute)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('SELECT COUNT(*) FROM `*PREFIX*webdav_user_mapping`') + ->will($this->returnValue($query)); + + $this->assertSame(5, $this->userWebDavAuth->countUsers()); + } + + public function testDeleteUser() { + $this->assertSame(false, $this->userWebDavAuth->deleteUser('')); + } + + public function testGetUsersWithParameter() { + $execute = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $execute->expects($this->exactly(3)) + ->method('fetchRow') + ->will( + $this->onConsecutiveCalls( + ['uid' => 'frank'], + ['uid' => 'lukas'] + ) + ); + + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($execute)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with( + $this->equalTo( + 'SELECT `uid` FROM `*PREFIX*webdav_user_mapping`' + . ' WHERE LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC' + ), + 10, + 500 + ) + ->will($this->returnValue($query)); + + $this->assertSame(['frank', 'lukas'], $this->userWebDavAuth->getUsers('foo', 10, 500)); + } + + public function testGetUsersWithoutParameter() { + $execute = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $execute->expects($this->exactly(3)) + ->method('fetchRow') + ->will( + $this->onConsecutiveCalls( + ['uid' => 'frank'], + ['uid' => 'lukas'] + ) + ); + + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($execute)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with( + $this->equalTo( + 'SELECT `uid` FROM `*PREFIX*webdav_user_mapping`' + . ' WHERE LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC' + ) + ) + ->will($this->returnValue($query)); + + $this->assertSame(['frank', 'lukas'], $this->userWebDavAuth->getUsers()); + } + + public function testUserExistsExisting() { + $execute = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $execute->expects($this->once()) + ->method('fetchOne') + ->will($this->returnValue('1')); + + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($execute)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('SELECT COUNT(*) FROM `*PREFIX*webdav_user_mapping` WHERE LOWER(`uid`) = LOWER(?)') + ->will($this->returnValue($query)); + + $this->assertSame(true, $this->userWebDavAuth->userExists('ExistingUser')); + } + + + public function testUserExistsNotExisting() { + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($query)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('SELECT COUNT(*) FROM `*PREFIX*webdav_user_mapping` WHERE LOWER(`uid`) = LOWER(?)') + ->will($this->returnValue($query)); + + $this->assertSame(false, $this->userWebDavAuth->userExists('NotExistingUser')); + } + + public function testGetDisplayName() { + $execute = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $execute->expects($this->once()) + ->method('fetchOne') + ->will($this->returnValue('Lukas Reschke')); + + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($execute)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with('SELECT `displayname` FROM `*PREFIX*webdav_user_mapping` WHERE LOWER(`uid`) = LOWER(?)') + ->will($this->returnValue($query)); + + $this->assertSame('Lukas Reschke', $this->userWebDavAuth->getDisplayName('lukas')); + } + + public function testGetDisplayNamesWithoutParameter() { + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->exactly(4)) + ->method('fetchRow') + ->will($this->onConsecutiveCalls( + ['uid' => 'Foo', 'displayname' => 'Mr. Foo'], + ['uid' => 'Lukas', 'displayname' => 'Reschke Lukas'], + ['uid' => 'frank', 'displayname' => 'Frank Karlitschek'] + )); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($query)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with( + $this->equalTo( + 'SELECT `uid`, `displayname` FROM `*PREFIX*webdav_user_mapping`' + . ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR ' + . 'LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC' + ), + null, + null + ) + ->will($this->returnValue($query)); + + + $this->assertSame([ + 'Foo' => 'Mr. Foo', + 'Lukas' => 'Reschke Lukas', + 'frank' => 'Frank Karlitschek' + ], $this->userWebDavAuth->getDisplayNames()); + } + + public function testGetDisplayNamesWithParameter() { + $query = $this->getMockBuilder('\OC_DB_StatementWrapper') + ->disableOriginalConstructor()->getMock(); + $query->expects($this->exactly(2)) + ->method('fetchRow') + ->will($this->onConsecutiveCalls( + ['uid' => 'Foo', 'displayname' => 'Mr. Foo'] + )); + $query->expects($this->once()) + ->method('execute') + ->will($this->returnValue($query)); + + $this->db->expects($this->once()) + ->method('prepareQuery') + ->with( + $this->equalTo( + 'SELECT `uid`, `displayname` FROM `*PREFIX*webdav_user_mapping`' + . ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR ' + . 'LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC' + ), + 10, + 15 + ) + ->will($this->returnValue($query)); + + + $this->assertSame([ + 'Foo' => 'Mr. Foo', + ], $this->userWebDavAuth->getDisplayNames('Foo', 10, 15)); + } + + public function testHasUserListings() { + $this->assertSame(true, $this->userWebDavAuth->hasUserListings()); + } + +} diff --git a/apps/user_webdavauth/user_webdavauth.php b/apps/user_webdavauth/user_webdavauth.php index 86e5b916f3d2..6e2d04ad90f3 100644 --- a/apps/user_webdavauth/user_webdavauth.php +++ b/apps/user_webdavauth/user_webdavauth.php @@ -1,89 +1,279 @@ . - * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ -class OC_USER_WEBDAVAUTH extends OC_User_Backend { - protected $webdavauth_url; +namespace OCA\user_webdavauth; - public function __construct() { - $this->webdavauth_url = OC_Config::getValue( "user_webdavauth_url" ); - } +use OC\HTTPHelper; +use OCP\IConfig; +use OCP\IDb; +use OCP\ILogger; +use OCP\IUserManager; - public function deleteUser($uid) { - // Can't delete user - OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to delete users from web frontend using WebDAV user backend', 3); - return false; +class USER_WEBDAVAUTH implements \OCP\UserInterface { + /** @var string */ + private $tableName = '*PREFIX*webdav_user_mapping'; + /** @var IConfig */ + private $config; + /** @var IDb */ + private $db; + /** @var HTTPHelper */ + private $httpHelper; + /** @var ILogger */ + private $logger; + /** @var IUserManager */ + private $userManager; + /** @var string */ + private $serverRoot; + + /** + * @param IConfig $config + * @param IDb $db + * @param HTTPHelper $httpHelper + * @param ILogger $logger + * @param IUserManager $userManager + * @param string $serverRoot + */ + public function __construct(IConfig $config, + IDb $db, + HTTPHelper $httpHelper, + ILogger $logger, + IUserManager $userManager, + $serverRoot) { + $this->config = $config; + $this->db = $db; + $this->httpHelper = $httpHelper; + $this->logger = $logger; + $this->userManager = $userManager; + $this->serverRoot = $serverRoot; } - public function setPassword ( $uid, $password ) { - // We can't change user password - OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to change password for users from web frontend using WebDAV user backend', 3); - return false; + /** + * Check if backend implements actions + * + * @param int $actions bitwise-or'ed actions + * @return boolean + */ + public function implementsActions($actions) { + return (bool)((\OC_User_Backend::CHECK_PASSWORD + | \OC_User_Backend::GET_DISPLAYNAME + | \OC_User_Backend::SET_DISPLAYNAME + | \OC_User_Backend::COUNT_USERS + | \OC_User_Backend::GET_HOME) + & $actions); } - public function checkPassword( $uid, $password ) { - $arr = explode('://', $this->webdavauth_url, 2); - if( ! isset($arr) OR count($arr) !== 2) { - OC_Log::write('OC_USER_WEBDAVAUTH', 'Invalid Url: "'.$this->webdavauth_url.'" ', 3); + /** + * Builds the auth url from the specified endpoint + * + * @param string $endPointUrl + * @param string $uid + * @param string $password + * @return string|false + */ + private function createAuthUrl($endPointUrl, $uid, $password) { + $arr = explode('://', strtolower($endPointUrl), 2); + if(empty($arr) || count($arr) !== 2) { return false; } list($webdavauth_protocol, $webdavauth_url_path) = $arr; - $url= $webdavauth_protocol.'://'.urlencode($uid).':'.urlencode($password).'@'.$webdavauth_url_path; - $headers = get_headers($url); - if($headers==false) { - OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to connect to WebDAV Url: "'.$webdavauth_protocol.'://'.$webdavauth_url_path.'" ', 3); + + if($webdavauth_protocol !== 'http' && $webdavauth_protocol !== 'https') { return false; + } + + return $webdavauth_protocol.'://'.urlencode($uid).':'.urlencode($password).'@'.$webdavauth_url_path; + } + /** + * Check if the password is correct + * + * @param string $uid The username + * @param string $password The password + * @return boolean|false + */ + public function checkPassword($uid, $password) { + $endPointUrl = $this->config->getSystemValue('user_webdavauth_url'); + $headers = $this->httpHelper->getHeaders($this->createAuthUrl($endPointUrl, $uid, $password)); + if($headers === false) { + $this->logger->error('Not possible to connect to WebDAV endpoint: ' . $endPointUrl, + array('app' => 'user_webdavauth')); + return false; } - $returncode= substr($headers[0], 9, 3); - if(substr($returncode, 0, 1) === '2') { + $uid = strtolower($uid); + + $returnCode = substr($headers[0], 9, 3); + if(substr($returnCode, 0, 1) === '2') { + // If user already exists in another backend don't login + $this->userManager->removeBackend($this); + if($this->userManager->userExists($uid)) { + return false; + } + + // If the user does not exists in this backend create it + if(!$this->userExists($uid)) { + $query = $this->db->prepareQuery('INSERT INTO `'.$this->tableName.'` (`uid`) VALUES (?)'); + $query->bindValue(1, $uid); + $query->execute(); + } + return $uid; - } else { - return false; } + return false; } - /* - * we don´t know if a user exists without the password. so we have to return true all the time - */ - public function userExists( $uid ){ - return true; + /** + * get the user's home directory + * + * @param string $uid the username + * @return string|false + */ + public function getHome($uid) { + if ($this->userExists($uid)) { + return $this->config->getSystemValue('datadirectory', $this->serverRoot . '/data') . '/' . $uid; + } + + return false; } /** + * Set display name + * + * @param string $uid The username + * @param string $displayName The new display name * @return bool */ - public function hasUserListings() { + public function setDisplayName($uid, $displayName) { + if ($this->userExists($uid)) { + $query = $this->db->prepareQuery('UPDATE `'.$this->tableName.'` ' . + 'SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)'); + $query->bindValue(1, $displayName); + $query->bindValue(2, $uid); + $query->execute(); + return true; + } + return false; } - /* - * we don´t know the users so all we can do it return an empty array here - */ - public function getUsers($search = '', $limit = 10, $offset = 0) { - $returnArray = array(); + /** + * Counts the users + * + * @return int + */ + public function countUsers() { + $query = $this->db->prepareQuery('SELECT COUNT(*) FROM `'.$this->tableName.'`'); + $result = $query->execute(); + return $result->fetchOne(); + } + + /** + * delete a user - not implemented within user_webdavauth + * FIXME: That should be an optional action, but unfortunately it isn't. - Thus we always return false. + * + * @param string $uid The username of the user to delete + * @return bool + */ + public function deleteUser($uid) { + return false; + } + + /** + * Get a list of all users + * + * @param string $search + * @param null $limit + * @param null $offset + * @return array All UIDs + * @throws \OC\DatabaseException + */ + public function getUsers($search = '', $limit = null, $offset = null) { + $users = array(); + + $query = $this->db->prepareQuery('SELECT `uid` FROM `'.$this->tableName.'`' + . ' WHERE LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC', $limit, $offset); + $query->bindValue(1, '%'.$search.'%'); + $query->bindValue(2, '%'.$search.'%'); + $result = $query->execute(); + while($row = $result->fetchRow()) { + $users[] = $row['uid']; + } + return $users; + } + + /** + * check if a user exists + * + * @param string $uid the username + * @return boolean + */ + public function userExists($uid) { + $query = $this->db->prepareQuery('SELECT COUNT(*) FROM `'.$this->tableName.'`' + . ' WHERE LOWER(`uid`) = LOWER(?)'); + $query->bindValue(1, $uid); + $result = $query->execute(); + $existing = $result->fetchOne(); + if($existing === '1') { + return true; + } - return $returnArray; + return false; + } + + /** + * get display name of the user + * + * @param string $uid user ID of the user + * @return string display name + */ + public function getDisplayName($uid) { + $query = $this->db->prepareQuery('SELECT `displayname` FROM `'.$this->tableName.'`' + . ' WHERE LOWER(`uid`) = LOWER(?)'); + $query->bindValue(1, $uid); + $result = $query->execute(); + return $result->fetchOne(); + } + + /** + * Get a list of all display names + * + * @param string $search + * @param null $limit + * @param null $offset + * @return array Array of displaynames (value) and the corresponding UIDs (key) + * @throws \OC\DatabaseException + */ + public function getDisplayNames($search = '', $limit = null, $offset = null) { + $users = array(); + + $query = $this->db->prepareQuery('SELECT `uid`, `displayname` FROM `'.$this->tableName.'`' + . ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR ' + . 'LOWER(`uid`) LIKE LOWER(?) ORDER BY `uid` ASC', $limit, $offset); + $query->bindValue(1, '%'.$search.'%'); + $query->bindValue(2, '%'.$search.'%'); + $result = $query->execute(); + while($row = $result->fetchRow()) { + $users[$row['uid']] = $row['displayname']; + } + + return $users; + } + + /** + * Check if a user list is available or not + * + * @return boolean if users can be listed or not + */ + public function hasUserListings() { + return true; } } diff --git a/lib/base.php b/lib/base.php index 009732ead7bd..954bb1041469 100644 --- a/lib/base.php +++ b/lib/base.php @@ -482,7 +482,7 @@ public static function init() { } // setup the basic server - self::$server = new \OC\Server(\OC::$WEBROOT); + self::$server = new \OC\Server(\OC::$WEBROOT, \OC::$SERVERROOT); \OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd); \OC::$server->getEventLogger()->start('boot', 'Initialize'); diff --git a/lib/private/httphelper.php b/lib/private/httphelper.php index 846825dee8de..1897f4c57093 100644 --- a/lib/private/httphelper.php +++ b/lib/private/httphelper.php @@ -137,7 +137,7 @@ public function getUrlContent($url) { /** * Returns the response headers of a HTTP URL without following redirects * @param string $location Needs to be a HTTPS or HTTP URL - * @return array + * @return array|false an indexed or associative array with the headers, or false on failure. */ public function getHeaders($location) { stream_context_set_default($this->getDefaultContextArray()); diff --git a/lib/private/server.php b/lib/private/server.php index f4c20576ebb8..78d12fc46bff 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -32,12 +32,16 @@ class Server extends SimpleContainer implements IServerContainer { /** @var string */ private $webRoot; + /** @var string */ + private $serverRoot; /** * @param string $webRoot + * @param string $serverRoot */ - function __construct($webRoot) { + function __construct($webRoot, $serverRoot) { $this->webRoot = $webRoot; + $this->serverRoot = $serverRoot; $this->registerService('ContactsManager', function ($c) { return new ContactsManager(); @@ -704,7 +708,18 @@ function getWebRoot() { } /** - * @return \OCP\IDateTimeZone + * Get the server root directory + * + * @return string + */ + function getServerRoot() { + return $this->serverRoot; + } + + /** + * Get the timezone of the current user, based on his session information and config data + * + * @return \DateTimeZone */ public function getDateTimeZone() { return $this->query('DateTimeZone'); diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 193e2fdf105b..c9c366576c81 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -306,6 +306,13 @@ function getAppManager(); */ function getWebRoot(); + /** + * Get the server root directory + * + * @return string + */ + function getServerRoot(); + /** * @return \OCP\Files\Config\IMountProviderCollection */