123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- <?php
- /**
- * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
- * SPDX-License-Identifier: AGPL-3.0-only
- */
- namespace Test\Encryption;
- use OC\Encryption\DecryptAll;
- use OC\Encryption\Exceptions\DecryptionFailedException;
- use OC\Encryption\Manager;
- use OC\Files\FileInfo;
- use OC\Files\View;
- use OCP\Files\Storage\IStorage;
- use OCP\IUserManager;
- use OCP\UserInterface;
- use Symfony\Component\Console\Formatter\OutputFormatterInterface;
- use Symfony\Component\Console\Helper\ProgressBar;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Test\TestCase;
- /**
- * Class DecryptAllTest
- *
- * @group DB
- *
- * @package Test\Encryption
- */
- class DecryptAllTest extends TestCase {
- /** @var \PHPUnit\Framework\MockObject\MockObject | IUserManager */
- protected $userManager;
- /** @var \PHPUnit\Framework\MockObject\MockObject | Manager */
- protected $encryptionManager;
- /** @var \PHPUnit\Framework\MockObject\MockObject | View */
- protected $view;
- /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Input\InputInterface */
- protected $inputInterface;
- /** @var \PHPUnit\Framework\MockObject\MockObject | \Symfony\Component\Console\Output\OutputInterface */
- protected $outputInterface;
- /** @var \PHPUnit\Framework\MockObject\MockObject | \OCP\UserInterface */
- protected $userInterface;
- /** @var DecryptAll */
- protected $instance;
- protected function setUp(): void {
- parent::setUp();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()->getMock();
- $this->encryptionManager = $this->getMockBuilder('OC\Encryption\Manager')
- ->disableOriginalConstructor()->getMock();
- $this->view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()->getMock();
- $this->inputInterface = $this->getMockBuilder(InputInterface::class)
- ->disableOriginalConstructor()->getMock();
- $this->outputInterface = $this->getMockBuilder(OutputInterface::class)
- ->disableOriginalConstructor()->getMock();
- $this->outputInterface->expects($this->any())->method('isDecorated')
- ->willReturn(false);
- $this->userInterface = $this->getMockBuilder(UserInterface::class)
- ->disableOriginalConstructor()->getMock();
- /* We need format method to return a string */
- $outputFormatter = $this->createMock(OutputFormatterInterface::class);
- $outputFormatter->method('format')->willReturn('foo');
- $outputFormatter->method('isDecorated')->willReturn(false);
- $this->outputInterface->expects($this->any())->method('getFormatter')
- ->willReturn($outputFormatter);
- $this->instance = new DecryptAll($this->encryptionManager, $this->userManager, $this->view);
- $this->invokePrivate($this->instance, 'input', [$this->inputInterface]);
- $this->invokePrivate($this->instance, 'output', [$this->outputInterface]);
- }
- public function dataDecryptAll() {
- return [
- [true, 'user1', true],
- [false, 'user1', true],
- [true, '0', true],
- [false, '0', true],
- [true, '', false],
- ];
- }
- /**
- * @dataProvider dataDecryptAll
- * @param bool $prepareResult
- * @param string $user
- * @param bool $userExistsChecked
- */
- public function testDecryptAll($prepareResult, $user, $userExistsChecked): void {
- if ($userExistsChecked) {
- $this->userManager->expects($this->once())->method('userExists')->willReturn(true);
- } else {
- $this->userManager->expects($this->never())->method('userExists');
- }
- /** @var DecryptAll | \PHPUnit\Framework\MockObject\MockObject | $instance */
- $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
- ->setConstructorArgs(
- [
- $this->encryptionManager,
- $this->userManager,
- $this->view
- ]
- )
- ->setMethods(['prepareEncryptionModules', 'decryptAllUsersFiles'])
- ->getMock();
- $instance->expects($this->once())
- ->method('prepareEncryptionModules')
- ->with($user)
- ->willReturn($prepareResult);
- if ($prepareResult) {
- $instance->expects($this->once())
- ->method('decryptAllUsersFiles')
- ->with($user);
- } else {
- $instance->expects($this->never())->method('decryptAllUsersFiles');
- }
- $instance->decryptAll($this->inputInterface, $this->outputInterface, $user);
- }
- /**
- * test decrypt all call with a user who doesn't exists
- */
- public function testDecryptAllWrongUser(): void {
- $this->userManager->expects($this->once())->method('userExists')->willReturn(false);
- $this->outputInterface->expects($this->once())->method('writeln')
- ->with('User "user1" does not exist. Please check the username and try again');
- $this->assertFalse(
- $this->instance->decryptAll($this->inputInterface, $this->outputInterface, 'user1')
- );
- }
- public function dataTrueFalse() {
- return [
- [true],
- [false],
- ];
- }
- /**
- * @dataProvider dataTrueFalse
- * @param bool $success
- */
- public function testPrepareEncryptionModules($success): void {
- $user = 'user1';
- $dummyEncryptionModule = $this->getMockBuilder('OCP\Encryption\IEncryptionModule')
- ->disableOriginalConstructor()->getMock();
- $dummyEncryptionModule->expects($this->once())
- ->method('prepareDecryptAll')
- ->with($this->inputInterface, $this->outputInterface, $user)
- ->willReturn($success);
- $callback = function () use ($dummyEncryptionModule) {
- return $dummyEncryptionModule;
- };
- $moduleDescription = [
- 'id' => 'id',
- 'displayName' => 'displayName',
- 'callback' => $callback
- ];
- $this->encryptionManager->expects($this->once())
- ->method('getEncryptionModules')
- ->willReturn([$moduleDescription]);
- $this->assertSame($success,
- $this->invokePrivate($this->instance, 'prepareEncryptionModules', [$user])
- );
- }
- /**
- * @dataProvider dataTestDecryptAllUsersFiles
- */
- public function testDecryptAllUsersFiles($user): void {
- /** @var DecryptAll | \PHPUnit\Framework\MockObject\MockObject | $instance */
- $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
- ->setConstructorArgs(
- [
- $this->encryptionManager,
- $this->userManager,
- $this->view
- ]
- )
- ->setMethods(['decryptUsersFiles'])
- ->getMock();
- $this->invokePrivate($instance, 'input', [$this->inputInterface]);
- $this->invokePrivate($instance, 'output', [$this->outputInterface]);
- if (empty($user)) {
- $this->userManager->expects($this->once())
- ->method('getBackends')
- ->willReturn([$this->userInterface]);
- $this->userInterface->expects($this->any())
- ->method('getUsers')
- ->willReturn(['user1', 'user2']);
- $instance->expects($this->exactly(2))
- ->method('decryptUsersFiles')
- ->withConsecutive(
- ['user1'],
- ['user2'],
- );
- } else {
- $instance->expects($this->once())
- ->method('decryptUsersFiles')
- ->with($user);
- }
- $this->invokePrivate($instance, 'decryptAllUsersFiles', [$user]);
- }
- public function dataTestDecryptAllUsersFiles() {
- return [
- ['user1'],
- ['']
- ];
- }
- public function testDecryptUsersFiles(): void {
- /** @var DecryptAll | \PHPUnit\Framework\MockObject\MockObject $instance */
- $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
- ->setConstructorArgs(
- [
- $this->encryptionManager,
- $this->userManager,
- $this->view
- ]
- )
- ->setMethods(['decryptFile'])
- ->getMock();
- $storage = $this->getMockBuilder(IStorage::class)
- ->disableOriginalConstructor()->getMock();
- $sharedStorage = $this->getMockBuilder(IStorage::class)
- ->disableOriginalConstructor()->getMock();
- $sharedStorage->expects($this->once())->method('instanceOfStorage')
- ->with('OCA\Files_Sharing\SharedStorage')->willReturn(true);
- $this->view->expects($this->exactly(2))
- ->method('getDirectoryContent')
- ->withConsecutive(
- ['/user1/files'],
- ['/user1/files/foo']
- )
- ->willReturnOnConsecutiveCalls(
- [
- new FileInfo('path', $storage, 'intPath', ['name' => 'foo', 'type' => 'dir'], null),
- new FileInfo('path', $storage, 'intPath', ['name' => 'bar', 'type' => 'file', 'encrypted' => true], null),
- new FileInfo('path', $sharedStorage, 'intPath', ['name' => 'shared', 'type' => 'file', 'encrypted' => true], null),
- ],
- [
- new FileInfo('path', $storage, 'intPath', ['name' => 'subfile', 'type' => 'file', 'encrypted' => true], null)
- ]
- );
- $this->view->expects($this->any())->method('is_dir')
- ->willReturnCallback(
- function ($path) {
- if ($path === '/user1/files/foo') {
- return true;
- }
- return false;
- }
- );
- $instance->expects($this->exactly(2))
- ->method('decryptFile')
- ->withConsecutive(
- ['/user1/files/bar'],
- ['/user1/files/foo/subfile'],
- );
- /* We need format method to return a string */
- $outputFormatter = $this->createMock(OutputFormatterInterface::class);
- $outputFormatter->method('isDecorated')->willReturn(false);
- $outputFormatter->method('format')->willReturn('foo');
- $output = $this->createMock(OutputInterface::class);
- $output->expects($this->any())
- ->method('getFormatter')
- ->willReturn($outputFormatter);
- $progressBar = new ProgressBar($output);
- $this->invokePrivate($instance, 'decryptUsersFiles', ['user1', $progressBar, '']);
- }
- /**
- * @dataProvider dataTrueFalse
- */
- public function testDecryptFile($isEncrypted): void {
- $path = 'test.txt';
- /** @var DecryptAll | \PHPUnit\Framework\MockObject\MockObject $instance */
- $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
- ->setConstructorArgs(
- [
- $this->encryptionManager,
- $this->userManager,
- $this->view
- ]
- )
- ->setMethods(['getTimestamp'])
- ->getMock();
- $fileInfo = $this->createMock(FileInfo::class);
- $fileInfo->expects($this->any())->method('isEncrypted')
- ->willReturn($isEncrypted);
- $this->view->expects($this->any())->method('getFileInfo')
- ->willReturn($fileInfo);
- if ($isEncrypted) {
- $instance->expects($this->any())->method('getTimestamp')->willReturn(42);
- $this->view->expects($this->once())
- ->method('copy')
- ->with($path, $path . '.decrypted.42');
- $this->view->expects($this->once())
- ->method('rename')
- ->with($path . '.decrypted.42', $path);
- } else {
- $instance->expects($this->never())->method('getTimestamp');
- $this->view->expects($this->never())->method('copy');
- $this->view->expects($this->never())->method('rename');
- }
- $this->assertTrue(
- $this->invokePrivate($instance, 'decryptFile', [$path])
- );
- }
- public function testDecryptFileFailure(): void {
- $path = 'test.txt';
- /** @var DecryptAll | \PHPUnit\Framework\MockObject\MockObject $instance */
- $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
- ->setConstructorArgs(
- [
- $this->encryptionManager,
- $this->userManager,
- $this->view
- ]
- )
- ->setMethods(['getTimestamp'])
- ->getMock();
- $fileInfo = $this->createMock(FileInfo::class);
- $fileInfo->expects($this->any())->method('isEncrypted')
- ->willReturn(true);
- $this->view->expects($this->any())->method('getFileInfo')
- ->willReturn($fileInfo);
- $instance->expects($this->any())->method('getTimestamp')->willReturn(42);
- $this->view->expects($this->once())
- ->method('copy')
- ->with($path, $path . '.decrypted.42')
- ->willReturnCallback(function () {
- throw new DecryptionFailedException();
- });
- $this->view->expects($this->never())->method('rename');
- $this->view->expects($this->once())
- ->method('file_exists')
- ->with($path . '.decrypted.42')
- ->willReturn(true);
- $this->view->expects($this->once())
- ->method('unlink')
- ->with($path . '.decrypted.42');
- $this->assertFalse(
- $this->invokePrivate($instance, 'decryptFile', [$path])
- );
- }
- }
|