Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

ShareControllerTest.php 32KB

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