diff options
-rw-r--r-- | apps/files_sharing/css/mobile.scss | 6 | ||||
-rw-r--r-- | apps/files_sharing/css/public.scss | 16 | ||||
-rw-r--r-- | apps/files_sharing/js/public.js | 16 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareController.php | 43 | ||||
-rw-r--r-- | apps/files_sharing/templates/public.php | 24 | ||||
-rw-r--r-- | apps/files_sharing/tests/Controller/ShareControllerTest.php | 105 |
6 files changed, 179 insertions, 31 deletions
diff --git a/apps/files_sharing/css/mobile.scss b/apps/files_sharing/css/mobile.scss index 272dbbc0c34..3aaa5718cab 100644 --- a/apps/files_sharing/css/mobile.scss +++ b/apps/files_sharing/css/mobile.scss @@ -50,5 +50,11 @@ table td.filename .nametext { padding-right: 14px; background-position: center; } +.note { + padding: 0 20px; +} +#emptycontent { + margin-top: 10vh; +} } diff --git a/apps/files_sharing/css/public.scss b/apps/files_sharing/css/public.scss index d1bdfe9162a..b8a5dbf4f38 100644 --- a/apps/files_sharing/css/public.scss +++ b/apps/files_sharing/css/public.scss @@ -92,8 +92,10 @@ thead { margin: 0 auto; } -#emptycontent.has-disclaimer { - margin-top: 10vh; +#emptycontent { + &.has-note { + margin-top: 5vh; + } } #public-upload #emptycontent h2 { @@ -152,8 +154,9 @@ thead { margin-right: 7px; } -.disclaimer { - margin: -20px auto 30px; +.disclaimer, +.note { + margin: 0 auto 30px; max-width: 400px; text-align: left; } @@ -184,6 +187,11 @@ thead { } } +#show-terms-dialog { + cursor: pointer; + font-weight: bold; +} + // hide the primary on public share on mobile @media only screen and (max-width: 768px) { #body-public { diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 2bd550a3b5c..c7169b3ce12 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -89,7 +89,7 @@ OCA.Sharing.PublicApp = { displayName: t('files', 'Delete'), iconClass: 'icon-delete', } - ] + ] } ); this.files = OCA.Files.Files; @@ -297,10 +297,24 @@ OCA.Sharing.PublicApp = { } }); + self._bindShowTermsAction(); + // legacy window.FileList = this.fileList; }, + /** + * Binds the click action for the "terms of service" action. + * Shows an OC info dialog on click. + * + * @private + */ + _bindShowTermsAction: function() { + $('#show-terms-dialog').on('click', function() { + OC.dialogs.info($('#disclaimerText').val(), t('files_sharing', 'Terms of service')); + }); + }, + _showTextPreview: function (data, previewHeight) { var textDiv = $('<div/>').addClass('text-preview'); textDiv.text(data); diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php index 9a8e1298f93..29ed242a975 100644 --- a/apps/files_sharing/lib/Controller/ShareController.php +++ b/apps/files_sharing/lib/Controller/ShareController.php @@ -61,7 +61,6 @@ use OCA\Files_Sharing\Activity\Providers\Downloads; use OCP\Files\NotFoundException; use OCP\Files\IRootFolder; use OCP\Share\Exceptions\ShareNotFound; -use OCP\Util; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; use OCP\Share\IManager as ShareManager; @@ -295,9 +294,12 @@ class ShareController extends AuthPublicShareController { if (!$this->validateShare($share)) { throw new NotFoundException(); } + + $shareNode = $share->getNode(); + // We can't get the path of a file share try { - if ($share->getNode() instanceof \OCP\Files\File && $path !== '') { + if ($shareNode instanceof \OCP\Files\File && $path !== '') { $this->emitAccessShareHook($share, 404, 'Share not found'); throw new NotFoundException(); } @@ -309,34 +311,34 @@ class ShareController extends AuthPublicShareController { $shareTmpl = []; $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName(); $shareTmpl['owner'] = $share->getShareOwner(); - $shareTmpl['filename'] = $share->getNode()->getName(); + $shareTmpl['filename'] = $shareNode->getName(); $shareTmpl['directory_path'] = $share->getTarget(); $shareTmpl['note'] = $share->getNote(); - $shareTmpl['mimetype'] = $share->getNode()->getMimetype(); - $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype()); + $shareTmpl['mimetype'] = $shareNode->getMimetype(); + $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype()); $shareTmpl['dirToken'] = $this->getToken(); $shareTmpl['sharingToken'] = $this->getToken(); $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(); $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false'; $shareTmpl['dir'] = ''; - $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize(); - $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize()); + $shareTmpl['nonHumanFileSize'] = $shareNode->getSize(); + $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize()); $shareTmpl['hideDownload'] = $share->getHideDownload(); - // Show file list $hideFileList = false; - if ($share->getNode() instanceof \OCP\Files\Folder) { - /** @var \OCP\Files\Folder $rootFolder */ - $rootFolder = $share->getNode(); + + if ($shareNode instanceof \OCP\Files\Folder) { + + $shareIsFolder = true; try { - $folderNode = $rootFolder->get($path); + $folderNode = $shareNode->get($path); } catch (\OCP\Files\NotFoundException $e) { $this->emitAccessShareHook($share, 404, 'Share not found'); throw new NotFoundException(); } - $shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath()); + $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath()); /* * The OC_Util methods require a view. This just uses the node API @@ -352,7 +354,7 @@ class ShareController extends AuthPublicShareController { $maxUploadFilesize = $freeSpace; $folder = new Template('files', 'list', ''); - $folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath())); + $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath())); $folder->assign('dirToken', $this->getToken()); $folder->assign('permissions', \OCP\Constants::PERMISSION_READ); $folder->assign('isPublic', true); @@ -365,6 +367,8 @@ class ShareController extends AuthPublicShareController { $folder->assign('usedSpacePercent', 0); $folder->assign('trash', false); $shareTmpl['folder'] = $folder->fetchPage(); + } else { + $shareIsFolder = false; } $shareTmpl['showgridview'] = true; @@ -379,14 +383,14 @@ class ShareController extends AuthPublicShareController { $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024); $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null); $shareTmpl['previewURL'] = $shareTmpl['downloadURL']; - $ogPreview = ''; + if ($shareTmpl['previewSupported']) { $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview', ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]); $ogPreview = $shareTmpl['previewImage']; // We just have direct previews for image files - if ($share->getNode()->getMimePart() === 'image') { + if ($shareNode->getMimePart() === 'image') { $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]); $ogPreview = $shareTmpl['previewURL']; @@ -411,7 +415,6 @@ class ShareController extends AuthPublicShareController { \OCP\Util::addStyle('files_sharing', 'publicView'); \OCP\Util::addScript('files_sharing', 'public'); \OCP\Util::addScript('files_sharing', 'templates'); - \OCP\Util::addScript('files_sharing', 'public_note'); \OCP\Util::addScript('files', 'fileactions'); \OCP\Util::addScript('files', 'fileactionsmenu'); \OCP\Util::addScript('files', 'jquery.fileupload'); @@ -447,7 +450,11 @@ class ShareController extends AuthPublicShareController { $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl); $response->setHeaderTitle($shareTmpl['filename']); $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']])); - if (!$share->getHideDownload()) { + + $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE; + + if ($isNoneFileDropFolder && !$share->getHideDownload()) { + \OCP\Util::addScript('files_sharing', 'public_note'); $response->setHeaderActions([ new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0), new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']), diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 08e119322e5..8795318c1c3 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -21,6 +21,7 @@ <input type="hidden" name="previewSupported" value="<?php p($_['previewSupported'] ? 'true' : 'false'); ?>" id="previewSupported"> <input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon"> <input type="hidden" name="hideDownload" value="<?php p($_['hideDownload'] ? 'true' : 'false'); ?>" id="hideDownload"> +<input type="hidden" id="disclaimerText" value="<?php p($_['disclaimer']) ?>"> <?php $upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize'); $post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size'); @@ -82,20 +83,33 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); <?php } else { ?> <input type="hidden" id="upload-only-interface" value="1"/> <div id="public-upload"> - <div id="emptycontent" class="<?php if (!empty($_['disclaimer'])) { ?>has-disclaimer<?php } ?>"> + <div + id="emptycontent" + class="<?php if (!empty($_['note'])) { ?>has-note<?php } ?>"> <div id="displayavatar"><div class="avatardiv"></div></div> <h2><?php p($l->t('Upload files to %s', [$_['shareOwner']])) ?></h2> <p><span class="icon-folder"></span> <?php p($_['filename']) ?></p> - <?php if (!empty($_['disclaimer'])) { ?> - <p class="disclaimer"><?php p($_['disclaimer']); ?></p> + + <?php if (empty($_['note']) === false) { ?> + <h3><?php p($l->t('Note')); ?></h3> + <p class="note"><?php p($_['note']); ?></p> <?php } ?> + <input type="file" name="files[]" class="hidden" multiple> <a href="#" class="button icon-upload"><?php p($l->t('Select or drop files')) ?></a> <div id="drop-upload-progress-indicator" style="padding-top: 25px;" class="hidden"><?php p($l->t('Uploading files…')) ?></div> <div id="drop-upload-done-indicator" style="padding-top: 25px;" class="hidden"><?php p($l->t('Uploaded files:')) ?></div> - <ul> - </ul> + + <?php if (!empty($_['disclaimer'])) { ?> + <div> + <?php + echo $l->t('By uploading files, you agree to the %1$sterms of service%2$s.', [ + '<span id="show-terms-dialog">', '</span>' + ]); + ?> + </div> + <?php } ?> </div> </div> <?php } ?> diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php index 564977c09bc..3a9856e1bd2 100644 --- a/apps/files_sharing/tests/Controller/ShareControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php @@ -32,6 +32,7 @@ namespace OCA\Files_Sharing\Tests\Controllers; use OC\Files\Filesystem; +use OC\Files\Node\Folder; use OCA\FederatedFileSharing\FederatedShareProvider; use OCA\Files_Sharing\Controller\ShareController; use OCP\AppFramework\Http\DataResponse; @@ -39,7 +40,9 @@ use OCP\AppFramework\Http\Template\ExternalShareMenuAction; use OCP\AppFramework\Http\Template\LinkMenuAction; use OCP\AppFramework\Http\Template\PublicTemplateResponse; use OCP\AppFramework\Http\Template\SimpleMenuAction; +use OCP\Constants; use OCP\Files\NotFoundException; +use OCP\Files\Storage; use OCP\IConfig; use OCP\IL10N; use OCP\ILogger; @@ -47,14 +50,12 @@ use OCP\IPreview; use OCP\IRequest; use OCP\IUser; use OCP\Share\Exceptions\ShareNotFound; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\AppFramework\Http\RedirectResponse; -use OCP\AppFramework\Http\TemplateResponse; use OCP\ISession; use OCP\IUserManager; use OCP\Security\ISecureRandom; use OCP\IURLGenerator; use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -424,6 +425,104 @@ class ShareControllerTest extends \Test\TestCase { } /** + * Checks file drop shares: + * - there must not be any header action + * - the template param "hideFileList" should be true + * + * @test + * @return void + */ + public function testShareFileDrop() { + $this->shareController->setToken('token'); + + $owner = $this->getMockBuilder(IUser::class)->getMock(); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + $owner->method('getUID')->willReturn('ownerUID'); + + /* @var MockObject|Storage $storage */ + $storage = $this->getMockBuilder(Storage::class) + ->disableOriginalConstructor() + ->getMock(); + + /* @var MockObject|Folder $folder */ + $folder = $this->getMockBuilder(Folder::class) + ->disableOriginalConstructor() + ->getMock(); + $folder->method('getName')->willReturn('/fileDrop'); + $folder->method('isReadable')->willReturn(true); + $folder->method('isShareable')->willReturn(true); + $folder->method('getStorage')->willReturn($storage); + $folder->method('get')->with('')->willReturn($folder); + $folder->method('getSize')->willReturn(1337); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(42); + $share->setPermissions(Constants::PERMISSION_CREATE) + ->setShareOwner('ownerUID') + ->setNode($folder) + ->setTarget('/fileDrop'); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->userManager->method('get')->with('ownerUID')->willReturn($owner); + + $this->l10n->expects($this->any()) + ->method('t') + ->will($this->returnCallback(function($text, $parameters) { + return vsprintf($text, $parameters); + })); + + $response = $this->shareController->showShare(); + // skip the "folder" param for tests + $responseParams = $response->getParams(); + unset($responseParams['folder']); + $response->setParams($responseParams); + + $sharedTmplParams = array( + 'displayName' => 'ownerDisplay', + 'owner' => 'ownerUID', + 'filename' => '/fileDrop', + 'directory_path' => '/fileDrop', + 'mimetype' => null, + 'dirToken' => 'token', + 'sharingToken' => 'token', + 'server2serversharing' => true, + 'protected' => 'false', + 'dir' => null, + 'downloadURL' => '', + 'fileSize' => '1 KB', + 'nonHumanFileSize' => 1337, + 'maxSizeAnimateGif' => null, + 'previewSupported' => null, + 'previewEnabled' => null, + 'previewMaxX' => null, + 'previewMaxY' => null, + 'hideFileList' => true, + 'shareOwner' => 'ownerDisplay', + 'disclaimer' => null, + 'shareUrl' => '', + 'previewImage' => '', + 'previewURL' => '', + 'note' => '', + 'hideDownload' => false, + 'showgridview' => true + ); + + $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy(); + $csp->addAllowedFrameDomain('\'self\''); + $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams); + $expectedResponse->setContentSecurityPolicy($csp); + $expectedResponse->setHeaderTitle($sharedTmplParams['filename']); + $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['displayName']); + + self::assertEquals($expectedResponse, $response); + } + + /** * @expectedException \OCP\Files\NotFoundException */ public function testShowShareInvalid() { |