DecryptAllTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <?php
  2. /**
  3. * @author Björn Schießle <schiessle@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2015, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Test\Encryption;
  22. use OC\Encryption\DecryptAll;
  23. use OC\Encryption\Exceptions\DecryptionFailedException;
  24. use OC\Encryption\Manager;
  25. use OC\Files\FileInfo;
  26. use OC\Files\View;
  27. use OCP\IUserManager;
  28. use Symfony\Component\Console\Formatter\OutputFormatterInterface;
  29. use Test\TestCase;
  30. /**
  31. * Class DecryptAllTest
  32. *
  33. * @group DB
  34. *
  35. * @package Test\Encryption
  36. */
  37. class DecryptAllTest extends TestCase {
  38. /** @var \PHPUnit_Framework_MockObject_MockObject | IUserManager */
  39. protected $userManager;
  40. /** @var \PHPUnit_Framework_MockObject_MockObject | Manager */
  41. protected $encryptionManager;
  42. /** @var \PHPUnit_Framework_MockObject_MockObject | View */
  43. protected $view;
  44. /** @var \PHPUnit_Framework_MockObject_MockObject | \Symfony\Component\Console\Input\InputInterface */
  45. protected $inputInterface;
  46. /** @var \PHPUnit_Framework_MockObject_MockObject | \Symfony\Component\Console\Output\OutputInterface */
  47. protected $outputInterface;
  48. /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\UserInterface */
  49. protected $userInterface;
  50. /** @var DecryptAll */
  51. protected $instance;
  52. public function setUp() {
  53. parent::setUp();
  54. $this->userManager = $this->getMockBuilder('OCP\IUserManager')
  55. ->disableOriginalConstructor()->getMock();
  56. $this->encryptionManager = $this->getMockBuilder('OC\Encryption\Manager')
  57. ->disableOriginalConstructor()->getMock();
  58. $this->view = $this->getMockBuilder('OC\Files\View')
  59. ->disableOriginalConstructor()->getMock();
  60. $this->inputInterface = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')
  61. ->disableOriginalConstructor()->getMock();
  62. $this->outputInterface = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')
  63. ->disableOriginalConstructor()->getMock();
  64. $this->userInterface = $this->getMockBuilder('OCP\UserInterface')
  65. ->disableOriginalConstructor()->getMock();
  66. $this->outputInterface->expects($this->any())->method('getFormatter')
  67. ->willReturn($this->createMock(OutputFormatterInterface::class));
  68. $this->instance = new DecryptAll($this->encryptionManager, $this->userManager, $this->view);
  69. $this->invokePrivate($this->instance, 'input', [$this->inputInterface]);
  70. $this->invokePrivate($this->instance, 'output', [$this->outputInterface]);
  71. }
  72. public function dataDecryptAll() {
  73. return [
  74. [true, 'user1', true],
  75. [false, 'user1', true],
  76. [true, '0', true],
  77. [false, '0', true],
  78. [true, '', false],
  79. ];
  80. }
  81. /**
  82. * @dataProvider dataDecryptAll
  83. * @param bool $prepareResult
  84. * @param string $user
  85. * @param bool $userExistsChecked
  86. */
  87. public function testDecryptAll($prepareResult, $user, $userExistsChecked) {
  88. if ($userExistsChecked) {
  89. $this->userManager->expects($this->once())->method('userExists')->willReturn(true);
  90. } else {
  91. $this->userManager->expects($this->never())->method('userExists');
  92. }
  93. /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject | $instance */
  94. $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
  95. ->setConstructorArgs(
  96. [
  97. $this->encryptionManager,
  98. $this->userManager,
  99. $this->view
  100. ]
  101. )
  102. ->setMethods(['prepareEncryptionModules', 'decryptAllUsersFiles'])
  103. ->getMock();
  104. $instance->expects($this->once())
  105. ->method('prepareEncryptionModules')
  106. ->with($user)
  107. ->willReturn($prepareResult);
  108. if ($prepareResult) {
  109. $instance->expects($this->once())
  110. ->method('decryptAllUsersFiles')
  111. ->with($user);
  112. } else {
  113. $instance->expects($this->never())->method('decryptAllUsersFiles');
  114. }
  115. $instance->decryptAll($this->inputInterface, $this->outputInterface, $user);
  116. }
  117. /**
  118. * test decrypt all call with a user who doesn't exists
  119. */
  120. public function testDecryptAllWrongUser() {
  121. $this->userManager->expects($this->once())->method('userExists')->willReturn(false);
  122. $this->outputInterface->expects($this->once())->method('writeln')
  123. ->with('User "user1" does not exist. Please check the username and try again');
  124. $this->assertFalse(
  125. $this->instance->decryptAll($this->inputInterface, $this->outputInterface, 'user1')
  126. );
  127. }
  128. public function dataTrueFalse() {
  129. return [
  130. [true],
  131. [false],
  132. ];
  133. }
  134. /**
  135. * @dataProvider dataTrueFalse
  136. * @param bool $success
  137. */
  138. public function testPrepareEncryptionModules($success) {
  139. $user = 'user1';
  140. $dummyEncryptionModule = $this->getMockBuilder('OCP\Encryption\IEncryptionModule')
  141. ->disableOriginalConstructor()->getMock();
  142. $dummyEncryptionModule->expects($this->once())
  143. ->method('prepareDecryptAll')
  144. ->with($this->inputInterface, $this->outputInterface, $user)
  145. ->willReturn($success);
  146. $callback = function() use ($dummyEncryptionModule) {return $dummyEncryptionModule;};
  147. $moduleDescription = [
  148. 'id' => 'id',
  149. 'displayName' => 'displayName',
  150. 'callback' => $callback
  151. ];
  152. $this->encryptionManager->expects($this->once())
  153. ->method('getEncryptionModules')
  154. ->willReturn([$moduleDescription]);
  155. $this->assertSame($success,
  156. $this->invokePrivate($this->instance, 'prepareEncryptionModules', [$user])
  157. );
  158. }
  159. /**
  160. * @dataProvider dataTestDecryptAllUsersFiles
  161. */
  162. public function testDecryptAllUsersFiles($user) {
  163. /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject | $instance */
  164. $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
  165. ->setConstructorArgs(
  166. [
  167. $this->encryptionManager,
  168. $this->userManager,
  169. $this->view
  170. ]
  171. )
  172. ->setMethods(['decryptUsersFiles'])
  173. ->getMock();
  174. $this->invokePrivate($instance, 'input', [$this->inputInterface]);
  175. $this->invokePrivate($instance, 'output', [$this->outputInterface]);
  176. if (empty($user)) {
  177. $this->userManager->expects($this->once())
  178. ->method('getBackends')
  179. ->willReturn([$this->userInterface]);
  180. $this->userInterface->expects($this->any())
  181. ->method('getUsers')
  182. ->willReturn(['user1', 'user2']);
  183. $instance->expects($this->at(0))
  184. ->method('decryptUsersFiles')
  185. ->with('user1');
  186. $instance->expects($this->at(1))
  187. ->method('decryptUsersFiles')
  188. ->with('user2');
  189. } else {
  190. $instance->expects($this->once())
  191. ->method('decryptUsersFiles')
  192. ->with($user);
  193. }
  194. $this->invokePrivate($instance, 'decryptAllUsersFiles', [$user]);
  195. }
  196. public function dataTestDecryptAllUsersFiles() {
  197. return [
  198. ['user1'],
  199. ['']
  200. ];
  201. }
  202. public function testDecryptUsersFiles() {
  203. /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject $instance */
  204. $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
  205. ->setConstructorArgs(
  206. [
  207. $this->encryptionManager,
  208. $this->userManager,
  209. $this->view
  210. ]
  211. )
  212. ->setMethods(['decryptFile'])
  213. ->getMock();
  214. $storage = $this->getMockBuilder('OCP\Files\Storage')
  215. ->disableOriginalConstructor()->getMock();
  216. $sharedStorage = $this->getMockBuilder('OCP\Files\Storage')
  217. ->disableOriginalConstructor()->getMock();
  218. $sharedStorage->expects($this->once())->method('instanceOfStorage')
  219. ->with('OCA\Files_Sharing\SharedStorage')->willReturn(true);
  220. $this->view->expects($this->at(0))->method('getDirectoryContent')
  221. ->with('/user1/files')->willReturn(
  222. [
  223. new FileInfo('path', $storage, 'intPath', ['name' => 'foo', 'type'=>'dir'], null),
  224. new FileInfo('path', $storage, 'intPath', ['name' => 'bar', 'type'=>'file', 'encrypted'=>true], null),
  225. new FileInfo('path', $sharedStorage, 'intPath', ['name' => 'shared', 'type'=>'file', 'encrypted'=>true], null),
  226. ]
  227. );
  228. $this->view->expects($this->at(3))->method('getDirectoryContent')
  229. ->with('/user1/files/foo')->willReturn(
  230. [
  231. new FileInfo('path', $storage, 'intPath', ['name' => 'subfile', 'type'=>'file', 'encrypted'=>true], null)
  232. ]
  233. );
  234. $this->view->expects($this->any())->method('is_dir')
  235. ->willReturnCallback(
  236. function($path) {
  237. if ($path === '/user1/files/foo') {
  238. return true;
  239. }
  240. return false;
  241. }
  242. );
  243. $instance->expects($this->at(0))
  244. ->method('decryptFile')
  245. ->with('/user1/files/bar');
  246. $instance->expects($this->at(1))
  247. ->method('decryptFile')
  248. ->with('/user1/files/foo/subfile');
  249. $progressBar = $this->getMockBuilder('Symfony\Component\Console\Helper\ProgressBar')
  250. ->disableOriginalConstructor()->getMock();
  251. $this->invokePrivate($instance, 'decryptUsersFiles', ['user1', $progressBar, '']);
  252. }
  253. public function testDecryptFile() {
  254. $path = 'test.txt';
  255. /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject $instance */
  256. $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
  257. ->setConstructorArgs(
  258. [
  259. $this->encryptionManager,
  260. $this->userManager,
  261. $this->view
  262. ]
  263. )
  264. ->setMethods(['getTimestamp'])
  265. ->getMock();
  266. $instance->expects($this->any())->method('getTimestamp')->willReturn(42);
  267. $this->view->expects($this->once())
  268. ->method('copy')
  269. ->with($path, $path . '.decrypted.42');
  270. $this->view->expects($this->once())
  271. ->method('rename')
  272. ->with($path . '.decrypted.42', $path);
  273. $this->assertTrue(
  274. $this->invokePrivate($instance, 'decryptFile', [$path])
  275. );
  276. }
  277. public function testDecryptFileFailure() {
  278. $path = 'test.txt';
  279. /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject $instance */
  280. $instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
  281. ->setConstructorArgs(
  282. [
  283. $this->encryptionManager,
  284. $this->userManager,
  285. $this->view
  286. ]
  287. )
  288. ->setMethods(['getTimestamp'])
  289. ->getMock();
  290. $instance->expects($this->any())->method('getTimestamp')->willReturn(42);
  291. $this->view->expects($this->once())
  292. ->method('copy')
  293. ->with($path, $path . '.decrypted.42')
  294. ->willReturnCallback(function() { throw new DecryptionFailedException();});
  295. $this->view->expects($this->never())->method('rename');
  296. $this->view->expects($this->once())
  297. ->method('file_exists')
  298. ->with($path . '.decrypted.42')
  299. ->willReturn(true);
  300. $this->view->expects($this->once())
  301. ->method('unlink')
  302. ->with($path . '.decrypted.42');
  303. $this->assertFalse(
  304. $this->invokePrivate($instance, 'decryptFile', [$path])
  305. );
  306. }
  307. }