diff --git a/lib/Model/Mount.php b/lib/Model/Mount.php index 9c2d967d1..1f33ad83e 100644 --- a/lib/Model/Mount.php +++ b/lib/Model/Mount.php @@ -17,6 +17,7 @@ use OCA\Files_Sharing\External\Manager as ExternalShareManager; use OCP\Federation\ICloudIdManager; use OCP\Http\Client\IClientService; +use OCP\IUser; /** * Class Mount @@ -41,6 +42,7 @@ class Mount extends ManagedModel implements IDeserializable, IQueryRow, JsonSeri private ICloudIdManager $cloudIdManager; private IClientService $httpClientService; private ExternalShareManager $externalShareManager; + private IUser $recipient; private string $remote = ''; private int $remoteShareId = 0; @@ -304,6 +306,16 @@ public function getExternalShareManager(): ExternalShareManager { return $this->externalShareManager; } + public function setRecipient(IUser $recipient): self { + $this->recipient = $recipient; + + return $this; + } + + public function getRecipient(): IUser { + return $this->recipient; + } + public function setRemote(string $remote): void { $this->remote = $remote; } @@ -334,6 +346,7 @@ public function toMount(): array { 'mountpoint' => $this->getMountPoint(false), 'HttpClientService' => $this->getHttpClientService(), 'manager' => $this->getExternalShareManager(), + 'recipient' => $this->getRecipient(), 'cloudId' => $this->getCloudIdManager()->getCloudId( $member->getUserId(), $member->getRemoteInstance()->getRoot() diff --git a/lib/MountManager/CircleMountProvider.php b/lib/MountManager/CircleMountProvider.php index 854906f21..23fc5f006 100644 --- a/lib/MountManager/CircleMountProvider.php +++ b/lib/MountManager/CircleMountProvider.php @@ -76,7 +76,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader): array { foreach ($items as $item) { try { $this->fixDuplicateFile($user->getUID(), $item); - $mounts[] = $this->generateCircleMount($item, $loader); + $mounts[] = $this->generateCircleMount($item, $loader, $user); } catch (\Exception $e) { $this->logger->warning('issue with teams\' mounts', ['exception' => $e]); } @@ -89,7 +89,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader): array { * @throws InitiatorNotFoundException * @throws MountPointConstructionException */ - public function generateCircleMount(Mount $mount, IStorageFactory $storageFactory): CircleMount { + public function generateCircleMount(Mount $mount, IStorageFactory $storageFactory, IUser $user): CircleMount { $initiator = $mount->getInitiator(); // TODO: right now, limited to Local Nextcloud User @@ -100,7 +100,8 @@ public function generateCircleMount(Mount $mount, IStorageFactory $storageFactor $mount->setCloudIdManager($this->cloudIdManager) ->setHttpClientService($this->clientService) - ->setExternalShareManager($this->externalShareManager); + ->setExternalShareManager($this->externalShareManager) + ->setRecipient($user); return new CircleMount( $mount, @@ -157,7 +158,7 @@ private function fixDuplicateFile(string $userId, Mount $mount): void { #[Override] public function getMountsForPath(string $setupPathHint, bool $forChildren, array $mountProviderArgs, IStorageFactory $loader): array { - /** @var array $userMountRequests */ + /** @var array $userMountRequests */ $userMountRequests = []; /** @var array $mounts */ $mounts = []; @@ -173,6 +174,7 @@ public function getMountsForPath(string $setupPathHint, bool $forChildren, array $userMountRequests[$user->getUID()] ??= [ 'federatedUser' => $this->federatedUserService->getLocalFederatedUser($user->getUID()), + 'user' => $user, 'paths' => [], ]; @@ -193,7 +195,7 @@ public function getMountsForPath(string $setupPathHint, bool $forChildren, array } try { $this->fixDuplicateFile($uid, $item); - $mounts[$mountPoint] = $this->generateCircleMount($item, $loader); + $mounts[$mountPoint] = $this->generateCircleMount($item, $loader, $userMountRequest['user']); } catch (\Exception $e) { $this->logger->error('Failed to create Teams mount', ['exception' => $e]); } diff --git a/tests/unit/lib/MountManager/CircleMountProviderTest.php b/tests/unit/lib/MountManager/CircleMountProviderTest.php new file mode 100644 index 000000000..312bc84aa --- /dev/null +++ b/tests/unit/lib/MountManager/CircleMountProviderTest.php @@ -0,0 +1,171 @@ +rootFolder = $this->createMock(IRootFolder::class); + $this->mountRequest = $this->createMock(MountRequest::class); + $this->federatedUserService = $this->createMock(FederatedUserService::class); + $configService = $this->createMock(ConfigService::class); + $configService->method('isLocalInstance') + ->willReturn(true); + $this->user = $this->createMock(IUser::class); + $this->user->method('getUID') + ->willReturn('alice'); + + $this->provider = new CircleMountProvider( + $this->createMock(IClientService::class), + $this->rootFolder, + Server::get(ICloudIdManager::class), + $this->mountRequest, + $this->createMock(MountPointRequest::class), + $this->federatedUserService, + $configService, + $this->createMock(LoggerInterface::class), + $this->createMock(ExternalShareManager::class), + ); + } + + private function createTeamMount(): Mount { + $localUser = new FederatedUser(); + $localUser->setUserId('alice') + ->setUserType(Member::TYPE_USER) + ->setInstance(''); + $initiator = new Member(); + $initiator->setUserId('alice') + ->setInheritedBy($localUser); + + $remoteInstance = new RemoteInstance(); + $remoteInstance->setRoot('https://remote.example'); + $owner = new Member(); + $owner->setUserId('bob') + ->setRemoteInstance($remoteInstance); + + $mount = new Mount(); + $mount->setMountId('mount-id') + ->setOriginalMountPoint('/team-share') + ->setToken('token') + ->setOwner($owner) + ->setInitiator($initiator); + + return $mount; + } + + private function mockFreeMountPoint(): void { + $cache = $this->createMock(ICache::class); + $cache->method('inCache') + ->willReturn(false); + $storage = $this->createMock(IStorage::class); + $storage->method('getCache') + ->willReturn($cache); + $homeMount = $this->createMock(IMountPoint::class); + $homeMount->method('getStorage') + ->willReturn($storage); + $userFolder = $this->createMock(IUserFolder::class); + $userFolder->method('getMountPoint') + ->willReturn($homeMount); + $this->rootFolder->method('getUserFolder') + ->with('alice') + ->willReturn($userFolder); + + $federatedUser = new FederatedUser(); + $federatedUser->setSingleId('alice-single-id'); + $this->federatedUserService->method('getLocalFederatedUser') + ->with('alice') + ->willReturn($federatedUser); + } + + public function testGenerateCircleMountCreatesExternalStorageForUser(): void { + $discoveryService = $this->createMock(IOCMDiscoveryService::class); + $discoveryService->method('discover') + ->willThrowException(new OCMProviderException()); + $this->overwriteService(IOCMDiscoveryService::class, $discoveryService); + $mount = $this->createTeamMount(); + + $circleMount = $this->provider->generateCircleMount($mount, new StorageFactory(), $this->user); + + $this->assertSame($this->user, $mount->toMount()['recipient']); + $this->assertTrue($circleMount->getStorage()->instanceOfStorage(ExternalStorage::class)); + } + + public function testGetMountsForUserPassesUserAsRecipient(): void { + $this->mockFreeMountPoint(); + $mount = $this->createTeamMount(); + $this->mountRequest->method('getForUser') + ->willReturn([$mount]); + + $mounts = $this->provider->getMountsForUser($this->user, new StorageFactory()); + + $this->assertCount(1, $mounts); + $this->assertSame($this->user, $mount->toMount()['recipient']); + } + + public function testGetMountsForPathPassesUserAsRecipient(): void { + $this->mockFreeMountPoint(); + $mount = $this->createTeamMount(); + $this->mountRequest->method('getForUser') + ->willReturn([$mount]); + $mountInfo = $this->createMock(ICachedMountInfo::class); + $mountInfo->method('getUser') + ->willReturn($this->user); + $mountInfo->method('getMountPoint') + ->willReturn('/alice/files/team-share/'); + + $mounts = $this->provider->getMountsForPath( + '/alice/files/team-share', + false, + [new MountProviderArgs($mountInfo, $this->createMock(ICacheEntry::class))], + new StorageFactory(), + ); + + $this->assertCount(1, $mounts); + $this->assertSame($this->user, $mount->toMount()['recipient']); + } +}