Merge pull request #54 from nextcloud/backport-upload-only-shares
[stable9] Backport files drop feature
This commit is contained in:
commit
470f23c8b9
|
@ -59,6 +59,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, func
|
|||
$rootShare = \OCP\Share::resolveReShare($share);
|
||||
$owner = $rootShare['uid_owner'];
|
||||
$isWritable = $share['permissions'] & (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_CREATE);
|
||||
$isReadable = $share['permissions'] & \OCP\Constants::PERMISSION_READ;
|
||||
$fileId = $share['file_source'];
|
||||
|
||||
if (!$isWritable) {
|
||||
|
@ -66,6 +67,9 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, func
|
|||
return new \OC\Files\Storage\Wrapper\PermissionsMask(array('storage' => $storage, 'mask' => \OCP\Constants::PERMISSION_READ + \OCP\Constants::PERMISSION_SHARE));
|
||||
});
|
||||
}
|
||||
if (!$isReadable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OC_Util::setupFS($owner);
|
||||
$ownerView = \OC\Files\Filesystem::getView();
|
||||
|
|
|
@ -43,6 +43,7 @@ OCP\JSON::setContentTypeHeader('text/plain');
|
|||
// If no token is sent along, rely on login only
|
||||
|
||||
$errorCode = null;
|
||||
$errorFileName = null;
|
||||
|
||||
$l = \OC::$server->getL10N('files');
|
||||
if (empty($_POST['dirToken'])) {
|
||||
|
@ -161,6 +162,15 @@ if (\OC\Files\Filesystem::isValidPath($dir) === true) {
|
|||
$resolution = null;
|
||||
}
|
||||
|
||||
if(isset($_POST['dirToken'])) {
|
||||
// If it is a read only share the resolution will always be autorename
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$share = $shareManager->getShareByToken((string)$_POST['dirToken']);
|
||||
if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
$resolution = 'autorename';
|
||||
}
|
||||
}
|
||||
|
||||
// target directory for when uploading folders
|
||||
$relativePath = '';
|
||||
if(!empty($_POST['file_directory'])) {
|
||||
|
@ -216,6 +226,7 @@ if (\OC\Files\Filesystem::isValidPath($dir) === true) {
|
|||
|
||||
} else {
|
||||
$error = $l->t('Upload failed. Could not find uploaded file');
|
||||
$errorFileName = $files['name'][$i];
|
||||
}
|
||||
} catch(Exception $ex) {
|
||||
$error = $ex->getMessage();
|
||||
|
@ -247,7 +258,26 @@ if (\OC\Files\Filesystem::isValidPath($dir) === true) {
|
|||
}
|
||||
|
||||
if ($error === false) {
|
||||
// Do not leak file information if it is a read-only share
|
||||
if(isset($_POST['dirToken'])) {
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$share = $shareManager->getShareByToken((string)$_POST['dirToken']);
|
||||
if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
$newResults = [];
|
||||
foreach($result as $singleResult) {
|
||||
$fileName = $singleResult['originalname'];
|
||||
$newResults['filename'] = $fileName;
|
||||
$newResults['mimetype'] = \OC::$server->getMimeTypeDetector()->detectPath($fileName);
|
||||
}
|
||||
$result = $newResults;
|
||||
}
|
||||
}
|
||||
|
||||
OCP\JSON::encodedPrint($result);
|
||||
} else {
|
||||
OCP\JSON::error(array(array('data' => array_merge(array('message' => $error, 'code' => $errorCode), $storageStats))));
|
||||
OCP\JSON::error(array(array('data' => array_merge(array(
|
||||
'message' => $error,
|
||||
'code' => $errorCode,
|
||||
'filename' => $errorFileName
|
||||
), $storageStats))));
|
||||
}
|
||||
|
|
|
@ -42,6 +42,12 @@ if($token === ''){
|
|||
}
|
||||
|
||||
$linkedItem = \OCP\Share::getShareByToken($token);
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$share = $shareManager->getShareByToken($token);
|
||||
if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
OCP\JSON::error(array('data' => 'Share is not readable.'));
|
||||
exit();
|
||||
}
|
||||
if($linkedItem === false || ($linkedItem['item_type'] !== 'file' && $linkedItem['item_type'] !== 'folder')) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_NOT_FOUND);
|
||||
\OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG);
|
||||
|
|
|
@ -62,6 +62,15 @@ if (!$isWritable) {
|
|||
$rootInfo = \OC\Files\Filesystem::getFileInfo($path);
|
||||
$rootView = new \OC\Files\View('');
|
||||
|
||||
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$share = $shareManager->getShareByToken($token);
|
||||
$sharePermissions= (int)$share->getPermissions();
|
||||
if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
OCP\JSON::error(array('data' => 'Share is not readable.'));
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \OCP\Files\FileInfo $dir
|
||||
* @param \OC\Files\View $view
|
||||
|
|
|
@ -584,6 +584,7 @@ class Share20OCS {
|
|||
|
||||
if ($newPermissions !== null &&
|
||||
$newPermissions !== \OCP\Constants::PERMISSION_READ &&
|
||||
$newPermissions !== (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) &&
|
||||
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) {
|
||||
return new \OC_OCS_Result(null, 400, 'can\'t change permission for public link share');
|
||||
}
|
||||
|
|
|
@ -158,3 +158,62 @@ thead {
|
|||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#public-upload .avatardiv {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent h2 {
|
||||
margin: 10px 0 5px 0;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent h2+p {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent .icon-folder {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
background-size: 16px;
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
margin-bottom: 0;
|
||||
margin-right: 5px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent .button {
|
||||
background-size: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
background-position: 16px;
|
||||
opacity: .7;
|
||||
font-size: 20px;
|
||||
margin: 20px;
|
||||
padding: 10px 20px;
|
||||
padding-left: 42px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent ul {
|
||||
width: 160px;
|
||||
margin: 5px auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent li {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
#public-upload #emptycontent li img {
|
||||
vertical-align: text-bottom;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#public-upload li span.icon-loading-small {
|
||||
padding-left: 18px;
|
||||
margin-right: 7px;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3
|
||||
* or later.
|
||||
*
|
||||
* See the COPYING-README file.
|
||||
*
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var TEMPLATE =
|
||||
'<li data-toggle="tooltip" title="{{name}}" data-name="{{name}}">' +
|
||||
'{{#if isUploading}}' +
|
||||
'<span class="icon-loading-small"></span> {{name}}' +
|
||||
'{{else}}' +
|
||||
'<img src="' + OC.imagePath('core', 'actions/error.svg') + '"/> {{name}}' +
|
||||
'{{/if}}' +
|
||||
'</li>';
|
||||
var Drop = {
|
||||
/** @type {Function} **/
|
||||
_template: undefined,
|
||||
|
||||
initialize: function () {
|
||||
$(document).bind('drop dragover', function (e) {
|
||||
// Prevent the default browser drop action:
|
||||
e.preventDefault();
|
||||
});
|
||||
var output = this.template();
|
||||
$('#public-upload').fileupload({
|
||||
url: OC.linkTo('files', 'ajax/upload.php'),
|
||||
dataType: 'json',
|
||||
dropZone: $('#public-upload'),
|
||||
formData: {
|
||||
dirToken: $('#sharingToken').val()
|
||||
},
|
||||
add: function(e, data) {
|
||||
var errors = [];
|
||||
if(data.files[0]['size'] && data.files[0]['size'] > $('#maxFilesizeUpload').val()) {
|
||||
errors.push('File is too big');
|
||||
}
|
||||
|
||||
$('#drop-upload-done-indicator').addClass('hidden');
|
||||
$('#drop-upload-progress-indicator').removeClass('hidden');
|
||||
_.each(data['files'], function(file) {
|
||||
if(errors.length === 0) {
|
||||
$('#public-upload ul').append(output({isUploading: true, name: escapeHTML(file.name)}));
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
data.submit();
|
||||
} else {
|
||||
OC.Notification.showTemporary(OC.L10N.translate('files_sharing', 'Could not upload "{filename}"', {filename: file.name}));
|
||||
$('#public-upload ul').append(output({isUploading: false, name: escapeHTML(file.name)}));
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
}
|
||||
});
|
||||
},
|
||||
success: function (response) {
|
||||
if(response.status !== 'error') {
|
||||
var mimeTypeUrl = OC.MimeType.getIconUrl(response['mimetype']);
|
||||
$('#public-upload ul li[data-name="' + escapeHTML(response['filename']) + '"]').html('<img src="' + escapeHTML(mimeTypeUrl) + '"/> ' + escapeHTML(response['filename']));
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
} else {
|
||||
var name = response[0]['data']['filename'];
|
||||
OC.Notification.showTemporary(OC.L10N.translate('files_sharing', 'Could not upload "{filename}"', {filename: name}));
|
||||
$('#public-upload ul li[data-name="' + escapeHTML(name) + '"]').html(output({isUploading: false, name: escapeHTML(name)}));
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
}
|
||||
|
||||
},
|
||||
progressall: function (e, data) {
|
||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||
if(progress === 100) {
|
||||
$('#drop-upload-done-indicator').removeClass('hidden');
|
||||
$('#drop-upload-progress-indicator').addClass('hidden');
|
||||
} else {
|
||||
$('#drop-upload-done-indicator').addClass('hidden');
|
||||
$('#drop-upload-progress-indicator').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#public-upload .button.icon-upload').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#public-upload #emptycontent input').focus().trigger('click');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {Function} from Handlebars
|
||||
* @private
|
||||
*/
|
||||
template: function () {
|
||||
if (!this._template) {
|
||||
this._template = Handlebars.compile(TEMPLATE);
|
||||
}
|
||||
return this._template;
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
if($('#upload-only-interface').val() === "1") {
|
||||
$('.avatardiv').avatar($('#sharingUserId').val(), 128, true);
|
||||
}
|
||||
|
||||
OCA.Files_Sharing_Drop = Drop;
|
||||
OCA.Files_Sharing_Drop.initialize();
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
|
@ -307,6 +307,7 @@ class ShareController extends Controller {
|
|||
$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
|
||||
|
||||
// Show file list
|
||||
$hideFileList = false;
|
||||
if ($share->getNode() instanceof \OCP\Files\Folder) {
|
||||
$shareTmpl['dir'] = $rootFolder->getRelativePath($path->getPath());
|
||||
|
||||
|
@ -322,12 +323,14 @@ class ShareController extends Controller {
|
|||
|
||||
$uploadLimit = Util::uploadLimit();
|
||||
$maxUploadFilesize = min($freeSpace, $uploadLimit);
|
||||
$hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
|
||||
|
||||
$folder = new Template('files', 'list', '');
|
||||
$folder->assign('dir', $rootFolder->getRelativePath($path->getPath()));
|
||||
$folder->assign('dirToken', $token);
|
||||
$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
|
||||
$folder->assign('isPublic', true);
|
||||
$folder->assign('hideFileList', $hideFileList);
|
||||
$folder->assign('publicUploadEnabled', 'no');
|
||||
$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
|
||||
$folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
|
||||
|
@ -338,6 +341,8 @@ class ShareController extends Controller {
|
|||
$shareTmpl['folder'] = $folder->fetchPage();
|
||||
}
|
||||
|
||||
$shareTmpl['hideFileList'] = $hideFileList;
|
||||
$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
|
||||
$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', array('token' => $token));
|
||||
$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
|
||||
$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
|
||||
|
@ -360,12 +365,15 @@ class ShareController extends Controller {
|
|||
* @param string $files
|
||||
* @param string $path
|
||||
* @param string $downloadStartSecret
|
||||
* @return void|RedirectResponse
|
||||
* @return void|OCP\AppFramework\Http\Response
|
||||
*/
|
||||
public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
|
||||
\OC_User::setIncognitoMode(true);
|
||||
|
||||
$share = $this->shareManager->getShareByToken($token);
|
||||
if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
return new OCP\AppFramework\Http\DataResponse('Share is read-only');
|
||||
}
|
||||
|
||||
// Share is password protected - check whether the user is permitted to access the share
|
||||
if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
|
||||
|
|
|
@ -8,8 +8,8 @@ OCP\Util::addStyle('files_sharing', 'mobile');
|
|||
OCP\Util::addScript('files_sharing', 'public');
|
||||
OCP\Util::addScript('files', 'fileactions');
|
||||
OCP\Util::addScript('files', 'fileactionsmenu');
|
||||
OCP\Util::addScript('files', 'jquery.iframe-transport');
|
||||
OCP\Util::addScript('files', 'jquery.fileupload');
|
||||
OCP\Util::addScript('files_sharing', 'files_drop');
|
||||
|
||||
// JS required for folders
|
||||
OCP\Util::addStyle('files', 'files');
|
||||
|
@ -33,6 +33,7 @@ $thumbSize = 1024;
|
|||
<div id="notification" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="sharingUserId" value="<?php p($_['owner']) ?>">
|
||||
<input type="hidden" id="filesApp" name="filesApp" value="1">
|
||||
<input type="hidden" id="isPublic" name="isPublic" value="1">
|
||||
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
|
||||
|
@ -42,7 +43,16 @@ $thumbSize = 1024;
|
|||
<input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype">
|
||||
<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="filesize" value="<?php p($_['nonHumanFileSize']); ?>" id="filesize">
|
||||
<?php
|
||||
$upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize');
|
||||
$post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size');
|
||||
$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
|
||||
?>
|
||||
<input type="hidden" name="maxFilesizeUpload" value="<?php p($maxUploadFilesize); ?>" id="maxFilesizeUpload">
|
||||
|
||||
<?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)): ?>
|
||||
<input type="hidden" name="filesize" value="<?php p($_['nonHumanFileSize']); ?>" id="filesize">
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="maxSizeAnimateGif" value="<?php p($_['maxSizeAnimateGif']); ?>" id="maxSizeAnimateGif">
|
||||
|
||||
|
||||
|
@ -56,11 +66,11 @@ $thumbSize = 1024;
|
|||
<div class="header-appname-container">
|
||||
<h1 class="header-appname">
|
||||
<?php
|
||||
if(OC_Util::getEditionString() === '') {
|
||||
p($theme->getName());
|
||||
} else {
|
||||
print_unescaped($theme->getHTMLName());
|
||||
}
|
||||
if(OC_Util::getEditionString() === '') {
|
||||
p($theme->getName());
|
||||
} else {
|
||||
print_unescaped($theme->getHTMLName());
|
||||
}
|
||||
?>
|
||||
</h1>
|
||||
</div>
|
||||
|
@ -69,25 +79,28 @@ $thumbSize = 1024;
|
|||
<div class="header-right">
|
||||
<span id="details">
|
||||
<?php
|
||||
if ($_['server2serversharing']) {
|
||||
?>
|
||||
<span id="save" data-protected="<?php p($_['protected']) ?>"
|
||||
data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>">
|
||||
<button id="save-button"><?php p($l->t('Add to your Nextcloud')) ?></button>
|
||||
<form class="save-form hidden" action="#">
|
||||
<input type="text" id="remote_address" placeholder="example.com/owncloud"/>
|
||||
<button id="save-button-confirm" class="icon-confirm svg" disabled></button>
|
||||
</form>
|
||||
</span>
|
||||
if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) {
|
||||
if ($_['server2serversharing']) {
|
||||
?>
|
||||
<span id="save" data-protected="<?php p($_['protected']) ?>"
|
||||
data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>">
|
||||
<button id="save-button"><?php p($l->t('Add to your ownCloud')) ?></button>
|
||||
<form class="save-form hidden" action="#">
|
||||
<input type="text" id="remote_address" placeholder="example.com/owncloud"/>
|
||||
<button id="save-button-confirm" class="icon-confirm svg" disabled></button>
|
||||
</form>
|
||||
</span>
|
||||
<?php } ?>
|
||||
<a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
|
||||
<img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/>
|
||||
<span id="download-text"><?php p($l->t('Download'))?></span>
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
|
||||
<img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/>
|
||||
<span id="download-text"><?php p($l->t('Download'))?></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div></header>
|
||||
</div></header>
|
||||
<div id="content-wrapper">
|
||||
<?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) { ?>
|
||||
<div id="content">
|
||||
<div id="preview">
|
||||
<?php if (isset($_['folder'])): ?>
|
||||
|
@ -95,7 +108,7 @@ $thumbSize = 1024;
|
|||
<?php else: ?>
|
||||
<?php if ($_['previewEnabled'] && substr($_['mimetype'], 0, strpos($_['mimetype'], '/')) == 'video'): ?>
|
||||
<div id="imgframe">
|
||||
<video tabindex="0" controls="" preload="none">
|
||||
<video tabindex="0" controls="" preload="none" style="max-width: <?php p($_['previewMaxX']); ?>px; max-height: <?php p($_['previewMaxY']); ?>px">
|
||||
<source src="<?php p($_['downloadURL']); ?>" type="<?php p($_['mimetype']); ?>" />
|
||||
</video>
|
||||
</div>
|
||||
|
@ -115,10 +128,34 @@ $thumbSize = 1024;
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<input type="hidden" id="upload-only-interface" value="1"/>
|
||||
<div id="public-upload">
|
||||
<div id="emptycontent" class="">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] !== true)): ?>
|
||||
<input type="hidden" name="dir" id="dir" value="" />
|
||||
<div class="hiddenuploadfield">
|
||||
<input type="file" id="file_upload_start" class="hiddenuploadfield" name="files[]"
|
||||
data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<footer>
|
||||
<p class="info">
|
||||
<?php print_unescaped($theme->getLongFooter()); ?>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Georg Ehrke <georg@owncloud.com>
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <icewind@owncloud.com>
|
||||
* @author Roeland Jago Douma <rullzer@owncloud.com>
|
||||
|
@ -26,9 +27,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing\Controllers;
|
||||
namespace OCA\Files_Sharing\Tests\Controllers;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OCA\FederatedFileSharing\FederatedShareProvider;
|
||||
use OCA\Files_Sharing\Controllers\ShareController;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
|
@ -66,8 +70,11 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
private $shareManager;
|
||||
/** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $userManager;
|
||||
/** @var FederatedShareProvider | \PHPUnit_Framework_MockObject_MockObject */
|
||||
private $federatedShareProvider;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->appName = 'files_sharing';
|
||||
|
||||
$this->shareManager = $this->getMockBuilder('\OC\Share20\Manager')->disableOriginalConstructor()->getMock();
|
||||
|
@ -76,6 +83,12 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->previewManager = $this->getMock('\OCP\IPreview');
|
||||
$this->config = $this->getMock('\OCP\IConfig');
|
||||
$this->userManager = $this->getMock('\OCP\IUserManager');
|
||||
$this->federatedShareProvider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->federatedShareProvider->expects($this->any())
|
||||
->method('isOutgoingServer2serverShareEnabled')->willReturn(true);
|
||||
$this->federatedShareProvider->expects($this->any())
|
||||
->method('isIncomingServer2serverShareEnabled')->willReturn(true);
|
||||
|
||||
$this->shareController = new \OCA\Files_Sharing\Controllers\ShareController(
|
||||
$this->appName,
|
||||
|
@ -88,7 +101,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->shareManager,
|
||||
$this->session,
|
||||
$this->previewManager,
|
||||
$this->getMock('\OCP\Files\IRootFolder')
|
||||
$this->getMock('\OCP\Files\IRootFolder'),
|
||||
$this->federatedShareProvider
|
||||
);
|
||||
|
||||
|
||||
|
@ -116,6 +130,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
// Set old user
|
||||
\OC_User::setUserId($this->oldUser);
|
||||
\OC_Util::setupFS($this->oldUser);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testShowAuthenticateNotAuthenticated() {
|
||||
|
@ -173,7 +188,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->assertEquals($expectedResponse, $response);
|
||||
}
|
||||
|
||||
public function testAutehnticateInvalidToken() {
|
||||
public function testAuthenticateInvalidToken() {
|
||||
$this->shareManager
|
||||
->expects($this->once())
|
||||
->method('getShareByToken')
|
||||
|
@ -247,11 +262,11 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
->method('access')
|
||||
->with($this->callback(function(array $data) {
|
||||
return $data['itemType'] === 'file' &&
|
||||
$data['itemSource'] === 100 &&
|
||||
$data['uidOwner'] === 'initiator' &&
|
||||
$data['token'] === 'token' &&
|
||||
$data['errorCode'] === 403 &&
|
||||
$data['errorMessage'] === 'Wrong password';
|
||||
$data['itemSource'] === 100 &&
|
||||
$data['uidOwner'] === 'initiator' &&
|
||||
$data['token'] === 'token' &&
|
||||
$data['errorCode'] === 403 &&
|
||||
$data['errorMessage'] === 'Wrong password';
|
||||
}));
|
||||
|
||||
$response = $this->shareController->authenticate('token', 'invalidpassword');
|
||||
|
@ -323,6 +338,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
[
|
||||
['max_filesize_animated_gifs_public_sharing', 10, 10],
|
||||
['enable_previews', true, true],
|
||||
['preview_max_x', 1024, 1024],
|
||||
['preview_max_y', 1024, 1024],
|
||||
]
|
||||
);
|
||||
$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
|
||||
|
@ -354,6 +371,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'maxSizeAnimateGif' => 10,
|
||||
'previewSupported' => true,
|
||||
'previewEnabled' => true,
|
||||
'hideFileList' => false,
|
||||
'shareOwner' => 'ownerDisplay'
|
||||
);
|
||||
|
||||
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
|
||||
|
@ -412,10 +431,13 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->shareController->showShare('token');
|
||||
}
|
||||
|
||||
|
||||
public function testDownloadShare() {
|
||||
$share = $this->getMock('\OCP\Share\IShare');
|
||||
$share->method('getPassword')->willReturn('password');
|
||||
$share
|
||||
->expects($this->once())
|
||||
->method('getPermissions')
|
||||
->willReturn(\OCP\Constants::PERMISSION_READ);
|
||||
|
||||
$this->shareManager
|
||||
->expects($this->once())
|
||||
|
@ -434,4 +456,24 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->assertEquals($expectedResponse, $response);
|
||||
}
|
||||
|
||||
}
|
||||
public function testDownloadShareWithCreateOnlyShare() {
|
||||
$share = $this->getMock('\OCP\Share\IShare');
|
||||
$share->method('getPassword')->willReturn('password');
|
||||
$share
|
||||
->expects($this->once())
|
||||
->method('getPermissions')
|
||||
->willReturn(\OCP\Constants::PERMISSION_CREATE);
|
||||
|
||||
$this->shareManager
|
||||
->expects($this->once())
|
||||
->method('getShareByToken')
|
||||
->with('validtoken')
|
||||
->willReturn($share);
|
||||
|
||||
// Test with a password protected share and no authentication
|
||||
$response = $this->shareController->downloadShare('validtoken');
|
||||
$expectedResponse = new DataResponse('Share is read-only');
|
||||
$this->assertEquals($expectedResponse, $response);
|
||||
}
|
||||
|
||||
}
|
|
@ -85,7 +85,7 @@ class AvatarController extends Controller {
|
|||
IL10N $l10n,
|
||||
IUserManager $userManager,
|
||||
IUserSession $userSession,
|
||||
Folder $userFolder,
|
||||
Folder $userFolder = null,
|
||||
ILogger $logger) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
|
@ -101,6 +101,7 @@ class AvatarController extends Controller {
|
|||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @PublicPage
|
||||
*
|
||||
* @param string $userId
|
||||
* @param int $size
|
||||
|
|
|
@ -24,30 +24,31 @@
|
|||
'<br />' +
|
||||
'<label for="linkText-{{cid}}" class="hidden-visually">{{urlLabel}}</label>' +
|
||||
'<input id="linkText-{{cid}}" class="linkText {{#unless isLinkShare}}hidden{{/unless}}" type="text" readonly="readonly" value="{{shareLinkURL}}" />' +
|
||||
' {{#if showPasswordCheckBox}}' +
|
||||
'<input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' +
|
||||
'<label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' +
|
||||
' {{/if}}' +
|
||||
'<div id="linkPass" class="linkPass {{#unless isPasswordSet}}hidden{{/unless}}">' +
|
||||
' <label for="linkPassText-{{cid}}" class="hidden-visually">{{passwordLabel}}</label>' +
|
||||
' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" />' +
|
||||
' <span class="icon-loading-small hidden"></span>' +
|
||||
'</div>' +
|
||||
' {{#if publicUpload}}' +
|
||||
'<div id="allowPublicUploadWrapper">' +
|
||||
' <span class="icon-loading-small hidden"></span>' +
|
||||
' <input type="checkbox" value="1" name="allowPublicUpload" id="sharingDialogAllowPublicUpload-{{cid}}" class="checkbox publicUploadCheckbox" {{{publicUploadChecked}}} />' +
|
||||
'<label for="sharingDialogAllowPublicUpload-{{cid}}">{{publicUploadLabel}}</label>' +
|
||||
'</div>' +
|
||||
' {{#if hideFileList}}' +
|
||||
'<div id="hideFileListWrapper">' +
|
||||
' <span class="icon-loading-small hidden"></span>' +
|
||||
' <input type="checkbox" value="1" name="hideFileList" id="sharingDialogHideFileList-{{cid}}" class="checkbox hideFileListCheckbox" {{{hideFileListChecked}}} />' +
|
||||
'<label for="sharingDialogHideFileList-{{cid}}">{{hideFileListLabel}}</label>' +
|
||||
'</div>' +
|
||||
' {{/if}}' +
|
||||
' {{/if}}' +
|
||||
' {{#if mailPublicNotificationEnabled}}' +
|
||||
'<form id="emailPrivateLink" class="emailPrivateLinkForm">' +
|
||||
' <input id="email" class="emailField" value="{{email}}" placeholder="{{mailPrivatePlaceholder}}" type="text" />' +
|
||||
' <input id="emailButton" class="emailButton" type="submit" value="{{mailButtonText}}" />' +
|
||||
'</form>' +
|
||||
' {{#if showPasswordCheckBox}}' +
|
||||
'<input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' +
|
||||
'<label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' +
|
||||
' {{/if}}' +
|
||||
'<div id="linkPass" class="linkPass {{#unless isPasswordSet}}hidden{{/unless}}">' +
|
||||
' <label for="linkPassText-{{cid}}" class="hidden-visually">{{passwordLabel}}</label>' +
|
||||
' <input id="linkPassText-{{cid}}" class="linkPassText" type="password" placeholder="{{passwordPlaceholder}}" />' +
|
||||
' <span class="icon-loading-small hidden"></span>' +
|
||||
'</div>' +
|
||||
'{{else}}' +
|
||||
// FIXME: this doesn't belong in this view
|
||||
// FIXME: this doesn't belong in this view
|
||||
'{{#if noSharingPlaceholder}}<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled"/>{{/if}}' +
|
||||
'{{/if}}'
|
||||
;
|
||||
|
@ -76,12 +77,12 @@
|
|||
showLink: true,
|
||||
|
||||
events: {
|
||||
'submit .emailPrivateLinkForm': '_onEmailPrivateLink',
|
||||
'focusout input.linkPassText': 'onPasswordEntered',
|
||||
'keyup input.linkPassText': 'onPasswordKeyUp',
|
||||
'click .linkCheckbox': 'onLinkCheckBoxChange',
|
||||
'click .linkText': 'onLinkTextClick',
|
||||
'change .publicUploadCheckbox': 'onAllowPublicUploadChange',
|
||||
'change .hideFileListCheckbox': 'onHideFileListChange',
|
||||
'click .showPasswordCheckbox': 'onShowPasswordClick'
|
||||
},
|
||||
|
||||
|
@ -100,6 +101,10 @@
|
|||
view.render();
|
||||
});
|
||||
|
||||
this.model.on('change:hideFileListStatus', function() {
|
||||
view.render();
|
||||
});
|
||||
|
||||
this.model.on('change:linkShare', function() {
|
||||
view.render();
|
||||
});
|
||||
|
@ -112,12 +117,12 @@
|
|||
|
||||
_.bindAll(
|
||||
this,
|
||||
'_onEmailPrivateLink',
|
||||
'onLinkCheckBoxChange',
|
||||
'onPasswordEntered',
|
||||
'onPasswordKeyUp',
|
||||
'onLinkTextClick',
|
||||
'onShowPasswordClick',
|
||||
'onHideFileListChange',
|
||||
'onAllowPublicUploadChange'
|
||||
);
|
||||
},
|
||||
|
@ -218,38 +223,23 @@
|
|||
});
|
||||
},
|
||||
|
||||
_onEmailPrivateLink: function(event) {
|
||||
event.preventDefault();
|
||||
onHideFileListChange: function () {
|
||||
var $checkbox = this.$('.hideFileListCheckbox');
|
||||
$checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock');
|
||||
|
||||
var $emailField = this.$el.find('.emailField');
|
||||
var $emailButton = this.$el.find('.emailButton');
|
||||
var email = $emailField.val();
|
||||
if (email !== '') {
|
||||
$emailField.prop('disabled', true);
|
||||
$emailButton.prop('disabled', true);
|
||||
$emailField.val(t('core', 'Sending ...'));
|
||||
this.model.sendEmailPrivateLink(email).done(function() {
|
||||
$emailField.css('font-weight', 'bold').val(t('core','Email sent'));
|
||||
setTimeout(function() {
|
||||
$emailField.val('');
|
||||
$emailField.css('font-weight', 'normal');
|
||||
$emailField.prop('disabled', false);
|
||||
$emailButton.prop('disabled', false);
|
||||
}, 2000);
|
||||
}).fail(function() {
|
||||
$emailField.val(email);
|
||||
$emailField.css('font-weight', 'normal');
|
||||
$emailField.prop('disabled', false);
|
||||
$emailButton.prop('disabled', false);
|
||||
});
|
||||
var permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ;
|
||||
if ($checkbox.is(':checked')) {
|
||||
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE;
|
||||
}
|
||||
return false;
|
||||
|
||||
this.model.saveLinkShare({
|
||||
permissions: permissions
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var linkShareTemplate = this.template();
|
||||
var resharingAllowed = this.model.sharePermissionPossible();
|
||||
var email = this.$el.find('.emailField').val();
|
||||
|
||||
if(!resharingAllowed
|
||||
|| !this.showLink
|
||||
|
@ -274,15 +264,23 @@
|
|||
publicUploadChecked = 'checked="checked"';
|
||||
}
|
||||
|
||||
var hideFileList = publicUploadChecked;
|
||||
|
||||
var hideFileListChecked = '';
|
||||
if(this.model.isHideFileListSet()) {
|
||||
hideFileListChecked = 'checked="checked"';
|
||||
}
|
||||
|
||||
var isLinkShare = this.model.get('linkShare').isLinkShare;
|
||||
var isPasswordSet = !!this.model.get('linkShare').password;
|
||||
var showPasswordCheckBox = isLinkShare
|
||||
&& ( !this.configModel.get('enforcePasswordForPublicLink')
|
||||
|| !this.model.get('linkShare').password);
|
||||
|| !this.model.get('linkShare').password);
|
||||
|
||||
this.$el.html(linkShareTemplate({
|
||||
cid: this.cid,
|
||||
shareAllowed: true,
|
||||
hideFileList: hideFileList,
|
||||
isLinkShare: isLinkShare,
|
||||
shareLinkURL: this.model.get('linkShare').link,
|
||||
linkShareLabel: t('core', 'Share link'),
|
||||
|
@ -294,46 +292,14 @@
|
|||
showPasswordCheckBox: showPasswordCheckBox,
|
||||
publicUpload: publicUpload && isLinkShare,
|
||||
publicUploadChecked: publicUploadChecked,
|
||||
hideFileListChecked: hideFileListChecked,
|
||||
publicUploadLabel: t('core', 'Allow editing'),
|
||||
hideFileListLabel: t('core', 'Hide file listing'),
|
||||
mailPublicNotificationEnabled: isLinkShare && this.configModel.isMailPublicNotificationEnabled(),
|
||||
mailPrivatePlaceholder: t('core', 'Email link to person'),
|
||||
mailButtonText: t('core', 'Send'),
|
||||
email: email
|
||||
mailButtonText: t('core', 'Send')
|
||||
}));
|
||||
|
||||
var $emailField = this.$el.find('.emailField');
|
||||
if (isLinkShare && $emailField.length !== 0) {
|
||||
$emailField.autocomplete({
|
||||
minLength: 1,
|
||||
source: function (search, response) {
|
||||
$.get(
|
||||
OC.generateUrl('core/ajax/share.php'), {
|
||||
fetch: 'getShareWithEmail',
|
||||
search: search.term
|
||||
}, function(result) {
|
||||
if (result.status == 'success' && result.data.length > 0) {
|
||||
response(result.data);
|
||||
}
|
||||
});
|
||||
},
|
||||
select: function( event, item ) {
|
||||
$emailField.val(item.item.email);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.data("ui-autocomplete")._renderItem = function( ul, item ) {
|
||||
return $('<li>')
|
||||
.append('<a>' + escapeHTML(item.displayname) + "<br>" + escapeHTML(item.email) + '</a>' )
|
||||
.appendTo( ul );
|
||||
};
|
||||
}
|
||||
|
||||
// TODO drop with IE8 drop
|
||||
if($('html').hasClass('ie8')) {
|
||||
this.$el.find('#linkPassText').removeAttr('placeholder');
|
||||
this.$el.find('#linkPassText').val('');
|
||||
}
|
||||
|
||||
this.delegateEvents();
|
||||
|
||||
return this;
|
||||
|
@ -354,4 +320,4 @@
|
|||
|
||||
OC.Share.ShareDialogLinkShareView = ShareDialogLinkShareView;
|
||||
|
||||
})();
|
||||
})();
|
|
@ -154,21 +154,17 @@
|
|||
// Default permissions are Edit (CRUD) and Share
|
||||
// Check if these permissions are possible
|
||||
var permissions = OC.PERMISSION_READ;
|
||||
if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
|
||||
permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_READ;
|
||||
} else {
|
||||
if (this.updatePermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_UPDATE;
|
||||
}
|
||||
if (this.createPermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_CREATE;
|
||||
}
|
||||
if (this.deletePermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_DELETE;
|
||||
}
|
||||
if (this.configModel.get('isResharingAllowed') && (this.sharePermissionPossible())) {
|
||||
permissions = permissions | OC.PERMISSION_SHARE;
|
||||
}
|
||||
if (this.updatePermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_UPDATE;
|
||||
}
|
||||
if (this.createPermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_CREATE;
|
||||
}
|
||||
if (this.deletePermissionPossible()) {
|
||||
permissions = permissions | OC.PERMISSION_DELETE;
|
||||
}
|
||||
if (this.configModel.get('isResharingAllowed') && (this.sharePermissionPossible())) {
|
||||
permissions = permissions | OC.PERMISSION_SHARE;
|
||||
}
|
||||
|
||||
attributes.permissions = permissions;
|
||||
|
@ -276,6 +272,13 @@
|
|||
return this.get('allowPublicUploadStatus');
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isHideFileListSet: function() {
|
||||
return this.get('hideFileListStatus');
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
@ -411,12 +414,6 @@
|
|||
if(!_.isObject(share)) {
|
||||
throw "Unknown Share";
|
||||
}
|
||||
if( share.share_type === OC.Share.SHARE_TYPE_REMOTE
|
||||
&& ( permission === OC.PERMISSION_SHARE
|
||||
|| permission === OC.PERMISSION_DELETE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (share.permissions & permission) === permission;
|
||||
},
|
||||
|
||||
|
@ -487,7 +484,7 @@
|
|||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
@ -557,8 +554,8 @@
|
|||
*/
|
||||
editPermissionPossible: function() {
|
||||
return this.createPermissionPossible()
|
||||
|| this.updatePermissionPossible()
|
||||
|| this.deletePermissionPossible();
|
||||
|| this.updatePermissionPossible()
|
||||
|| this.deletePermissionPossible();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -566,8 +563,8 @@
|
|||
*/
|
||||
hasEditPermission: function(shareIndex) {
|
||||
return this.hasCreatePermission(shareIndex)
|
||||
|| this.hasUpdatePermission(shareIndex)
|
||||
|| this.hasDeletePermission(shareIndex);
|
||||
|| this.hasUpdatePermission(shareIndex)
|
||||
|| this.hasDeletePermission(shareIndex);
|
||||
},
|
||||
|
||||
_getUrl: function(base, params) {
|
||||
|
@ -695,6 +692,16 @@
|
|||
});
|
||||
}
|
||||
|
||||
var hideFileListStatus = false;
|
||||
if(!_.isUndefined(data.shares)) {
|
||||
$.each(data.shares, function (key, value) {
|
||||
if (value.share_type === OC.Share.SHARE_TYPE_LINK) {
|
||||
hideFileListStatus = (value.permissions & OC.PERMISSION_READ) ? false : true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @type {OC.Share.Types.ShareInfo[]} **/
|
||||
var shares = _.map(data.shares, function(share) {
|
||||
// properly parse some values because sometimes the server
|
||||
|
@ -767,7 +774,8 @@
|
|||
shares: shares,
|
||||
linkShare: linkShare,
|
||||
permissions: permissions,
|
||||
allowPublicUploadStatus: allowPublicUploadStatus
|
||||
allowPublicUploadStatus: allowPublicUploadStatus,
|
||||
hideFileListStatus: hideFileListStatus
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -793,4 +801,4 @@
|
|||
});
|
||||
|
||||
OC.Share.ShareItemModel = ShareItemModel;
|
||||
})();
|
||||
})();
|
|
@ -233,8 +233,9 @@ class Manager implements IManager {
|
|||
throw new GenericShareException($message_t, $message_t, 404);
|
||||
}
|
||||
|
||||
// Check that read permissions are always set
|
||||
if (($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
|
||||
// Link shares are allowed to have no read permissions to allow upload to hidden folders
|
||||
if ($share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK &&
|
||||
($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
|
||||
throw new \InvalidArgumentException('Shares need at least read permissions');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,7 +670,6 @@ class ManagerTest extends \Test\TestCase {
|
|||
|
||||
$data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true];
|
||||
$data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true];
|
||||
$data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $allPermssions, null, $user0, $user0, 16, null, null), 'Shares need at least read permissions', true];
|
||||
|
||||
$data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false];
|
||||
$data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false];
|
||||
|
|
Loading…
Reference in New Issue