You cannot move a non-shareable node into a share

We have an External storage set up to expose a local folder on our Nextcloud. That folder is also accessible via SMB. So, we often use the following workflow:

  • In OS, move file into SMB share
  • In Nextcloud, move file from External storage to a folder shared with Nextcloud.

With the most recent update, we started getting the following error:
“You cannot move a non-shareable node into a share”

It comes from this part of the code:

	/**
	 * Ensure that when copying or moving a node it is not transferred from one share to another,
	 * if the user is neither the owner nor has re-share permissions.
	 * For share creation we already ensure this in the share manager.
	 */
	public function validateMoveOrCopy(string $source, string $target): bool {
		try {
			$targetNode = $this->tree->getNodeForPath($target);
		} catch (NotFound) {
			[$targetPath,] = \Sabre\Uri\split($target);
			$targetNode = $this->tree->getNodeForPath($targetPath);
		}

		$sourceNode = $this->tree->getNodeForPath($source);
		if ((!$sourceNode instanceof DavNode) || (!$targetNode instanceof DavNode)) {
			return true;
		}

		$sourceNode = $sourceNode->getNode();
		if ($sourceNode->isShareable()) {
			return true;
		}

		$targetShares = $this->getShare($targetNode->getNode());
		if (empty($targetShares)) {
			// Target is not a share so no re-sharing inprogress
			return true;
		}

		$sourceStorage = $sourceNode->getStorage();
		if ($sourceStorage->instanceOfStorage(ISharedStorage::class)) {
			// source is also a share - check if it is the same share

			/** @var ISharedStorage $sourceStorage */
			$sourceShare = $sourceStorage->getShare();
			foreach ($targetShares as $targetShare) {
				if ($targetShare->getId() === $sourceShare->getId()) {
					return true;
				}
			}
		}

		throw new Forbidden('You cannot move a non-shareable node into a share');
	}

So it would seem that when I transfer a file via SMB, I am not the owner and so I do not have permission to move the file into a share.

In the code above, I don’t see any check for configuration or any special casing for External storage. It seems that my use case with External storage is behaving a little differently that this code expected.

We have workarounds at the moment: move into a non-shared folder, then into the shared folder or transfer directly to the shared folder. However, it is confusing for new users and a speed bump for everyone.

This prevention seems to be more inconvenience than security, especially if it is that easy to work around in other cases. I think the implementation could be reconsidered to achieve its goals with a better user experience.

(Let me know if this is not normal behaviour and you need specific instance details.)