diff --git a/lib/Db/CoreQueryBuilder.php b/lib/Db/CoreQueryBuilder.php index 22be02462..ca19c57e5 100644 --- a/lib/Db/CoreQueryBuilder.php +++ b/lib/Db/CoreQueryBuilder.php @@ -1574,6 +1574,31 @@ public function leftJoinMountpoint(string $aliasMount, IFederatedUser $federated } + /** + * @param string $aliasMount + * @param string[] $paths + * @param bool $forChildren + */ + public function limitToMountpoints(string $aliasMount, array $paths, bool $forChildren = false): void { + if (count($paths) === 0) { + return; + } + + $expr = $this->expr(); + $orX = $expr->orX(); + + if ($forChildren) { + foreach ($paths as $path) { + $orX->add($expr->like($aliasMount . '.mountpoint', $this->createNamedParameter($path . '/%'))); + } + } else { + $orX->add($expr->in($aliasMount . '.mountpoint', $this->createNamedParameter($paths, IQueryBuilder::PARAM_STR_ARRAY))); + } + + $this->andWhere($orX); + } + + /** * @param string $alias * @param array $default diff --git a/lib/Db/MountRequest.php b/lib/Db/MountRequest.php index ec3765ab9..b55b95412 100644 --- a/lib/Db/MountRequest.php +++ b/lib/Db/MountRequest.php @@ -58,16 +58,21 @@ public function delete(string $token): void { /** * @param IFederatedUser $federatedUser + * @param string[] $paths + * @param bool $forChildren * * @return Mount[] * @throws RequestBuilderException */ - public function getForUser(IFederatedUser $federatedUser): array { + public function getForUser(IFederatedUser $federatedUser, array $paths = [], bool $forChildren = false): array { $qb = $this->getMountSelectSql(); $qb->setOptions([CoreQueryBuilder::MOUNT], ['getData' => true]); $qb->leftJoinMember(CoreQueryBuilder::MOUNT); $qb->leftJoinMountpoint(CoreQueryBuilder::MOUNT, $federatedUser); $qb->limitToInitiator(CoreQueryBuilder::MOUNT, $federatedUser, 'circle_id'); + if (count($paths) !== 0) { + $qb->limitToMountpoints(CoreQueryBuilder::MOUNT, $paths, $forChildren); + } return $this->getItemsFromRequest($qb); diff --git a/lib/MountManager/CircleMountProvider.php b/lib/MountManager/CircleMountProvider.php index 58c9ab27e..0edd9b0b6 100644 --- a/lib/MountManager/CircleMountProvider.php +++ b/lib/MountManager/CircleMountProvider.php @@ -29,6 +29,8 @@ use OCP\DB\Exception; use OCP\Federation\ICloudIdManager; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IPartialMountProvider; +use OCP\Files\Config\MountProviderArgs; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; @@ -36,9 +38,10 @@ use OCP\Files\Storage\IStorageFactory; use OCP\Http\Client\IClientService; use OCP\IUser; +use Override; use Psr\Log\LoggerInterface; -class CircleMountProvider implements IMountProvider { +class CircleMountProvider implements IMountProvider, IPartialMountProvider { use TArrayTools; public const EXTERNAL_STORAGE = ExternalStorage::class; @@ -247,4 +250,55 @@ private function generateIncrementedMountpoint(Folder $fs, Mount $mount, IFedera $n++; } } + + #[Override] + public function getMountsForPath(string $setupPathHint, bool $forChildren, array $mountProviderArgs, IStorageFactory $loader): array { + /** @var array $userMountRequests */ + $userMountRequests = []; + /** @var array $mounts */ + $mounts = []; + + /** @var MountProviderArgs $mountProviderArg */ + foreach ($mountProviderArgs as $mountProviderArg) { + $user = $mountProviderArg->mountInfo->getUser(); + + $parts = explode('/', $mountProviderArg->mountInfo->getMountPoint()); + if ($parts[1] !== $user->getUID() || $parts[2] !== 'files') { + continue; + } + + if (!isset($userMountRequests[$user->getUID()])) { + $federatedUser = $this->federatedUserService->getLocalFederatedUser($user->getUID()); + $userMountRequests[$user->getUID()] = [ + 'federatedUser' => $federatedUser, + 'paths' => [], + ]; + } + + $userMountRequests[$user->getUID()]['paths'][] = '/' . implode('/', array_slice($parts, 3)); + } + + foreach ($userMountRequests as $uid => $userMountRequest) { + $userItems = $this->mountRequest->getForUser( + $userMountRequest['federatedUser'], + $userMountRequest['paths'], + $forChildren + ); + + foreach ($userItems as $item) { + $mountPoint = '/' . $uid . '/files' . $item->getMountPoint(); + if (isset($mounts[$mountPoint])) { + continue; + } + try { + $this->fixDuplicateFile($uid, $item); + $mounts[$mountPoint] = $this->generateCircleMount($item, $loader); + } catch (\Exception $e) { + $this->logger->warning('issue with teams\' partial mounts', ['exception' => $e]); + } + } + } + + return $mounts; + } }