Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update re-share if shared-by user has been revoked #43025

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

luka-nextcloud
Copy link
Contributor

Summary

TODO

  • ...

Checklist

@luka-nextcloud
Copy link
Contributor Author

Another effected case by this issue:

  1. UserA share Folder1 to UserB
  2. UserB share Folder1 to UserC
  3. UserA revoke UserB
  4. UserA try to update sharing permission of UserC
    -> Error: Could not get proper share mount for . Failing since else the next calls are called with null

@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch 2 times, most recently from c298bf1 to 0828727 Compare February 5, 2024 18:28
@luka-nextcloud
Copy link
Contributor Author

@artonge I've updated as you requested, please check again.

Copy link
Contributor

@artonge artonge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add comments to clarify what each if group does?

I am also wondering if we could find this shares with the following query:

SELECT
	f.fileid,
	f.path,
	f.storage,
	s.id as share_id,
	s.uid_owner as share_owner,
	s.uid_initiator as share_initiator,
	s.share_with as share_recipient
FROM
	oc_filecache f
	JOIN oc_share s ON f.fileid = s.file_source
	AND s.uid_initiator NOT IN (
		SELECT
			user_id
		FROM
			oc_mounts m
		WHERE
			f.storage = m.storage_id
	)

If so, then we could have a background job to remove them every hour or so like https://github.com/nextcloud/server/blob/master/apps/files_sharing/lib/DeleteOrphanedSharesJob.php, which might be easier than the current solution.

lib/private/Share20/Manager.php Outdated Show resolved Hide resolved
lib/private/Share20/Manager.php Outdated Show resolved Hide resolved
lib/private/Share20/Manager.php Outdated Show resolved Hide resolved
@luka-nextcloud
Copy link
Contributor Author

Can you add comments to clarify what each if group does?

I am also wondering if we could find this shares with the following query:

SELECT
	f.fileid,
	f.path,
	f.storage,
	s.id as share_id,
	s.uid_owner as share_owner,
	s.uid_initiator as share_initiator,
	s.share_with as share_recipient
FROM
	oc_filecache f
	JOIN oc_share s ON f.fileid = s.file_source
	AND s.uid_initiator NOT IN (
		SELECT
			user_id
		FROM
			oc_mounts m
		WHERE
			f.storage = m.storage_id
	)

If so, then we could have a background job to remove them every hour or so like https://github.com/nextcloud/server/blob/master/apps/files_sharing/lib/DeleteOrphanedSharesJob.php, which might be easier than the current solution.

@artonge It only works if the shared-by user refreshes his files list after his share has revoked. So, I don't think this query would do the job.

@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch 3 times, most recently from 007d650 to df7160f Compare April 1, 2024 08:13
@susnux susnux added this to the Nextcloud 30 milestone Apr 18, 2024
@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch from df7160f to 73fb85b Compare May 30, 2024 12:15
apps/files_sharing/lib/Command/FixBrokenShares.php Outdated Show resolved Hide resolved
apps/files_sharing/lib/Command/FixBrokenShares.php Outdated Show resolved Hide resolved
apps/files_sharing/lib/Command/FixBrokenShares.php Outdated Show resolved Hide resolved
apps/files_sharing/lib/OrphanHelper.php Outdated Show resolved Hide resolved
@skjnldsv skjnldsv removed their request for review June 3, 2024 08:07
@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch from 7e64905 to cf9b02a Compare June 4, 2024 18:39
apps/files_sharing/lib/OrphanHelper.php Outdated Show resolved Hide resolved
apps/files_sharing/lib/Command/FixBrokenShares.php Outdated Show resolved Hide resolved
lib/private/Share20/Manager.php Outdated Show resolved Hide resolved
@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch 4 times, most recently from 0d42361 to 032be69 Compare June 17, 2024 15:11
@luka-nextcloud
Copy link
Contributor Author

@come-nc Could you please review again? All checks have passed now.


public function __construct(
IDBConnection $connection,
IRootFolder $rootFolder
IRootFolder $rootFolder,
IUserMountCache $userMountCache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IUserMountCache $userMountCache
IUserMountCache $userMountCache,


foreach ($sharesInFolder as $shares) {
foreach ($shares as $child) {
$this->deleteShare($child);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For subfiles you did not check that the user still has access to it, I think?

Comment on lines 1129 to 1032
// If the user has another shares, we don't delete the shares by this user
if ($share->getShareType() === IShare::TYPE_USER) {
$groupShares = $this->getSharedWith($share->getSharedWith(), IShare::TYPE_GROUP, $node, -1, 0);

if (count($groupShares) !== 0) {
return;
}

// Check shares of parent folders
try {
$parentNode = $node->getParent();
while ($parentNode) {
$groupShares = $this->getSharedWith($share->getSharedWith(), IShare::TYPE_GROUP, $parentNode, -1, 0);
$userShares = $this->getSharedWith($share->getSharedWith(), IShare::TYPE_USER, $parentNode, -1, 0);

if (count($groupShares) !== 0 || count($userShares) !== 0) {
return;
}

$parentNode = $parentNode->getParent();
}
} catch (NotFoundException) {
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing all this to check if the user still has access to the file or not, does it not make more sense to directly check if the user has access to the file? We must have some tooling for that, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@come-nc I cannot find another way to check this logic. Could you provide some suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get the user folder of the user and use getFirstNodeById would work I think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note that this would only work after deleting the share)

@come-nc
Copy link
Contributor

come-nc commented Jun 24, 2024

@luka-nextcloud After talking with Robin, actually the ownership transfer is supposed to update the owner of the share so there should be no problem in the first place?

@luka-nextcloud
Copy link
Contributor Author

@come-nc Does it mean that these changes are enough for this issue?

image

image

@come-nc
Copy link
Contributor

come-nc commented Jun 25, 2024

@come-nc Does it mean that these changes are enough for this issue?

image

image

No, the second diff looks like it will cause trouble by arbitrary changing sharedBy of shares.

I lost track of what you are trying to fix, can you explain how to reproduce your problem? Why do you remove the exception handling removing invalid shares in OwnershipTransferService?

@luka-nextcloud
Copy link
Contributor Author

@come-nc

  • Reproduce steps:
  1. UserA share Folder1 to UserB
  2. UserB share Folder1 to UserC
  3. UserA deleted sharing to UserB
  4. UserA transfer Folder1 to UserD
    -> UserC lost access to Folder1. When UserC open sharing tab of Folder1, the error message Error: Could not get proper share mount for . Failing since else the next calls are called with null returned.
  • Issue occurred because the sharing of UserB to UserC was not deleted or updated after UserA deleted sharing to UserB. Then, when UserA transfering Folder1 to UserD, that re-share record cannot be transferred because it throws GenericShareException error.

@come-nc
Copy link
Contributor

come-nc commented Jun 27, 2024

@come-nc

  • Reproduce steps:
  1. UserA share Folder1 to UserB
  2. UserB share Folder1 to UserC
  3. UserA deleted sharing to UserB
  4. UserA transfer Folder1 to UserD
    -> UserC lost access to Folder1. When UserC open sharing tab of Folder1, the error message Error: Could not get proper share mount for . Failing since else the next calls are called with null returned.
  • Issue occurred because the sharing of UserB to UserC was not deleted or updated after UserA deleted sharing to UserB. Then, when UserA transfering Folder1 to UserD, that re-share record cannot be transferred because it throws GenericShareException error.

UserC already loses access to Folder1 after step 3, right?
At that point the sharing tab shows no error?

@luka-nextcloud
Copy link
Contributor Author

@come-nc

UserC already loses access to Folder1 after step 3, right?

No, UserC didn't lose access to Folder1 after step3. This is the issue we are trying to fix.

At that point the sharing tab shows no error?

No error.

@luka-nextcloud
Copy link
Contributor Author

@come-nc
Original problem:
Re-share was not deleted when parent share deleted. Then, it caused error while transferring ownership.

Reproduce steps:
Mentioned above.

Solution:
Delete the re-share and its children when parent share is deleted.

This was referenced Jul 30, 2024
@Altahrim Altahrim mentioned this pull request Aug 5, 2024
@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch from a03da0a to e1450ee Compare August 7, 2024 09:23
@Altahrim Altahrim mentioned this pull request Aug 7, 2024
@AndyScherzinger AndyScherzinger force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch from e1450ee to 522cf26 Compare August 7, 2024 21:58
Comment on lines 1089 to 1093
foreach ($shares as $child) {
if ($this->hasNodeAccess($user->getUID(), $child->getNode())) {
continue;
}
$this->deleteShare($child);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is generalCreateCheck method not directly run on $child instead?
I do not understand the logic in hasNodeAccess, it searches for other shares of the same node but only directly to the user?

Also, the code is duplicated between user shares and group shares, please first compute an array of target users and then loop on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@come-nc Ok, I have checked again. The logic in hasNodeAccess was not really correct. It missed some cases. So, I removed that function and updated approach for deleteReshare. First collect related user ids, then collect the re-share by those users, finally do generalCreateCheck on those re-share records.

@skjnldsv skjnldsv mentioned this pull request Aug 13, 2024
Signed-off-by: Luka Trovic <luka@nextcloud.com>
@luka-nextcloud luka-nextcloud force-pushed the bugfix/error-on-reshare-after-transfer-ownership branch from 522cf26 to b23eafb Compare August 13, 2024 19:00
@skjnldsv skjnldsv modified the milestones: Nextcloud 30, Nextcloud 31 Aug 14, 2024
lib/private/Share20/Manager.php Show resolved Hide resolved
foreach ($userIds as $userId) {
foreach ($shareTypes as $shareType) {
$provider = $this->factory->getProviderForType($shareType);
$shares = $provider->getSharesBy($userId, $shareType, $node, false, -1, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you pass false for $reshares flag here but true in the call to getSharesInFolder below?

return null;
}
foreach ($mounts as $mount) {
// Only the mount of owner has the internal path value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icewind1991 Could you provide a suggestion?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check if $mount is a HomeMountPoint and then use $mount->getUser()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3. to review Waiting for reviews bug
Projects
Status: 👀 In review
Development

Successfully merging this pull request may close these issues.

[Bug]: Sub folder shares were broken on ownership transfer
6 participants