ShareControllerTest.php 31 KB

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