* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
+use OCP\EventDispatcher\IEventDispatcher;
+use Psr\Log\LoggerInterface;
+
// load needed apps
$RUNTIME_APPTYPES = ['filesystem', 'authentication', 'logging'];
\OC::$server->getRequest(),
\OC::$server->getShareManager(),
\OC::$server->getSession(),
- \OC::$server->getBruteForceThrottler()
+ \OC::$server->getBruteForceThrottler(),
+ \OC::$server->query(LoggerInterface::class)
);
$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
\OC::$server->getTagManager(),
\OC::$server->getRequest(),
\OC::$server->getPreviewManager(),
- \OC::$server->getEventDispatcher(),
+ \OC::$server->query(IEventDispatcher::class),
\OC::$server->getL10N('dav')
);
$filesDropPlugin = new \OCA\DAV\Files\Sharing\FilesDropPlugin();
// Define root url with /public.php/dav/files/TOKEN
+// $baseuri is defined in public.php
preg_match('/(^files\/\w+)/i', substr($requestUri, strlen($baseuri)), $match);
$baseuri = $baseuri . $match[0];
private const BRUTEFORCE_ACTION = 'public_dav_auth';
public const DAV_AUTHENTICATED = 'public_link_authenticated';
- private IShare $share;
+ private ?IShare $share = null;
private IManager $shareManager;
private ISession $session;
private IRequest $request;
private IThrottler $throttler;
-
+ private LoggerInterface $logger;
public function __construct(IRequest $request,
- IManager $shareManager,
- ISession $session,
- IThrottler $throttler) {
+ IManager $shareManager,
+ ISession $session,
+ IThrottler $throttler,
+ LoggerInterface $logger) {
$this->request = $request;
$this->shareManager = $shareManager;
$this->session = $session;
$this->throttler = $throttler;
+ $this->logger = $logger;
// setup realm
$defaults = new \OCP\Defaults();
} catch (\Exception $e) {
$class = get_class($e);
$msg = $e->getMessage();
- \OC::$server->get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
throw new ServiceUnavailable("$class: $msg");
}
}
* @return string
* @throws NotFound
*/
- private function getToken(): string {
- $path = $this->request->getPathInfo();
+ private function getToken(): string {
+ $path = $this->request->getPathInfo() ?: '';
// ['', 'dav', 'files', 'token']
$splittedPath = explode('/', $path);
$token = $this->getToken();
try {
+ /** @var IShare $share */
$share = $this->shareManager->getShareByToken($token);
} catch (ShareNotFound $e) {
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
* @return bool
* @throws NotAuthenticated
*/
- protected function validateUserPass($username, $password): bool {
+ protected function validateUserPass($username, $password) {
$this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), self::BRUTEFORCE_ACTION);
$token = $this->getToken();
}
return true;
}
+
+ if ($this->session->exists(PublicAuth::DAV_AUTHENTICATED)
+ && $this->session->get(PublicAuth::DAV_AUTHENTICATED) === $share->getId()) {
+ return true;
+ }
if (in_array('XMLHttpRequest', explode(',', $this->request->getHeader('X-Requested-With')))) {
// do not re-authenticate over ajax, use dummy auth name to prevent browser popup
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
return false;
- } else {
- return true;
}
+
+ return true;
}
public function getShare(): IShare {
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ *
+ * @author Bjoern Schiessle <bjoern@schiessle.org>
+ * @author Joas Schilling <coding@schilljs.com>
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @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 OCA\DAV\Tests\unit\Connector;
+
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\Security\Bruteforce\IThrottler;
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IManager;
+use OCP\Share\IShare;
+
+/**
+ * Class LegacyPublicAuthTest
+ *
+ * @group DB
+ *
+ * @package OCA\DAV\Tests\unit\Connector
+ */
+class LegacyPublicAuthTest extends \Test\TestCase {
+
+ /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
+ private $session;
+ /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
+ private $request;
+ /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
+ private $shareManager;
+ /** @var \OCA\DAV\Connector\LegacyPublicAuth */
+ private $auth;
+ /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
+ private $throttler;
+
+ /** @var string */
+ private $oldUser;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->session = $this->getMockBuilder(ISession::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->request = $this->getMockBuilder(IRequest::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->shareManager = $this->getMockBuilder(IManager::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->throttler = $this->getMockBuilder(IThrottler::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->auth = new \OCA\DAV\Connector\LegacyPublicAuth(
+ $this->request,
+ $this->shareManager,
+ $this->session,
+ $this->throttler
+ );
+
+ // Store current user
+ $this->oldUser = \OC_User::getUser();
+ }
+
+ protected function tearDown(): void {
+ \OC_User::setIncognitoMode(false);
+
+ // Set old user
+ \OC_User::setUserId($this->oldUser);
+ \OC_Util::setupFS($this->oldUser);
+
+ parent::tearDown();
+ }
+
+ public function testNoShare(): void {
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willThrowException(new ShareNotFound());
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+ public function testShareNoPassword(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn(null);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordFancyShareType(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(42);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+
+ public function testSharePasswordRemote(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordLinkValidPassword(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(true);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordMailValidPassword(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(true);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testInvalidSharePasswordLinkValidSession(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $this->shareManager->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordLinkInvalidSession(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $this->shareManager->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+
+ public function testSharePasswordMailInvalidSession(): void {
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->willReturn($share);
+
+ $this->shareManager->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+}
+++ /dev/null
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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 OCA\DAV\Tests\unit\Connector;
-
-use OCP\IRequest;
-use OCP\ISession;
-use OCP\Security\Bruteforce\IThrottler;
-use OCP\Share\Exceptions\ShareNotFound;
-use OCP\Share\IManager;
-use OCP\Share\IShare;
-
-/**
- * Class PublicAuthTest
- *
- * @group DB
- *
- * @package OCA\DAV\Tests\unit\Connector
- */
-class PublicAuthTest extends \Test\TestCase {
-
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
- private $session;
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $shareManager;
- /** @var \OCA\DAV\Connector\PublicAuth */
- private $auth;
- /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
- private $throttler;
-
- /** @var string */
- private $oldUser;
-
- protected function setUp(): void {
- parent::setUp();
-
- $this->session = $this->getMockBuilder(ISession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->shareManager = $this->getMockBuilder(IManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->throttler = $this->getMockBuilder(IThrottler::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->auth = new \OCA\DAV\Connector\PublicAuth(
- $this->request,
- $this->shareManager,
- $this->session,
- $this->throttler
- );
-
- // Store current user
- $this->oldUser = \OC_User::getUser();
- }
-
- protected function tearDown(): void {
- \OC_User::setIncognitoMode(false);
-
- // Set old user
- \OC_User::setUserId($this->oldUser);
- \OC_Util::setupFS($this->oldUser);
-
- parent::tearDown();
- }
-
- public function testNoShare(): void {
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willThrowException(new ShareNotFound());
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertFalse($result);
- }
-
- public function testShareNoPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn(null);
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertTrue($result);
- }
-
- public function testSharePasswordFancyShareType(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(42);
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertFalse($result);
- }
-
-
- public function testSharePasswordRemote(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertTrue($result);
- }
-
- public function testSharePasswordLinkValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $this->shareManager->expects($this->once())
- ->method('checkPassword')->with(
- $this->equalTo($share),
- $this->equalTo('password')
- )->willReturn(true);
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertTrue($result);
- }
-
- public function testSharePasswordMailValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $this->shareManager->expects($this->once())
- ->method('checkPassword')->with(
- $this->equalTo($share),
- $this->equalTo('password')
- )->willReturn(true);
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertTrue($result);
- }
-
- public function testSharePasswordLinkValidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
- $share->method('getId')->willReturn('42');
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $this->shareManager->method('checkPassword')
- ->with(
- $this->equalTo($share),
- $this->equalTo('password')
- )->willReturn(false);
-
- $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
- $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertTrue($result);
- }
-
- public function testSharePasswordLinkInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
- $share->method('getId')->willReturn('42');
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $this->shareManager->method('checkPassword')
- ->with(
- $this->equalTo($share),
- $this->equalTo('password')
- )->willReturn(false);
-
- $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
- $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertFalse($result);
- }
-
-
- public function testSharePasswordMailInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
- $share->method('getId')->willReturn('42');
-
- $this->shareManager->expects($this->once())
- ->method('getShareByToken')
- ->willReturn($share);
-
- $this->shareManager->method('checkPassword')
- ->with(
- $this->equalTo($share),
- $this->equalTo('password')
- )->willReturn(false);
-
- $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
- $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
-
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
-
- $this->assertFalse($result);
- }
-}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ *
+ * @author Bjoern Schiessle <bjoern@schiessle.org>
+ * @author Joas Schilling <coding@schilljs.com>
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @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 OCA\DAV\Tests\unit\Connector;
+
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\Security\Bruteforce\IThrottler;
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IManager;
+use OCP\Share\IShare;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class PublicAuthTest
+ *
+ * @group DB
+ *
+ * @package OCA\DAV\Tests\unit\Connector
+ */
+class PublicAuthTest extends \Test\TestCase {
+
+ /** @var ISession|MockObject */
+ private $session;
+ /** @var IRequest|MockObject */
+ private $request;
+ /** @var IManager|MockObject */
+ private $shareManager;
+ /** @var PublicAuth */
+ private $auth;
+ /** @var IThrottler|MockObject */
+ private $throttler;
+ /** @var LoggerInterface|MockObject */
+ private $logger;
+
+ /** @var string */
+ private $oldUser;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->session = $this->getMockBuilder(ISession::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->request = $this->getMockBuilder(IRequest::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->shareManager = $this->getMockBuilder(IManager::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->throttler = $this->getMockBuilder(IThrottler::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->logger = $this->createMock(LoggerInterface::class);
+
+ $this->auth = new \OCA\DAV\Connector\Sabre\PublicAuth(
+ $this->request,
+ $this->shareManager,
+ $this->session,
+ $this->throttler,
+ $this->logger,
+ );
+
+ // Store current user
+ $this->oldUser = \OC_User::getUser();
+ }
+
+ protected function tearDown(): void {
+ \OC_User::setIncognitoMode(false);
+
+ // Set old user
+ \OC_User::setUserId($this->oldUser);
+ \OC_Util::setupFS($this->oldUser);
+
+ parent::tearDown();
+ }
+
+ public function testGetToken(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $result = $this->invokePrivate($this->auth, 'getToken');
+
+ $this->assertSame('GX9HSGQrGE', $result);
+ }
+
+ public function testGetTokenInvalid(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files');
+
+ $this->expectException(\Sabre\DAV\Exception\NotFound::class);
+ $this->invokePrivate($this->auth, 'getToken');
+ }
+
+ public function testCheckTokenValidShare(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn(null);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'checkToken');
+ $this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
+ }
+
+ public function testCheckTokenInvalidShare(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $this->shareManager
+ ->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->will($this->throwException(new ShareNotFound()));
+
+ $this->expectException(\Sabre\DAV\Exception\NotFound::class);
+ $this->invokePrivate($this->auth, 'checkToken');
+ }
+
+ public function testCheckTokenAlreadyAuthenticated(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getShareType')->willReturn(42);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
+
+ $result = $this->invokePrivate($this->auth, 'checkToken');
+ $this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
+ }
+
+ public function testCheckTokenPasswordNotAuthenticated(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(42);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
+
+ $this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
+ $this->invokePrivate($this->auth, 'checkToken');
+ }
+
+ public function testCheckTokenPasswordAuthenticatedWrongShare(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(42);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
+
+ $this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
+ $this->invokePrivate($this->auth, 'checkToken');
+ }
+
+ public function testNoShare(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willThrowException(new ShareNotFound());
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+ public function testShareNoPassword(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn(null);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordFancyShareType(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(42);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+
+ public function testSharePasswordRemote(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordLinkValidPassword(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(true);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordMailValidPassword(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(true);
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testInvalidSharePasswordLinkValidSession(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertTrue($result);
+ }
+
+ public function testSharePasswordLinkInvalidSession(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+
+
+ public function testSharePasswordMailInvalidSession(): void {
+ $this->request->method('getPathInfo')
+ ->willReturn('/dav/files/GX9HSGQrGE');
+
+ $share = $this->getMockBuilder(IShare::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $share->method('getPassword')->willReturn('password');
+ $share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
+ $share->method('getId')->willReturn('42');
+
+ $this->shareManager->expects($this->once())
+ ->method('getShareByToken')
+ ->with('GX9HSGQrGE')
+ ->willReturn($share);
+
+ $this->shareManager->expects($this->once())
+ ->method('checkPassword')
+ ->with(
+ $this->equalTo($share),
+ $this->equalTo('password')
+ )->willReturn(false);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('43');
+
+ $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+
+ $this->assertFalse($result);
+ }
+}
var filesClient = new OC.Files.Client({
host: OC.getHost(),
port: OC.getPort(),
- userName: $('#sharingToken').val(),
// note: password not be required, the endpoint
// will recognize previous validation from the session
- root: OC.getRootPath() + '/public.php/webdav',
+ root: OC.getRootPath() + '/public.php/dav/files/' + $('#sharingToken').val() + '/',
useHTTPS: OC.getProtocol() === 'https'
});
return false;
}
var base = OC.getProtocol() + '://' + OC.getHost();
- data.url = base + OC.getRootPath() + '/public.php/webdav/' + encodeURI(name);
+ data.url = base + OC.getRootPath() + '/public.php/dav/files/' + $('#sharingToken').val() + '/' + encodeURI(name);
data.multipart = false;
data.headers = {};
}
- var userName = filesClient.getUserName();
- var password = filesClient.getPassword();
- if (userName) {
- // copy username/password from DAV client
- data.headers['Authorization'] =
- 'Basic ' + btoa(userName + ':' + (password || ''));
- }
-
$('#drop-upload-done-indicator').addClass('hidden');
$('#drop-upload-progress-indicator').removeClass('hidden');
var filesClient = new OC.Files.Client({
host: OC.getHost(),
port: OC.getPort(),
- userName: token,
// note: password not be required, the endpoint
// will recognize previous validation from the session
- root: OC.getRootPath() + '/public.php/webdav',
+ root: OC.getRootPath() + '/public.php/dav/files/' + token + '/',
useHTTPS: OC.getProtocol() === 'https'
});
return;
}
// Undocumented Url to public WebDAV endpoint
- var url = parent.location.protocol + '//' + location.host + OC.linkTo('', 'public.php/webdav');
+ var url = parent.location.protocol + '//' + location.host + OC.linkTo('', 'public.php/dav/files/'+ token);
$.ajax({
url: url,
headers: {
- Authorization: 'Basic ' + btoa(token + ':'),
Range: 'bytes=0-10000'
}
}).then(function (data) {
// also add auth in URL due to POST workaround
base = OC.getProtocol() + '://' + token + '@' + OC.getHost() + (OC.getPort() ? ':' + OC.getPort() : '');
}
- return base + OC.getRootPath() + '/public.php/webdav' + encodedPath;
+
+ // encodedPath starts with a leading slash
+ return base + OC.getRootPath() + '/public.php/dav/files/' + token + encodedPath;
};
this.fileList.getAjaxUrl = function (action, params) {
$this->previewManager = $previewManager;
}
- protected function getPasswordHash(): string {
+ protected function getPasswordHash(): ?string {
return $this->share->getPassword();
}
return $this->shareManager->checkPassword($this->share, $password);
}
- protected function getPasswordHash(): string {
+ protected function getPasswordHash(): ?string {
return $this->share->getPassword();
}
* mimetype: string,
* note: string,
* parent: null,
- * password?: string,
+ * password?: null|string,
* password_expiration_time?: ?string,
* path: ?string,
* permissions: int,
* send_password_by_talk?: bool,
* share_type: int,
- * share_with?: string,
+ * share_with?: null|string,
* share_with_avatar?: string,
* share_with_displayname?: string,
* share_with_displayname_unique?: ?string,
* share_with_link?: string,
- * status?: array{clearAt?: int|null, icon?: ?string, message?: ?string, status?: string},
+ * status?: array{clearAt: int|null, icon: ?string, message: ?string, status: string},
* stime: int,
* storage: int,
* storage_id: string,
"nullable": true
},
"password": {
- "type": "string"
+ "type": "string",
+ "nullable": true
},
"password_expiration_time": {
"type": "string",
"format": "int64"
},
"share_with": {
- "type": "string"
+ "type": "string",
+ "nullable": true
},
"share_with_avatar": {
"type": "string"
},
"status": {
"type": "object",
+ "required": [
+ "clearAt",
+ "icon",
+ "message",
+ "status"
+ ],
"properties": {
"clearAt": {
"type": "integer",
OCA.FilesSharingDrop.addFileToUpload('',data);
expect(data.submit.calledOnce).toEqual(true);
- expect(data.url).toContain("/public.php/webdav/" + encodeURI(testFile.name));
- expect(data.headers['Authorization']).toEqual('Basic ' + btoa(sharingToken+":"));
+ expect(data.url).toContain("/public.php/dav/files/" + sharingToken + '/' + encodeURI(testFile.name));
});
}
});
App.initialize($('#preview'));
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('PROPFIND');
- expect(fakeServer.requests[0].url).toEqual('https://example.com:9876/owncloud/public.php/webdav/subdir');
- expect(fakeServer.requests[0].requestHeaders.Authorization).toEqual('Basic c2g0dG9rOm51bGw=');
+ expect(fakeServer.requests[0].url).toEqual('https://example.com:9876/owncloud/public.php/dav/files/sh4tok/subdir');
uploaderDetectStub.restore();
});
});
it('returns correct upload URL', function() {
expect(fileList.getUploadUrl('some file.txt'))
- .toEqual('/owncloud/public.php/webdav/subdir/some%20file.txt');
+ .toEqual('/owncloud/public.php/dav/files/sh4tok/subdir/some%20file.txt');
});
it('returns correct upload URL with specified dir', function() {
expect(fileList.getUploadUrl('some file.txt', 'sub'))
- .toEqual('/owncloud/public.php/webdav/sub/some%20file.txt');
+ .toEqual('/owncloud/public.php/dav/files/sh4tok/sub/some%20file.txt');
});
});
});
}
$base = substr($this->baseUrl, 0, -4);
- $fullUrl = $base . '/public.php/webdav' . $path;
+ $fullUrl = $base . "/public.php/dav/files/$token/$path";
- $options['auth'] = [$token, ''];
$options['headers'] = [
'X-REQUESTED-WITH' => 'XMLHttpRequest'
];
}
$base = substr($this->baseUrl, 0, -4);
- $fullUrl = $base . '/public.php/webdav/' . $folder;
+ $fullUrl = $base . "/public.php/dav/files/$token/$folder";
- $options['auth'] = [$token, ''];
$options['headers'] = [
'X-REQUESTED-WITH' => 'XMLHttpRequest'
];
$token = $this->lastShareData->data->token;
}
- $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav";
- $this->checkDownload($fullUrl, [$token, $password], 'text/plain');
+ $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/";
+ $this->checkDownload($fullUrl, ['', $password], 'text/plain');
}
private function checkDownload($url, $auth = null, $mimeType = null) {
*/
public function downloadPublicFileWithRange($range) {
$token = $this->lastShareData->data->token;
- $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav";
+ $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token";
$client = new GClient();
$options = [];
- $options['auth'] = [$token, ""];
$options['headers'] = [
'Range' => $range
];
*/
public function downloadPublicFileInsideAFolderWithRange($path, $range) {
$token = $this->lastShareData->data->token;
- $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav" . "$path";
+ $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$path";
$client = new GClient();
$options = [
'Range' => $range
]
];
- $options['auth'] = [$token, ""];
$this->response = $client->request("GET", $fullUrl, $options);
}
Then the HTTP status code should be "503"
Then Maintenance mode is disabled
And the command was successful
+
+ Scenario: Accessing /public.php/dav with maintenance mode enabled
+ When requesting "/public.php/dav" with "GET"
+ Then the HTTP status code should be "503"
+ Then Maintenance mode is disabled
+ And the command was successful
<code>$baseuri</code>
</UndefinedGlobalVariable>
</file>
+ <file src="apps/dav/appinfo/v2/publicremote.php">
+ <InternalMethod>
+ <code>\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($previousLog)</code>
+ <code>\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false)</code>
+ </InternalMethod>
+ <UndefinedGlobalVariable>
+ <code>$baseuri</code>
+ <code>$baseuri</code>
+ </UndefinedGlobalVariable>
+ </file>
<file src="apps/dav/lib/AppInfo/Application.php">
<InvalidArgument>
<code>CalendarDeletionDefaultUpdaterListener::class</code>
*
* @since 14.0.0
*/
- abstract protected function getPasswordHash(): string;
+ abstract protected function getPasswordHash(): ?string;
/**
* Is the provided token a valid token