1
0

ShareControllerTest.php 32 KB

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