Skip to content

Commit dbf87f3

Browse files
cristianscheidbackportbot[bot]
authored andcommitted
fix: resolve share mount for remote circle members
fix: resolve share mount for remote circle members Signed-off-by: Cristian Scheid <cristianscheid@gmail.com> [skip ci]
1 parent 95dc1de commit dbf87f3

7 files changed

Lines changed: 97 additions & 2 deletions

File tree

‎lib/AppInfo/Application.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public function boot(IBootContext $context): void {
154154

155155
public function registerMountProvider(ContainerInterface $container): void {
156156
$configService = $container->get(ConfigService::class);
157-
if (!$configService->isGSAvailable()) {
157+
if (!$configService->isGSAvailable() && !$configService->isFederatedTeamsEnabled()) {
158158
return;
159159
}
160160

‎lib/Db/MountPointRequest.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,11 @@ public function update(Mountpoint $mountpoint): void {
4949
throw new MountNotFoundException('Mount not found');
5050
}
5151
}
52+
53+
public function deleteByMountId(string $mountId): void {
54+
$qb = $this->getMountPointDeleteSql();
55+
56+
$qb->limit('mount_id', $mountId);
57+
$qb->executeStatement();
58+
}
5259
}

‎lib/Db/MountRequest.php‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use OCA\Circles\Exceptions\RequestBuilderException;
1515
use OCA\Circles\IFederatedUser;
1616
use OCA\Circles\Model\Mount;
17+
use OCA\Circles\Service\ConfigService;
18+
use OCA\Circles\Service\TimezoneService;
1719
use OCA\Circles\Tools\Traits\TStringTools;
1820
use OCP\DB\QueryBuilder\IQueryBuilder;
1921

@@ -25,6 +27,13 @@
2527
class MountRequest extends MountRequestBuilder {
2628
use TStringTools;
2729

30+
public function __construct(
31+
TimezoneService $timezoneService,
32+
ConfigService $configService,
33+
private MountPointRequest $mountPointRequest,
34+
) {
35+
parent::__construct($timezoneService, $configService);
36+
}
2837

2938
/**
3039
* @param Mount $mount
@@ -49,10 +58,39 @@ public function save(Mount $mount): void {
4958
* @param string $token
5059
*/
5160
public function delete(string $token): void {
61+
$qb = $this->getMountSelectSql();
62+
$qb->limitToToken($token);
63+
$mounts = $this->getItemsFromRequest($qb);
64+
5265
$qb = $this->getMountDeleteSql();
5366
$qb->limitToToken($token);
67+
$qb->executeStatement();
68+
69+
foreach ($mounts as $mount) {
70+
$this->mountPointRequest->deleteByMountId($mount->getMountId());
71+
}
72+
}
5473

74+
public function hasMountForCircleId(string $circleId): bool {
75+
$qb = $this->getMountSelectSql();
76+
$qb->limitToCircleId($circleId);
77+
$qb->setMaxResults(1);
78+
79+
return count($this->getItemsFromRequest($qb)) > 0;
80+
}
81+
82+
public function deleteByCircleId(string $circleId): void {
83+
$qb = $this->getMountSelectSql();
84+
$qb->limitToCircleId($circleId);
85+
$mounts = $this->getItemsFromRequest($qb);
86+
87+
$qb = $this->getMountDeleteSql();
88+
$qb->limitToCircleId($circleId);
5589
$qb->executeStatement();
90+
91+
foreach ($mounts as $mount) {
92+
$this->mountPointRequest->deleteByMountId($mount->getMountId());
93+
}
5694
}
5795

5896

‎lib/Listeners/Files/RemovingMember.php‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace OCA\Circles\Listeners\Files;
1313

14+
use OCA\Circles\Db\MemberRequest;
15+
use OCA\Circles\Db\MountRequest;
1416
use OCA\Circles\Events\RemovingCircleMemberEvent;
1517
use OCA\Circles\Exceptions\MembershipNotFoundException;
1618
use OCA\Circles\Model\Member;
@@ -31,17 +33,23 @@ class RemovingMember implements IEventListener {
3133
private MemberService $memberService;
3234
private ShareTokenService $shareTokenService;
3335
private ShareWrapperService $shareWrapperService;
36+
private MemberRequest $memberRequest;
37+
private MountRequest $mountRequest;
3438

3539
public function __construct(
3640
LoggerInterface $logger,
3741
MemberService $memberService,
3842
ShareTokenService $shareTokenService,
3943
ShareWrapperService $shareWrapperService,
44+
MemberRequest $memberRequest,
45+
MountRequest $mountRequest,
4046
) {
4147
$this->logger = $logger;
4248
$this->memberService = $memberService;
4349
$this->shareTokenService = $shareTokenService;
4450
$this->shareWrapperService = $shareWrapperService;
51+
$this->memberRequest = $memberRequest;
52+
$this->mountRequest = $mountRequest;
4553
}
4654

4755
public function handle(Event $event): void {
@@ -78,11 +86,50 @@ function (Membership $membership) {
7886

7987
if ($member->getUserType() === Member::TYPE_USER) {
8088
$this->removingSharesInternalMember($member, $singleIds);
89+
$this->removingMountsIfLastLocalMember($member, $singleIds);
8190
}
8291
}
8392
}
8493

8594

95+
/**
96+
* A circle mount is created on the local instance when a file or folder is
97+
* shared on the remote instance with a circle that lives there but also has
98+
* members on the local instance. This mount is used by every member of the
99+
* local instance who belongs to that remote circle.
100+
*
101+
* Removing a share on a remote circle only propagates to instances that still
102+
* have a member in that circle. Once the last local member leaves, the local
103+
* instance stops receiving that propagation, so we have to remove the mount
104+
* at this point.
105+
*
106+
* We have to iterate through every parent circle this member's circle belongs
107+
* to, checking for circles where this member leaving would be the last local
108+
* member leaving that circle, and thus where the mount must be removed.
109+
*
110+
* @param Member $member the member being removed
111+
* @param string[] $singleIds parent circles this member's circle belongs to
112+
*/
113+
private function removingMountsIfLastLocalMember(Member $member, array $singleIds): void {
114+
if (!$member->isLocal()) {
115+
return;
116+
}
117+
118+
foreach ($singleIds as $singleId) {
119+
if (!$this->mountRequest->hasMountForCircleId($singleId)) {
120+
continue;
121+
}
122+
123+
foreach ($this->memberRequest->getInheritedMembers($singleId) as $remainingMember) {
124+
if ($remainingMember->getUserType() === Member::TYPE_USER && $remainingMember->isLocal()) {
125+
continue 2;
126+
}
127+
}
128+
129+
$this->mountRequest->deleteByCircleId($singleId);
130+
}
131+
}
132+
86133
/**
87134
* @param Member $member
88135
* @param string[] $singleIds

‎lib/Model/Mount.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use OCA\Circles\Tools\Db\IQueryRow;
1818
use OCA\Circles\Tools\IDeserializable;
1919
use OCA\Circles\Tools\Traits\TArrayTools;
20+
use OCA\Files_Sharing\External\Manager as ExternalShareManager;
2021
use OCP\Federation\ICloudIdManager;
2122
use OCP\Http\Client\IClientService;
2223

‎lib/MountManager/CircleMountProvider.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use OCA\Circles\Service\ConfigService;
2626
use OCA\Circles\Service\FederatedUserService;
2727
use OCA\Circles\Tools\Traits\TArrayTools;
28+
use OCA\Files_Sharing\External\Manager as ExternalShareManager;
2829
use OCA\Files_Sharing\External\Storage as ExternalStorage;
2930
use OCP\DB\Exception;
3031
use OCP\Federation\ICloudIdManager;
@@ -53,6 +54,7 @@ public function __construct(
5354
private FederatedUserService $federatedUserService,
5455
private ConfigService $configService,
5556
private LoggerInterface $logger,
57+
private ExternalShareManager $externalShareManager,
5658
) {
5759
}
5860

‎lib/ShareByCircleProvider.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ public function getAllShares(): iterable {
888888
public function getUsersForShare(IShare $share): iterable {
889889
$members = $this->shareWrapperService->getShareById((int)$share->getId())->getCircle()->getInheritedMembers();
890890
foreach ($members as $member) {
891-
if ($member->getUserType() === Member::TYPE_USER) {
891+
if ($member->getUserType() === Member::TYPE_USER && $member->isLocal()) {
892892
yield $this->userManager->getExistingUser($member->getUserId());
893893
}
894894
}

0 commit comments

Comments
 (0)