diff options
Diffstat (limited to 'apps/files_external/tests/Controller')
4 files changed, 739 insertions, 0 deletions
diff --git a/apps/files_external/tests/Controller/AjaxControllerTest.php b/apps/files_external/tests/Controller/AjaxControllerTest.php new file mode 100644 index 00000000000..b1ea7a2b1b1 --- /dev/null +++ b/apps/files_external/tests/Controller/AjaxControllerTest.php @@ -0,0 +1,152 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Files_External\Tests\Controller; + +use OCA\Files_External\Controller\AjaxController; +use OCA\Files_External\Lib\Auth\Password\GlobalAuth; +use OCA\Files_External\Lib\Auth\PublicKey\RSA; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IGroupManager; +use OCP\IL10N; +use OCP\IRequest; +use OCP\IUser; +use OCP\IUserSession; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class AjaxControllerTest extends TestCase { + private IRequest&MockObject $request; + private RSA&MockObject $rsa; + private GlobalAuth&MockObject $globalAuth; + private IUserSession&MockObject $userSession; + private IGroupManager&MockObject $groupManager; + private IL10N&MockObject $l10n; + private AjaxController $ajaxController; + + protected function setUp(): void { + $this->request = $this->createMock(IRequest::class); + $this->rsa = $this->createMock(RSA::class); + $this->globalAuth = $this->createMock(GlobalAuth::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->groupManager = $this->createMock(IGroupManager::class); + $this->l10n = $this->createMock(IL10N::class); + + $this->ajaxController = new AjaxController( + 'files_external', + $this->request, + $this->rsa, + $this->globalAuth, + $this->userSession, + $this->groupManager, + $this->l10n, + ); + + $this->l10n->expects($this->any()) + ->method('t') + ->willReturnCallback(function ($string, $args) { + if (!is_array($args)) { + $args = [$args]; + } + return vsprintf($string, $args); + }); + + parent::setUp(); + } + + public function testGetSshKeys(): void { + $this->rsa + ->expects($this->once()) + ->method('createKey') + ->willReturn([ + 'privatekey' => 'MyPrivateKey', + 'publickey' => 'MyPublicKey', + ]); + + $expected = new JSONResponse( + [ + 'data' => [ + 'private_key' => 'MyPrivateKey', + 'public_key' => 'MyPublicKey', + ], + 'status' => 'success', + ] + ); + $this->assertEquals($expected, $this->ajaxController->getSshKeys()); + } + + public function testSaveGlobalCredentialsAsAdminForAnotherUser(): void { + $user = $this->createMock(IUser::class); + $user + ->expects($this->once()) + ->method('getUID') + ->willReturn('MyAdminUid'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($user); + $this->globalAuth + ->expects($this->never()) + ->method('saveAuth'); + + $response = $this->ajaxController->saveGlobalCredentials('UidOfTestUser', 'test', 'password'); + $this->assertSame($response->getStatus(), 403); + $this->assertSame('Permission denied', $response->getData()['message']); + } + + public function testSaveGlobalCredentialsAsAdminForSelf(): void { + $user = $this->createMock(IUser::class); + $user + ->expects($this->once()) + ->method('getUID') + ->willReturn('MyAdminUid'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($user); + $this->globalAuth + ->expects($this->once()) + ->method('saveAuth') + ->with('MyAdminUid', 'test', 'password'); + + $response = $this->ajaxController->saveGlobalCredentials('MyAdminUid', 'test', 'password'); + $this->assertSame($response->getStatus(), 200); + } + + public function testSaveGlobalCredentialsAsNormalUserForSelf(): void { + $user = $this->createMock(IUser::class); + $user + ->method('getUID') + ->willReturn('MyUserUid'); + $this->userSession + ->method('getUser') + ->willReturn($user); + $this->globalAuth + ->method('saveAuth') + ->with('MyUserUid', 'test', 'password'); + + $response = $this->ajaxController->saveGlobalCredentials('MyUserUid', 'test', 'password'); + $this->assertSame($response->getStatus(), 200); + } + + public function testSaveGlobalCredentialsAsNormalUserForAnotherUser(): void { + $user = $this->createMock(IUser::class); + $user + ->method('getUID') + ->willReturn('MyUserUid'); + $this->userSession + ->method('getUser') + ->willReturn($user); + $this->globalAuth + ->expects($this->never()) + ->method('saveAuth'); + + $response = $this->ajaxController->saveGlobalCredentials('AnotherUserUid', 'test', 'password'); + $this->assertSame($response->getStatus(), 403); + $this->assertSame('Permission denied', $response->getData()['message']); + } +} diff --git a/apps/files_external/tests/Controller/GlobalStoragesControllerTest.php b/apps/files_external/tests/Controller/GlobalStoragesControllerTest.php new file mode 100644 index 00000000000..74a27eb15e4 --- /dev/null +++ b/apps/files_external/tests/Controller/GlobalStoragesControllerTest.php @@ -0,0 +1,60 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Tests\Controller; + +use OC\User\User; +use OCA\Files_External\Controller\GlobalStoragesController; +use OCA\Files_External\Service\BackendService; +use OCA\Files_External\Service\GlobalStoragesService; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IL10N; +use OCP\IRequest; +use OCP\IUserSession; +use Psr\Log\LoggerInterface; + +class GlobalStoragesControllerTest extends StoragesControllerTestCase { + protected function setUp(): void { + parent::setUp(); + + $this->service = $this->createMock(GlobalStoragesService::class); + + $this->service->method('getVisibilityType') + ->willReturn(BackendService::VISIBILITY_ADMIN); + + $this->controller = $this->createController(true); + } + + private function createController(bool $allowCreateLocal = true): GlobalStoragesController { + $session = $this->createMock(IUserSession::class); + $session->method('getUser') + ->willReturn(new User('test', null, $this->createMock(IEventDispatcher::class))); + + $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('files_external_allow_create_new_local', true) + ->willReturn($allowCreateLocal); + + return new GlobalStoragesController( + 'files_external', + $this->createMock(IRequest::class), + $this->createMock(IL10N::class), + $this->service, + $this->createMock(LoggerInterface::class), + $session, + $this->createMock(IGroupManager::class), + $config + ); + } + + public function testAddLocalStorageWhenDisabled(): void { + $this->controller = $this->createController(false); + parent::testAddLocalStorageWhenDisabled(); + } +} diff --git a/apps/files_external/tests/Controller/StoragesControllerTestCase.php b/apps/files_external/tests/Controller/StoragesControllerTestCase.php new file mode 100644 index 00000000000..1eb52f9b459 --- /dev/null +++ b/apps/files_external/tests/Controller/StoragesControllerTestCase.php @@ -0,0 +1,409 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Tests\Controller; + +use OCA\Files_External\Controller\GlobalStoragesController; +use OCA\Files_External\Controller\UserStoragesController; +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\NullMechanism; +use OCA\Files_External\Lib\Backend\Backend; +use OCA\Files_External\Lib\Backend\SMB; +use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\MountConfig; +use OCA\Files_External\NotFoundException; +use OCA\Files_External\Service\GlobalStoragesService; +use OCA\Files_External\Service\UserStoragesService; +use OCP\AppFramework\Http; +use PHPUnit\Framework\MockObject\MockObject; + +abstract class StoragesControllerTestCase extends \Test\TestCase { + protected GlobalStoragesController|UserStoragesController $controller; + protected GlobalStoragesService|UserStoragesService|MockObject $service; + + protected function setUp(): void { + parent::setUp(); + MountConfig::$skipTest = true; + } + + protected function tearDown(): void { + MountConfig::$skipTest = false; + parent::tearDown(); + } + + /** + * @return \OCA\Files_External\Lib\Backend\Backend&MockObject + */ + protected function getBackendMock($class = SMB::class, $storageClass = \OCA\Files_External\Lib\Storage\SMB::class) { + $backend = $this->createMock(Backend::class); + $backend->method('getStorageClass') + ->willReturn($storageClass); + $backend->method('getIdentifier') + ->willReturn('identifier:' . $class); + $backend->method('getParameters') + ->willReturn([]); + return $backend; + } + + /** + * @return AuthMechanism|MockObject + */ + protected function getAuthMechMock($scheme = 'null', $class = NullMechanism::class) { + $authMech = $this->createMock(AuthMechanism::class); + $authMech->method('getScheme') + ->willReturn($scheme); + $authMech->method('getIdentifier') + ->willReturn('identifier:' . $class); + $authMech->method('getParameters') + ->willReturn([]); + + return $authMech; + } + + public function testAddStorage(): void { + $authMech = $this->getAuthMechMock(); + $authMech->method('validateStorage') + ->willReturn(true); + $authMech->method('isVisibleFor') + ->willReturn(true); + $backend = $this->getBackendMock(); + $backend->method('validateStorage') + ->willReturn(true); + $backend->method('isVisibleFor') + ->willReturn(true); + + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->once()) + ->method('createStorage') + ->willReturn($storageConfig); + $this->service->expects($this->once()) + ->method('addStorage') + ->willReturn($storageConfig); + + $response = $this->controller->create( + 'mount', + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $data = $response->getData(); + $this->assertEquals(Http::STATUS_CREATED, $response->getStatus()); + $this->assertEquals($storageConfig->jsonSerialize(), $data); + } + + public function testAddLocalStorageWhenDisabled(): void { + $authMech = $this->getAuthMechMock(); + $backend = $this->getBackendMock(); + + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->never()) + ->method('createStorage'); + $this->service->expects($this->never()) + ->method('addStorage'); + + $response = $this->controller->create( + 'mount', + 'local', + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $data = $response->getData(); + $this->assertEquals(Http::STATUS_FORBIDDEN, $response->getStatus()); + } + + public function testUpdateStorage(): void { + $authMech = $this->getAuthMechMock(); + $authMech->method('validateStorage') + ->willReturn(true); + $authMech->method('isVisibleFor') + ->willReturn(true); + $backend = $this->getBackendMock(); + $backend->method('validateStorage') + ->willReturn(true); + $backend->method('isVisibleFor') + ->willReturn(true); + + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->once()) + ->method('createStorage') + ->willReturn($storageConfig); + $this->service->expects($this->once()) + ->method('updateStorage') + ->willReturn($storageConfig); + + $response = $this->controller->update( + 1, + 'mount', + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $data = $response->getData(); + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + $this->assertEquals($storageConfig->jsonSerialize(), $data); + } + + public static function mountPointNamesProvider(): array { + return [ + [''], + ['/'], + ['//'], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('mountPointNamesProvider')] + public function testAddOrUpdateStorageInvalidMountPoint($mountPoint): void { + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint($mountPoint); + $storageConfig->setBackend($this->getBackendMock()); + $storageConfig->setAuthMechanism($this->getAuthMechMock()); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->exactly(2)) + ->method('createStorage') + ->willReturn($storageConfig); + $this->service->expects($this->never()) + ->method('addStorage'); + $this->service->expects($this->never()) + ->method('updateStorage'); + + $response = $this->controller->create( + $mountPoint, + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + + $response = $this->controller->update( + 1, + $mountPoint, + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + } + + public function testAddOrUpdateStorageInvalidBackend(): void { + $this->service->expects($this->exactly(2)) + ->method('createStorage') + ->willThrowException(new \InvalidArgumentException()); + $this->service->expects($this->never()) + ->method('addStorage'); + $this->service->expects($this->never()) + ->method('updateStorage'); + + $response = $this->controller->create( + 'mount', + '\OC\Files\Storage\InvalidStorage', + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + + $response = $this->controller->update( + 1, + 'mount', + '\OC\Files\Storage\InvalidStorage', + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + } + + public function testUpdateStorageNonExisting(): void { + $authMech = $this->getAuthMechMock(); + $authMech->method('validateStorage') + ->willReturn(true); + $authMech->method('isVisibleFor') + ->willReturn(true); + $backend = $this->getBackendMock(); + $backend->method('validateStorage') + ->willReturn(true); + $backend->method('isVisibleFor') + ->willReturn(true); + + $storageConfig = new StorageConfig(255); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->once()) + ->method('createStorage') + ->willReturn($storageConfig); + $this->service->expects($this->once()) + ->method('updateStorage') + ->willThrowException(new NotFoundException()); + + $response = $this->controller->update( + 255, + 'mount', + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); + } + + public function testDeleteStorage(): void { + $this->service->expects($this->once()) + ->method('removeStorage'); + + $response = $this->controller->destroy(1); + $this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus()); + } + + public function testDeleteStorageNonExisting(): void { + $this->service->expects($this->once()) + ->method('removeStorage') + ->willThrowException(new NotFoundException()); + + $response = $this->controller->destroy(255); + $this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); + } + + public function testGetStorage(): void { + $backend = $this->getBackendMock(); + $authMech = $this->getAuthMechMock(); + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint('test'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions(['user' => 'test', 'password', 'password123']); + $storageConfig->setMountOptions(['priority' => false]); + + $this->service->expects($this->once()) + ->method('getStorage') + ->with(1) + ->willReturn($storageConfig); + $response = $this->controller->show(1); + + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + $expected = $storageConfig->jsonSerialize(); + $expected['can_edit'] = false; + $this->assertEquals($expected, $response->getData()); + } + + public static function validateStorageProvider(): array { + return [ + [true, true, true], + [false, true, false], + [true, false, false], + [false, false, false] + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('validateStorageProvider')] + public function testValidateStorage(bool $backendValidate, bool $authMechValidate, bool $expectSuccess): void { + $backend = $this->getBackendMock(); + $backend->method('validateStorage') + ->willReturn($backendValidate); + $backend->method('isVisibleFor') + ->willReturn(true); + + $authMech = $this->getAuthMechMock(); + $authMech->method('validateStorage') + ->willReturn($authMechValidate); + $authMech->method('isVisibleFor') + ->willReturn(true); + + $storageConfig = new StorageConfig(); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->once()) + ->method('createStorage') + ->willReturn($storageConfig); + + if ($expectSuccess) { + $this->service->expects($this->once()) + ->method('addStorage') + ->with($storageConfig) + ->willReturn($storageConfig); + } else { + $this->service->expects($this->never()) + ->method('addStorage'); + } + + $response = $this->controller->create( + 'mount', + \OCA\Files_External\Lib\Storage\SMB::class, + NullMechanism::class, + [], + [], + [], + [], + null + ); + + if ($expectSuccess) { + $this->assertEquals(Http::STATUS_CREATED, $response->getStatus()); + } else { + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + } + } +} diff --git a/apps/files_external/tests/Controller/UserStoragesControllerTest.php b/apps/files_external/tests/Controller/UserStoragesControllerTest.php new file mode 100644 index 00000000000..3e8d89ec060 --- /dev/null +++ b/apps/files_external/tests/Controller/UserStoragesControllerTest.php @@ -0,0 +1,118 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Tests\Controller; + +use OC\User\User; +use OCA\Files_External\Controller\UserStoragesController; +use OCA\Files_External\Lib\Storage\SMB; +use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\Service\BackendService; +use OCA\Files_External\Service\UserStoragesService; +use OCP\AppFramework\Http; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IL10N; +use OCP\IRequest; +use OCP\IUserSession; +use Psr\Log\LoggerInterface; + +class UserStoragesControllerTest extends StoragesControllerTestCase { + + /** + * @var array + */ + private array $oldAllowedBackends; + + protected function setUp(): void { + parent::setUp(); + $this->service = $this->createMock(UserStoragesService::class); + + $this->service->method('getVisibilityType') + ->willReturn(BackendService::VISIBILITY_PERSONAL); + + $this->controller = $this->createController(true); + } + + private function createController(bool $allowCreateLocal = true) { + $session = $this->createMock(IUserSession::class); + $session->method('getUser') + ->willReturn(new User('test', null, $this->createMock(IEventDispatcher::class))); + + $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('files_external_allow_create_new_local', true) + ->willReturn($allowCreateLocal); + + return new UserStoragesController( + 'files_external', + $this->createMock(IRequest::class), + $this->createMock(IL10N::class), + $this->service, + $this->createMock(LoggerInterface::class), + $session, + $this->createMock(IGroupManager::class), + $config + ); + } + + public function testAddLocalStorageWhenDisabled(): void { + $this->controller = $this->createController(false); + parent::testAddLocalStorageWhenDisabled(); + } + + public function testAddOrUpdateStorageDisallowedBackend(): void { + $backend = $this->getBackendMock(); + $backend->method('isVisibleFor') + ->with(BackendService::VISIBILITY_PERSONAL) + ->willReturn(false); + $authMech = $this->getAuthMechMock(); + + $storageConfig = new StorageConfig(1); + $storageConfig->setMountPoint('mount'); + $storageConfig->setBackend($backend); + $storageConfig->setAuthMechanism($authMech); + $storageConfig->setBackendOptions([]); + + $this->service->expects($this->exactly(2)) + ->method('createStorage') + ->willReturn($storageConfig); + $this->service->expects($this->never()) + ->method('addStorage'); + $this->service->expects($this->never()) + ->method('updateStorage'); + + $response = $this->controller->create( + 'mount', + SMB::class, + '\Auth\Mechanism', + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + + $response = $this->controller->update( + 1, + 'mount', + SMB::class, + '\Auth\Mechanism', + [], + [], + [], + [], + null + ); + + $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); + } +} |