Merge pull request #52226 from nextcloud/backport/52180/stable31

[stable31] fix(files_sharing): bring back handling of `hide-download` on public shares
This commit is contained in:
Ferdinand Thiessen 2025-04-27 15:07:15 +02:00 committed by GitHub
commit 3cd879ff61
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 68 additions and 41 deletions

View file

@ -14,6 +14,7 @@ use OCP\Constants;
use OCP\Files\ForbiddenException;
use OCP\Files\IFilenameValidator;
use OCP\Files\InvalidPathException;
use OCP\Files\Storage\ISharedStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\FilesMetadata\Exceptions\FilesMetadataException;
use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
@ -63,6 +64,7 @@ class FilesPlugin extends ServerPlugin {
public const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
public const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
public const SHARE_NOTE = '{http://nextcloud.org/ns}note';
public const SHARE_HIDE_DOWNLOAD_PROPERTYNAME = '{http://nextcloud.org/ns}hide-download';
public const SUBFOLDER_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-folder-count';
public const SUBFILE_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-file-count';
public const FILE_METADATA_PREFIX = '{http://nextcloud.org/ns}metadata-';
@ -390,6 +392,19 @@ class FilesPlugin extends ServerPlugin {
);
});
$propFind->handle(self::SHARE_HIDE_DOWNLOAD_PROPERTYNAME, function () use ($node) {
$storage = $node->getNode()->getStorage();
if ($storage->instanceOfStorage(ISharedStorage::class)) {
/** @var ISharedStorage $storage */
return match($storage->getShare()->getHideDownload()) {
true => 'true',
false => 'false',
};
} else {
return null;
}
});
$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () {
return $this->config->getSystemValue('data-fingerprint', '');
});
@ -677,8 +692,6 @@ class FilesPlugin extends ServerPlugin {
return IMetadataValueWrapper::EDIT_REQ_READ_PERMISSION;
}
/**
* @param string $filePath
* @param ?\Sabre\DAV\INode $node

View file

@ -88,7 +88,7 @@ export const action = new FileAction({
}
// We can only download dav files and folders.
if (nodes.some(node => !node.isDavRessource)) {
if (nodes.some(node => !node.isDavResource)) {
return false
}

View file

@ -17,6 +17,13 @@ export function isDownloadable(node: Node): boolean {
return false
}
// check hide-download property of shares
if (node.attributes['hide-download'] === true
|| node.attributes['hide-download'] === 'true'
) {
return false
}
// If the mount type is a share, ensure it got download permissions.
if (node.attributes['share-attributes']) {
const shareAttributes = JSON.parse(node.attributes['share-attributes'] || '[]') as Array<ShareAttribute>

View file

@ -1293,16 +1293,11 @@ class ShareAPIController extends OCSController {
|| $share->getShareType() === IShare::TYPE_EMAIL) {
// Update hide download state
$attributes = $share->getAttributes() ?? $share->newAttributes();
if ($hideDownload === 'true') {
$share->setHideDownload(true);
$attributes->setAttribute('permissions', 'download', false);
} elseif ($hideDownload === 'false') {
$share->setHideDownload(false);
$attributes->setAttribute('permissions', 'download', true);
}
$share->setAttributes($attributes);
// If either manual permissions are specified or publicUpload
// then we need to also update the permissions of the share

View file

@ -146,7 +146,7 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
// Create the header action menu
$headerActions = [];
if ($view !== 'public-file-drop') {
if ($view !== 'public-file-drop' && !$share->getHideDownload()) {
// The download URL is used for the "download" header action as well as in some cases for the direct link
$downloadUrl = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
'token' => $token,
@ -157,7 +157,7 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
$headerActions[] = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $downloadUrl, 0, (string)$shareNode->getSize());
// If remote sharing is enabled also add the remote share action to the menu
if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled() && !$share->getHideDownload()) {
if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
$headerActions[] = new ExternalShareMenuAction(
// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
$this->l10n->t('Add to your %s', [$this->defaults->getProductName()]),

View file

@ -2,7 +2,8 @@
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { addNewFileMenuEntry, registerDavProperty } from '@nextcloud/files'
import { addNewFileMenuEntry } from '@nextcloud/files'
import { registerDavProperty } from '@nextcloud/files/dav'
import { registerAccountFilter } from './files_filters/AccountFilter'
import { entry as newFileRequest } from './files_newMenu/newFileRequest'
@ -21,6 +22,7 @@ addNewFileMenuEntry(newFileRequest)
registerDavProperty('nc:note', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:sharees', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:hide-download', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:share-attributes', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('oc:share-types', { oc: 'http://owncloud.org/ns' })
registerDavProperty('ocs:share-permissions', { ocs: 'http://open-collaboration-services.org/ns' })

View file

@ -252,6 +252,15 @@ export default class Share {
* Hide the download button on public page
*/
set hideDownload(state: boolean) {
// disabling hide-download also enables the download permission
// needed for regression in Nextcloud 31.0.0 until (incl.) 31.0.3
if (!state) {
const attribute = this.attributes.find(({ key, scope }) => key === 'download' && scope === 'permissions')
if (attribute) {
attribute.value = true
}
}
this._share.hide_download = state === true
}

View file

@ -94,6 +94,7 @@ const ocsEntryToNode = async function(ocsEntry: any): Promise<Folder | File | nu
attributes: {
...ocsEntry,
'has-preview': hasPreview,
'hide-download': ocsEntry?.hide_download === 1,
// Also check the sharingStatusAction.ts code
'owner-id': ocsEntry?.uid_owner,
'owner-display-name': ocsEntry?.displayname_owner,

4
dist/5291-5291.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/5329-5329.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/core-common.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/files-init.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/files-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long