ShareControllerTest.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Files_Sharing\Tests\Controllers;
  8. use OC\Files\Filesystem;
  9. use OC\Files\Node\Folder;
  10. use OC\Share20\Manager;
  11. use OCA\FederatedFileSharing\FederatedShareProvider;
  12. use OCA\Files_Sharing\Controller\ShareController;
  13. use OCA\Files_Sharing\DefaultPublicShareTemplateProvider;
  14. use OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent;
  15. use OCP\Accounts\IAccount;
  16. use OCP\Accounts\IAccountManager;
  17. use OCP\Accounts\IAccountProperty;
  18. use OCP\Activity\IManager;
  19. use OCP\AppFramework\Http\DataResponse;
  20. use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
  21. use OCP\AppFramework\Http\Template\LinkMenuAction;
  22. use OCP\AppFramework\Http\Template\PublicTemplateResponse;
  23. use OCP\AppFramework\Http\Template\SimpleMenuAction;
  24. use OCP\AppFramework\Services\IInitialState;
  25. use OCP\Constants;
  26. use OCP\Defaults;
  27. use OCP\EventDispatcher\IEventDispatcher;
  28. use OCP\Files\File;
  29. use OCP\Files\IRootFolder;
  30. use OCP\Files\NotFoundException;
  31. use OCP\Files\Storage;
  32. use OCP\IConfig;
  33. use OCP\IL10N;
  34. use OCP\IPreview;
  35. use OCP\IRequest;
  36. use OCP\ISession;
  37. use OCP\IURLGenerator;
  38. use OCP\IUser;
  39. use OCP\IUserManager;
  40. use OCP\Security\ISecureRandom;
  41. use OCP\Share\Exceptions\ShareNotFound;
  42. use OCP\Share\IPublicShareTemplateFactory;
  43. use OCP\Share\IShare;
  44. use PHPUnit\Framework\MockObject\MockObject;
  45. /**
  46. * @group DB
  47. *
  48. * @package OCA\Files_Sharing\Controllers
  49. */
  50. class ShareControllerTest extends \Test\TestCase {
  51. /** @var string */
  52. private $user;
  53. /** @var string */
  54. private $oldUser;
  55. /** @var string */
  56. private $appName = 'files_sharing';
  57. /** @var ShareController */
  58. private $shareController;
  59. /** @var IURLGenerator|MockObject */
  60. private $urlGenerator;
  61. /** @var ISession|MockObject */
  62. private $session;
  63. /** @var \OCP\IPreview|MockObject */
  64. private $previewManager;
  65. /** @var \OCP\IConfig|MockObject */
  66. private $config;
  67. /** @var \OC\Share20\Manager|MockObject */
  68. private $shareManager;
  69. /** @var IUserManager|MockObject */
  70. private $userManager;
  71. /** @var FederatedShareProvider|MockObject */
  72. private $federatedShareProvider;
  73. /** @var IAccountManager|MockObject */
  74. private $accountManager;
  75. /** @var IEventDispatcher|MockObject */
  76. private $eventDispatcher;
  77. /** @var IL10N */
  78. private $l10n;
  79. /** @var ISecureRandom */
  80. private $secureRandom;
  81. /** @var Defaults|MockObject */
  82. private $defaults;
  83. /** @var IPublicShareTemplateFactory|MockObject */
  84. private $publicShareTemplateFactory;
  85. protected function setUp(): void {
  86. parent::setUp();
  87. $this->appName = 'files_sharing';
  88. $this->shareManager = $this->createMock(Manager::class);
  89. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  90. $this->session = $this->createMock(ISession::class);
  91. $this->previewManager = $this->createMock(IPreview::class);
  92. $this->config = $this->createMock(IConfig::class);
  93. $this->userManager = $this->createMock(IUserManager::class);
  94. $this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
  95. $this->federatedShareProvider->expects($this->any())
  96. ->method('isOutgoingServer2serverShareEnabled')->willReturn(true);
  97. $this->federatedShareProvider->expects($this->any())
  98. ->method('isIncomingServer2serverShareEnabled')->willReturn(true);
  99. $this->accountManager = $this->createMock(IAccountManager::class);
  100. $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
  101. $this->l10n = $this->createMock(IL10N::class);
  102. $this->secureRandom = $this->createMock(ISecureRandom::class);
  103. $this->defaults = $this->createMock(Defaults::class);
  104. $this->publicShareTemplateFactory = $this->createMock(IPublicShareTemplateFactory::class);
  105. $this->publicShareTemplateFactory
  106. ->expects($this->any())
  107. ->method('getProvider')
  108. ->willReturn(
  109. new DefaultPublicShareTemplateProvider(
  110. $this->userManager,
  111. $this->accountManager,
  112. $this->previewManager,
  113. $this->federatedShareProvider,
  114. $this->urlGenerator,
  115. $this->eventDispatcher,
  116. $this->l10n,
  117. $this->defaults,
  118. $this->config,
  119. $this->createMock(IRequest::class),
  120. $this->createMock(IInitialState::class)
  121. )
  122. );
  123. $this->shareController = new \OCA\Files_Sharing\Controller\ShareController(
  124. $this->appName,
  125. $this->createMock(IRequest::class),
  126. $this->config,
  127. $this->urlGenerator,
  128. $this->userManager,
  129. $this->createMock(IManager::class),
  130. $this->shareManager,
  131. $this->session,
  132. $this->previewManager,
  133. $this->createMock(IRootFolder::class),
  134. $this->federatedShareProvider,
  135. $this->accountManager,
  136. $this->eventDispatcher,
  137. $this->l10n,
  138. $this->secureRandom,
  139. $this->defaults,
  140. $this->publicShareTemplateFactory,
  141. );
  142. // Store current user
  143. $this->oldUser = \OC_User::getUser();
  144. // Create a dummy user
  145. $this->user = \OC::$server->getSecureRandom()->generate(12, ISecureRandom::CHAR_LOWER);
  146. \OC::$server->getUserManager()->createUser($this->user, $this->user);
  147. \OC_Util::tearDownFS();
  148. $this->loginAsUser($this->user);
  149. }
  150. protected function tearDown(): void {
  151. \OC_Util::tearDownFS();
  152. \OC_User::setUserId('');
  153. Filesystem::tearDown();
  154. $user = \OC::$server->getUserManager()->get($this->user);
  155. if ($user !== null) {
  156. $user->delete();
  157. }
  158. \OC_User::setIncognitoMode(false);
  159. \OC::$server->getSession()->set('public_link_authenticated', '');
  160. // Set old user
  161. \OC_User::setUserId($this->oldUser);
  162. \OC_Util::setupFS($this->oldUser);
  163. parent::tearDown();
  164. }
  165. public function testShowShareInvalidToken() {
  166. $this->shareController->setToken('invalidtoken');
  167. $this->shareManager
  168. ->expects($this->once())
  169. ->method('getShareByToken')
  170. ->with('invalidtoken')
  171. ->will($this->throwException(new ShareNotFound()));
  172. $this->expectException(NotFoundException::class);
  173. // Test without a not existing token
  174. $this->shareController->showShare();
  175. }
  176. public function testShowShareNotAuthenticated() {
  177. $this->shareController->setToken('validtoken');
  178. $share = \OC::$server->getShareManager()->newShare();
  179. $share->setPassword('password');
  180. $this->shareManager
  181. ->expects($this->once())
  182. ->method('getShareByToken')
  183. ->with('validtoken')
  184. ->willReturn($share);
  185. $this->expectException(NotFoundException::class);
  186. // Test without a not existing token
  187. $this->shareController->showShare();
  188. }
  189. public function testShowShare() {
  190. $note = 'personal note';
  191. $filename = 'file1.txt';
  192. $this->shareController->setToken('token');
  193. $owner = $this->createMock(IUser::class);
  194. $owner->method('getDisplayName')->willReturn('ownerDisplay');
  195. $owner->method('getUID')->willReturn('ownerUID');
  196. $owner->method('isEnabled')->willReturn(true);
  197. $initiator = $this->createMock(IUser::class);
  198. $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
  199. $initiator->method('getUID')->willReturn('initiatorUID');
  200. $initiator->method('isEnabled')->willReturn(true);
  201. $file = $this->createMock(File::class);
  202. $file->method('getName')->willReturn($filename);
  203. $file->method('getMimetype')->willReturn('text/plain');
  204. $file->method('getSize')->willReturn(33);
  205. $file->method('isReadable')->willReturn(true);
  206. $file->method('isShareable')->willReturn(true);
  207. $file->method('getId')->willReturn(111);
  208. $accountName = $this->createMock(IAccountProperty::class);
  209. $accountName->method('getScope')
  210. ->willReturn(IAccountManager::SCOPE_PUBLISHED);
  211. $account = $this->createMock(IAccount::class);
  212. $account->method('getProperty')
  213. ->with(IAccountManager::PROPERTY_DISPLAYNAME)
  214. ->willReturn($accountName);
  215. $this->accountManager->expects($this->once())
  216. ->method('getAccount')
  217. ->with($owner)
  218. ->willReturn($account);
  219. $share = \OC::$server->getShareManager()->newShare();
  220. $share->setId(42);
  221. $share->setPassword('password')
  222. ->setShareOwner('ownerUID')
  223. ->setSharedBy('initiatorUID')
  224. ->setNode($file)
  225. ->setNote($note)
  226. ->setTarget("/$filename");
  227. $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
  228. $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
  229. $this->urlGenerator->expects($this->exactly(3))
  230. ->method('linkToRouteAbsolute')
  231. ->withConsecutive(
  232. ['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename]],
  233. ['files_sharing.sharecontroller.showShare', ['token' => 'token']],
  234. ['files_sharing.PublicPreview.getPreview', ['token' => 'token', 'x' => 200, 'y' => 200, 'file' => '/'.$filename]],
  235. )->willReturnOnConsecutiveCalls(
  236. 'downloadURL',
  237. 'shareUrl',
  238. 'previewImage',
  239. );
  240. $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
  241. $this->config->method('getSystemValue')
  242. ->willReturnMap(
  243. [
  244. ['max_filesize_animated_gifs_public_sharing', 10, 10],
  245. ['enable_previews', true, true],
  246. ['preview_max_x', 1024, 1024],
  247. ['preview_max_y', 1024, 1024],
  248. ]
  249. );
  250. $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
  251. $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
  252. $this->shareManager
  253. ->expects($this->once())
  254. ->method('getShareByToken')
  255. ->with('token')
  256. ->willReturn($share);
  257. $this->config
  258. ->expects($this->once())
  259. ->method('getAppValue')
  260. ->with('core', 'shareapi_public_link_disclaimertext', null)
  261. ->willReturn('My disclaimer text');
  262. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  263. if ($uid === 'ownerUID') {
  264. return $owner;
  265. }
  266. if ($uid === 'initiatorUID') {
  267. return $initiator;
  268. }
  269. return null;
  270. });
  271. $this->eventDispatcher->method('dispatchTyped')->with(
  272. $this->callback(function ($event) use ($share) {
  273. if ($event instanceof BeforeTemplateRenderedEvent) {
  274. return $event->getShare() === $share;
  275. } else {
  276. return true;
  277. }
  278. })
  279. );
  280. $this->l10n->expects($this->any())
  281. ->method('t')
  282. ->willReturnCallback(function ($text, $parameters) {
  283. return vsprintf($text, $parameters);
  284. });
  285. $this->defaults->expects(self::any())
  286. ->method('getProductName')
  287. ->willReturn('Nextcloud');
  288. $response = $this->shareController->showShare();
  289. $sharedTmplParams = [
  290. 'owner' => 'ownerUID',
  291. 'filename' => $filename,
  292. 'directory_path' => "/$filename",
  293. 'mimetype' => 'text/plain',
  294. 'dirToken' => 'token',
  295. 'sharingToken' => 'token',
  296. 'server2serversharing' => true,
  297. 'protected' => 'true',
  298. 'dir' => '',
  299. 'downloadURL' => 'downloadURL',
  300. 'fileSize' => '33 B',
  301. 'nonHumanFileSize' => 33,
  302. 'maxSizeAnimateGif' => 10,
  303. 'previewSupported' => true,
  304. 'previewEnabled' => true,
  305. 'previewMaxX' => 1024,
  306. 'previewMaxY' => 1024,
  307. 'hideFileList' => false,
  308. 'shareOwner' => 'ownerDisplay',
  309. 'disclaimer' => 'My disclaimer text',
  310. 'shareUrl' => 'shareUrl',
  311. 'previewImage' => 'previewImage',
  312. 'previewURL' => 'downloadURL',
  313. 'note' => $note,
  314. 'hideDownload' => false,
  315. 'showgridview' => false,
  316. 'label' => '',
  317. 'filename' => $filename,
  318. ];
  319. $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
  320. $csp->addAllowedFrameDomain('\'self\'');
  321. $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams);
  322. $expectedResponse->setContentSecurityPolicy($csp);
  323. $expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
  324. $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['shareOwner']);
  325. $expectedResponse->setHeaderActions([
  326. new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $sharedTmplParams['downloadURL'], 0),
  327. new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 10, $sharedTmplParams['fileSize']),
  328. new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $sharedTmplParams['previewURL']),
  329. new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $sharedTmplParams['owner'], $sharedTmplParams['shareOwner'], $sharedTmplParams['filename']),
  330. ]);
  331. $this->assertEquals($expectedResponse, $response);
  332. }
  333. public function testShowShareWithPrivateName() {
  334. $note = 'personal note';
  335. $filename = 'file1.txt';
  336. $this->shareController->setToken('token');
  337. $owner = $this->createMock(IUser::class);
  338. $owner->method('getDisplayName')->willReturn('ownerDisplay');
  339. $owner->method('getUID')->willReturn('ownerUID');
  340. $owner->method('isEnabled')->willReturn(true);
  341. $initiator = $this->createMock(IUser::class);
  342. $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
  343. $initiator->method('getUID')->willReturn('initiatorUID');
  344. $initiator->method('isEnabled')->willReturn(true);
  345. $file = $this->createMock(File::class);
  346. $file->method('getName')->willReturn($filename);
  347. $file->method('getMimetype')->willReturn('text/plain');
  348. $file->method('getSize')->willReturn(33);
  349. $file->method('isReadable')->willReturn(true);
  350. $file->method('isShareable')->willReturn(true);
  351. $file->method('getId')->willReturn(111);
  352. $accountName = $this->createMock(IAccountProperty::class);
  353. $accountName->method('getScope')
  354. ->willReturn(IAccountManager::SCOPE_LOCAL);
  355. $account = $this->createMock(IAccount::class);
  356. $account->method('getProperty')
  357. ->with(IAccountManager::PROPERTY_DISPLAYNAME)
  358. ->willReturn($accountName);
  359. $this->accountManager->expects($this->once())
  360. ->method('getAccount')
  361. ->with($owner)
  362. ->willReturn($account);
  363. $share = \OC::$server->getShareManager()->newShare();
  364. $share->setId(42);
  365. $share->setPassword('password')
  366. ->setShareOwner('ownerUID')
  367. ->setSharedBy('initiatorUID')
  368. ->setNode($file)
  369. ->setNote($note)
  370. ->setTarget("/$filename");
  371. $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
  372. $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
  373. $this->urlGenerator->expects($this->exactly(3))
  374. ->method('linkToRouteAbsolute')
  375. ->withConsecutive(
  376. ['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename]],
  377. ['files_sharing.sharecontroller.showShare', ['token' => 'token']],
  378. ['files_sharing.PublicPreview.getPreview', ['token' => 'token', 'x' => 200, 'y' => 200, 'file' => '/'.$filename]],
  379. )->willReturnOnConsecutiveCalls(
  380. 'downloadURL',
  381. 'shareUrl',
  382. 'previewImage',
  383. );
  384. $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
  385. $this->config->method('getSystemValue')
  386. ->willReturnMap(
  387. [
  388. ['max_filesize_animated_gifs_public_sharing', 10, 10],
  389. ['enable_previews', true, true],
  390. ['preview_max_x', 1024, 1024],
  391. ['preview_max_y', 1024, 1024],
  392. ]
  393. );
  394. $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
  395. $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
  396. $this->shareManager
  397. ->expects($this->once())
  398. ->method('getShareByToken')
  399. ->with('token')
  400. ->willReturn($share);
  401. $this->config
  402. ->expects($this->once())
  403. ->method('getAppValue')
  404. ->with('core', 'shareapi_public_link_disclaimertext', null)
  405. ->willReturn('My disclaimer text');
  406. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  407. if ($uid === 'ownerUID') {
  408. return $owner;
  409. }
  410. if ($uid === 'initiatorUID') {
  411. return $initiator;
  412. }
  413. return null;
  414. });
  415. $this->eventDispatcher->method('dispatchTyped')->with(
  416. $this->callback(function ($event) use ($share) {
  417. if ($event instanceof BeforeTemplateRenderedEvent) {
  418. return $event->getShare() === $share;
  419. } else {
  420. return true;
  421. }
  422. })
  423. );
  424. $this->l10n->expects($this->any())
  425. ->method('t')
  426. ->will($this->returnCallback(function ($text, $parameters) {
  427. return vsprintf($text, $parameters);
  428. }));
  429. $this->defaults->expects(self::any())
  430. ->method('getProductName')
  431. ->willReturn('Nextcloud');
  432. $response = $this->shareController->showShare();
  433. $sharedTmplParams = [
  434. 'owner' => '',
  435. 'filename' => $filename,
  436. 'directory_path' => "/$filename",
  437. 'mimetype' => 'text/plain',
  438. 'dirToken' => 'token',
  439. 'sharingToken' => 'token',
  440. 'server2serversharing' => true,
  441. 'protected' => 'true',
  442. 'dir' => '',
  443. 'downloadURL' => 'downloadURL',
  444. 'fileSize' => '33 B',
  445. 'nonHumanFileSize' => 33,
  446. 'maxSizeAnimateGif' => 10,
  447. 'previewSupported' => true,
  448. 'previewEnabled' => true,
  449. 'previewMaxX' => 1024,
  450. 'previewMaxY' => 1024,
  451. 'hideFileList' => false,
  452. 'shareOwner' => '',
  453. 'disclaimer' => 'My disclaimer text',
  454. 'shareUrl' => 'shareUrl',
  455. 'previewImage' => 'previewImage',
  456. 'previewURL' => 'downloadURL',
  457. 'note' => $note,
  458. 'hideDownload' => false,
  459. 'showgridview' => false,
  460. 'label' => ''
  461. ];
  462. $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
  463. $csp->addAllowedFrameDomain('\'self\'');
  464. $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams);
  465. $expectedResponse->setContentSecurityPolicy($csp);
  466. $expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
  467. $expectedResponse->setHeaderDetails('');
  468. $expectedResponse->setHeaderActions([
  469. new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $sharedTmplParams['downloadURL'], 0),
  470. new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 10, $sharedTmplParams['fileSize']),
  471. new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $sharedTmplParams['previewURL']),
  472. new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $sharedTmplParams['owner'], $sharedTmplParams['shareOwner'], $sharedTmplParams['filename']),
  473. ]);
  474. $this->assertEquals($expectedResponse, $response);
  475. }
  476. public function testShowShareHideDownload() {
  477. $note = 'personal note';
  478. $filename = 'file1.txt';
  479. $this->shareController->setToken('token');
  480. $owner = $this->getMockBuilder(IUser::class)->getMock();
  481. $owner->method('getDisplayName')->willReturn('ownerDisplay');
  482. $owner->method('getUID')->willReturn('ownerUID');
  483. $owner->method('isEnabled')->willReturn(true);
  484. $initiator = $this->createMock(IUser::class);
  485. $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
  486. $initiator->method('getUID')->willReturn('initiatorUID');
  487. $initiator->method('isEnabled')->willReturn(true);
  488. $file = $this->getMockBuilder('OCP\Files\File')->getMock();
  489. $file->method('getName')->willReturn($filename);
  490. $file->method('getMimetype')->willReturn('text/plain');
  491. $file->method('getSize')->willReturn(33);
  492. $file->method('isReadable')->willReturn(true);
  493. $file->method('isShareable')->willReturn(true);
  494. $file->method('getId')->willReturn(111);
  495. $accountName = $this->createMock(IAccountProperty::class);
  496. $accountName->method('getScope')
  497. ->willReturn(IAccountManager::SCOPE_PUBLISHED);
  498. $account = $this->createMock(IAccount::class);
  499. $account->method('getProperty')
  500. ->with(IAccountManager::PROPERTY_DISPLAYNAME)
  501. ->willReturn($accountName);
  502. $this->accountManager->expects($this->once())
  503. ->method('getAccount')
  504. ->with($owner)
  505. ->willReturn($account);
  506. $share = \OC::$server->getShareManager()->newShare();
  507. $share->setId(42);
  508. $share->setPassword('password')
  509. ->setShareOwner('ownerUID')
  510. ->setSharedBy('initiatorUID')
  511. ->setNode($file)
  512. ->setNote($note)
  513. ->setTarget("/$filename")
  514. ->setHideDownload(true);
  515. $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
  516. $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
  517. // Even if downloads are disabled the "downloadURL" parameter is
  518. // provided to the template, as it is needed to preview audio and GIF
  519. // files.
  520. $this->urlGenerator->expects($this->exactly(3))
  521. ->method('linkToRouteAbsolute')
  522. ->withConsecutive(
  523. ['files_sharing.sharecontroller.downloadShare', ['token' => 'token', 'filename' => $filename]],
  524. ['files_sharing.sharecontroller.showShare', ['token' => 'token']],
  525. ['files_sharing.PublicPreview.getPreview', ['token' => 'token', 'x' => 200, 'y' => 200, 'file' => '/'.$filename]],
  526. )->willReturnOnConsecutiveCalls(
  527. 'downloadURL',
  528. 'shareUrl',
  529. 'previewImage',
  530. );
  531. $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
  532. $this->config->method('getSystemValue')
  533. ->willReturnMap(
  534. [
  535. ['max_filesize_animated_gifs_public_sharing', 10, 10],
  536. ['enable_previews', true, true],
  537. ['preview_max_x', 1024, 1024],
  538. ['preview_max_y', 1024, 1024],
  539. ]
  540. );
  541. $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
  542. $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
  543. $this->shareManager
  544. ->expects($this->once())
  545. ->method('getShareByToken')
  546. ->with('token')
  547. ->willReturn($share);
  548. $this->config
  549. ->expects($this->once())
  550. ->method('getAppValue')
  551. ->with('core', 'shareapi_public_link_disclaimertext', null)
  552. ->willReturn('My disclaimer text');
  553. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  554. if ($uid === 'ownerUID') {
  555. return $owner;
  556. }
  557. if ($uid === 'initiatorUID') {
  558. return $initiator;
  559. }
  560. return null;
  561. });
  562. $this->eventDispatcher->method('dispatchTyped')->with(
  563. $this->callback(function ($event) use ($share) {
  564. if ($event instanceof BeforeTemplateRenderedEvent) {
  565. return $event->getShare() === $share;
  566. } else {
  567. return true;
  568. }
  569. })
  570. );
  571. $this->l10n->expects($this->any())
  572. ->method('t')
  573. ->willReturnCallback(function ($text, $parameters) {
  574. return vsprintf($text, $parameters);
  575. });
  576. $response = $this->shareController->showShare();
  577. $sharedTmplParams = [
  578. 'owner' => 'ownerUID',
  579. 'filename' => $filename,
  580. 'directory_path' => "/$filename",
  581. 'mimetype' => 'text/plain',
  582. 'dirToken' => 'token',
  583. 'sharingToken' => 'token',
  584. 'server2serversharing' => true,
  585. 'protected' => 'true',
  586. 'dir' => '',
  587. 'downloadURL' => 'downloadURL',
  588. 'fileSize' => '33 B',
  589. 'nonHumanFileSize' => 33,
  590. 'maxSizeAnimateGif' => 10,
  591. 'previewSupported' => true,
  592. 'previewEnabled' => true,
  593. 'previewMaxX' => 1024,
  594. 'previewMaxY' => 1024,
  595. 'hideFileList' => false,
  596. 'shareOwner' => 'ownerDisplay',
  597. 'disclaimer' => 'My disclaimer text',
  598. 'shareUrl' => 'shareUrl',
  599. 'previewImage' => 'previewImage',
  600. 'previewURL' => 'downloadURL',
  601. 'note' => $note,
  602. 'hideDownload' => true,
  603. 'showgridview' => false,
  604. 'label' => ''
  605. ];
  606. $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
  607. $csp->addAllowedFrameDomain('\'self\'');
  608. $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams);
  609. $expectedResponse->setContentSecurityPolicy($csp);
  610. $expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
  611. $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['shareOwner']);
  612. $expectedResponse->setHeaderActions([]);
  613. $this->assertEquals($expectedResponse, $response);
  614. }
  615. /**
  616. * Checks file drop shares:
  617. * - there must not be any header action
  618. * - the template param "hideFileList" should be true
  619. *
  620. * @test
  621. * @return void
  622. */
  623. public function testShareFileDrop() {
  624. $this->shareController->setToken('token');
  625. $owner = $this->getMockBuilder(IUser::class)->getMock();
  626. $owner->method('getDisplayName')->willReturn('ownerDisplay');
  627. $owner->method('getUID')->willReturn('ownerUID');
  628. $owner->method('isEnabled')->willReturn(true);
  629. $initiator = $this->createMock(IUser::class);
  630. $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
  631. $initiator->method('getUID')->willReturn('initiatorUID');
  632. $initiator->method('isEnabled')->willReturn(true);
  633. /* @var MockObject|Storage $storage */
  634. $storage = $this->getMockBuilder(Storage::class)
  635. ->disableOriginalConstructor()
  636. ->getMock();
  637. /* @var MockObject|Folder $folder */
  638. $folder = $this->getMockBuilder(Folder::class)
  639. ->disableOriginalConstructor()
  640. ->getMock();
  641. $folder->method('getName')->willReturn('/fileDrop');
  642. $folder->method('isReadable')->willReturn(true);
  643. $folder->method('isShareable')->willReturn(true);
  644. $folder->method('getStorage')->willReturn($storage);
  645. $folder->method('get')->with('')->willReturn($folder);
  646. $folder->method('getSize')->willReturn(1337);
  647. $folder->method('getId')->willReturn(111);
  648. $accountName = $this->createMock(IAccountProperty::class);
  649. $accountName->method('getScope')
  650. ->willReturn(IAccountManager::SCOPE_PUBLISHED);
  651. $account = $this->createMock(IAccount::class);
  652. $account->method('getProperty')
  653. ->with(IAccountManager::PROPERTY_DISPLAYNAME)
  654. ->willReturn($accountName);
  655. $this->accountManager->expects($this->once())
  656. ->method('getAccount')
  657. ->with($owner)
  658. ->willReturn($account);
  659. $share = \OC::$server->getShareManager()->newShare();
  660. $share->setId(42);
  661. $share->setPermissions(Constants::PERMISSION_CREATE)
  662. ->setShareOwner('ownerUID')
  663. ->setSharedBy('initiatorUID')
  664. ->setNode($folder)
  665. ->setTarget('/fileDrop');
  666. $this->shareManager
  667. ->expects($this->once())
  668. ->method('getShareByToken')
  669. ->with('token')
  670. ->willReturn($share);
  671. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  672. if ($uid === 'ownerUID') {
  673. return $owner;
  674. }
  675. if ($uid === 'initiatorUID') {
  676. return $initiator;
  677. }
  678. return null;
  679. });
  680. $this->l10n->expects($this->any())
  681. ->method('t')
  682. ->willReturnCallback(function ($text, $parameters) {
  683. return vsprintf($text, $parameters);
  684. });
  685. $response = $this->shareController->showShare();
  686. // skip the "folder" param for tests
  687. $responseParams = $response->getParams();
  688. unset($responseParams['folder']);
  689. $response->setParams($responseParams);
  690. $sharedTmplParams = [
  691. 'owner' => 'ownerUID',
  692. 'filename' => '/fileDrop',
  693. 'directory_path' => '/fileDrop',
  694. 'mimetype' => null,
  695. 'dirToken' => 'token',
  696. 'sharingToken' => 'token',
  697. 'server2serversharing' => true,
  698. 'protected' => 'false',
  699. 'dir' => null,
  700. 'downloadURL' => '',
  701. 'fileSize' => '1 KB',
  702. 'nonHumanFileSize' => 1337,
  703. 'maxSizeAnimateGif' => null,
  704. 'previewSupported' => null,
  705. 'previewEnabled' => null,
  706. 'previewMaxX' => null,
  707. 'previewMaxY' => null,
  708. 'hideFileList' => true,
  709. 'shareOwner' => 'ownerDisplay',
  710. 'disclaimer' => null,
  711. 'shareUrl' => '',
  712. 'previewImage' => '',
  713. 'previewURL' => '',
  714. 'note' => '',
  715. 'hideDownload' => false,
  716. 'showgridview' => false,
  717. 'label' => ''
  718. ];
  719. $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
  720. $csp->addAllowedFrameDomain('\'self\'');
  721. $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams);
  722. $expectedResponse->setContentSecurityPolicy($csp);
  723. $expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
  724. $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['shareOwner']);
  725. self::assertEquals($expectedResponse, $response);
  726. }
  727. public function testShowShareInvalid() {
  728. $this->expectException(\OCP\Files\NotFoundException::class);
  729. $filename = 'file1.txt';
  730. $this->shareController->setToken('token');
  731. $owner = $this->getMockBuilder(IUser::class)->getMock();
  732. $owner->method('getDisplayName')->willReturn('ownerDisplay');
  733. $owner->method('getUID')->willReturn('ownerUID');
  734. $file = $this->getMockBuilder('OCP\Files\File')->getMock();
  735. $file->method('getName')->willReturn($filename);
  736. $file->method('getMimetype')->willReturn('text/plain');
  737. $file->method('getSize')->willReturn(33);
  738. $file->method('isShareable')->willReturn(false);
  739. $file->method('isReadable')->willReturn(true);
  740. $share = \OC::$server->getShareManager()->newShare();
  741. $share->setId(42);
  742. $share->setPassword('password')
  743. ->setShareOwner('ownerUID')
  744. ->setNode($file)
  745. ->setTarget("/$filename");
  746. $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
  747. $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
  748. $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
  749. $this->config->method('getSystemValue')
  750. ->willReturnMap(
  751. [
  752. ['max_filesize_animated_gifs_public_sharing', 10, 10],
  753. ['enable_previews', true, true],
  754. ]
  755. );
  756. $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
  757. $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
  758. $this->shareManager
  759. ->expects($this->once())
  760. ->method('getShareByToken')
  761. ->with('token')
  762. ->willReturn($share);
  763. $this->userManager->method('get')->with('ownerUID')->willReturn($owner);
  764. $this->shareController->showShare();
  765. }
  766. public function testDownloadShareWithCreateOnlyShare() {
  767. $share = $this->getMockBuilder(IShare::class)->getMock();
  768. $share->method('getPassword')->willReturn('password');
  769. $share
  770. ->expects($this->once())
  771. ->method('getPermissions')
  772. ->willReturn(\OCP\Constants::PERMISSION_CREATE);
  773. $this->shareManager
  774. ->expects($this->once())
  775. ->method('getShareByToken')
  776. ->with('validtoken')
  777. ->willReturn($share);
  778. // Test with a password protected share and no authentication
  779. $response = $this->shareController->downloadShare('validtoken');
  780. $expectedResponse = new DataResponse('Share has no read permission');
  781. $this->assertEquals($expectedResponse, $response);
  782. }
  783. public function testDisabledOwner() {
  784. $this->shareController->setToken('token');
  785. $owner = $this->getMockBuilder(IUser::class)->getMock();
  786. $owner->method('isEnabled')->willReturn(false);
  787. $initiator = $this->createMock(IUser::class);
  788. $initiator->method('isEnabled')->willReturn(false);
  789. /* @var MockObject|Folder $folder */
  790. $folder = $this->createMock(Folder::class);
  791. $share = \OC::$server->getShareManager()->newShare();
  792. $share->setId(42);
  793. $share->setPermissions(Constants::PERMISSION_CREATE)
  794. ->setShareOwner('ownerUID')
  795. ->setSharedBy('initiatorUID')
  796. ->setNode($folder)
  797. ->setTarget('/share');
  798. $this->shareManager
  799. ->expects($this->once())
  800. ->method('getShareByToken')
  801. ->with('token')
  802. ->willReturn($share);
  803. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  804. if ($uid === 'ownerUID') {
  805. return $owner;
  806. }
  807. if ($uid === 'initiatorUID') {
  808. return $initiator;
  809. }
  810. return null;
  811. });
  812. $this->expectException(NotFoundException::class);
  813. $this->shareController->showShare();
  814. }
  815. public function testDisabledInitiator() {
  816. $this->shareController->setToken('token');
  817. $owner = $this->getMockBuilder(IUser::class)->getMock();
  818. $owner->method('isEnabled')->willReturn(false);
  819. $initiator = $this->createMock(IUser::class);
  820. $initiator->method('isEnabled')->willReturn(true);
  821. /* @var MockObject|Folder $folder */
  822. $folder = $this->createMock(Folder::class);
  823. $share = \OC::$server->getShareManager()->newShare();
  824. $share->setId(42);
  825. $share->setPermissions(Constants::PERMISSION_CREATE)
  826. ->setShareOwner('ownerUID')
  827. ->setSharedBy('initiatorUID')
  828. ->setNode($folder)
  829. ->setTarget('/share');
  830. $this->shareManager
  831. ->expects($this->once())
  832. ->method('getShareByToken')
  833. ->with('token')
  834. ->willReturn($share);
  835. $this->userManager->method('get')->willReturnCallback(function (string $uid) use ($owner, $initiator) {
  836. if ($uid === 'ownerUID') {
  837. return $owner;
  838. }
  839. if ($uid === 'initiatorUID') {
  840. return $initiator;
  841. }
  842. return null;
  843. });
  844. $this->expectException(NotFoundException::class);
  845. $this->shareController->showShare();
  846. }
  847. }