99
1010use Exception ;
1111use InvalidArgumentException ;
12+ use LogicException ;
1213use OC \Files \View ;
1314use OCA \Files_Sharing \Event \ShareMountedEvent ;
15+ use OCA \Talk \Share \RoomShareProvider ;
1416use OCP \Cache \CappedMemoryCache ;
17+ use OCP \DB \QueryBuilder \IQueryBuilder ;
1518use OCP \EventDispatcher \IEventDispatcher ;
1619use OCP \Files \Config \IMountProvider ;
20+ use OCP \Files \Config \IPartialMountProvider ;
21+ use OCP \Files \IRootFolder ;
1722use OCP \Files \Mount \IMountManager ;
1823use OCP \Files \Mount \IMountPoint ;
1924use OCP \Files \Storage \IStorageFactory ;
2025use OCP \ICacheFactory ;
2126use OCP \IConfig ;
27+ use OCP \IDBConnection ;
2228use OCP \IUser ;
2329use OCP \Share \IAttributes ;
2430use OCP \Share \IManager ;
2531use OCP \Share \IShare ;
2632use Psr \Log \LoggerInterface ;
33+ use function array_filter ;
34+ use function array_values ;
2735use function count ;
2836
29- class MountProvider implements IMountProvider {
37+ class MountProvider implements IMountProvider, IPartialMountProvider {
38+
39+ private const SUPPORTED_SHARE_TYPES = [
40+ IShare::TYPE_USER ,
41+ IShare::TYPE_GROUP ,
42+ IShare::TYPE_USERGROUP ,
43+ RoomShareProvider::SHARE_TYPE_USERROOM ,
44+ IShare::TYPE_CIRCLE ,
45+ IShare::TYPE_ROOM ,
46+ IShare::TYPE_DECK ,
47+ IShare::TYPE_SCIENCEMESH ,
48+ ];
49+
50+ /**
51+ * Maps internal share types to the right provider
52+ *
53+ * NOTE: this information should come either from the provider or from
54+ * the provider factory!
55+ */
56+ private const TYPE_MAPPING = [
57+ IShare::TYPE_USERGROUP => IShare::TYPE_GROUP ,
58+ RoomShareProvider::SHARE_TYPE_USERROOM => IShare::TYPE_ROOM ,
59+ ];
60+
3061 /**
3162 * @param IConfig $config
3263 * @param IManager $shareManager
@@ -39,6 +70,8 @@ public function __construct(
3970 protected IEventDispatcher $ eventDispatcher ,
4071 protected ICacheFactory $ cacheFactory ,
4172 protected IMountManager $ mountManager ,
73+ protected IDBConnection $ dbConn ,
74+ protected IRootFolder $ rootFolder ,
4275 ) {
4376 }
4477
@@ -244,6 +277,64 @@ public function adjustTarget(
244277 );
245278 }
246279 }
280+
281+ /**
282+ * @inheritdoc
283+ */
284+ public function getMountsFromMountPoints (
285+ string $ path ,
286+ array $ mountProviderArgs ,
287+ IStorageFactory $ loader ,
288+ ): array {
289+ if (empty ($ mountProviderArgs )) {
290+ return [];
291+ }
292+
293+ $ uniqueMountOwnerIds = [];
294+ $ uniqueRootIds = [];
295+ $ user = null ;
296+ foreach ($ mountProviderArgs as $ mountProviderArg ) {
297+ $ mountInfo = $ mountProviderArg ->mountInfo ;
298+ // get a list of unique owner IDs root mount IDs
299+ $ user ??= $ mountInfo ->getUser ();
300+ $ uniqueMountOwnerIds [$ user ->getUID ()] ??= true ;
301+ $ uniqueRootIds [$ mountInfo ->getRootId ()] ??= true ;
302+ }
303+ $ uniqueMountOwnerIds = array_keys ($ uniqueMountOwnerIds );
304+ $ uniqueRootIds = array_keys ($ uniqueRootIds );
305+
306+ // make sure the MPs belong to the same user
307+ if ($ user === null || count ($ uniqueMountOwnerIds ) !== 1 ) {
308+ // question: what kind of exception to throw in here?
309+ throw new LogicException ();
310+ }
311+
312+ $ rootIdsByShareProviderType = $ this ->getShareInfo ($ user , $ uniqueRootIds );
313+ $ sharesInPath = [];
314+ foreach ($ rootIdsByShareProviderType as $ shareType => $ rootIds ) {
315+ // todo: pagination for many rootIds
316+ $ sharesInPath [] = $ this ->shareManager ->getSharedWithByNodes (
317+ $ uniqueMountOwnerIds [0 ],
318+ $ shareType ,
319+ $ rootIds ,
320+ -1
321+ );
322+ }
323+ $ sharesInPath = array_merge (...$ sharesInPath );
324+
325+ // filter out shares owned or shared by the user and ones for which
326+ // the user has no permissions
327+ $ shares = $ this ->filterShares ($ sharesInPath , $ user ->getUID ());
328+ $ superShares = $ this ->buildSuperShares ($ shares , $ user );
329+
330+ return $ this ->getMountsFromSuperShares (
331+ $ user ->getUID (),
332+ $ superShares ,
333+ $ loader ,
334+ $ user ,
335+ );
336+ }
337+
247338 /**
248339 * @param string $userId
249340 * @param array $superShares
@@ -334,7 +425,7 @@ public function getMountsFromSuperShares(
334425 $ validShareCache ->set ($ userId , $ newMaxValidatedShare , 24 * 60 * 60 );
335426
336427 // array_filter removes the null values from the array
337- return array_values ( array_filter ($ mounts) );
428+ return array_filter ($ mounts );
338429 }
339430
340431 /**
@@ -354,4 +445,59 @@ static function (IShare $share) use ($userId) {
354445 }
355446 );
356447 }
448+
449+ /**
450+ * Helper function to retrieve data needed to determine which
451+ * IShareProviders need to be queried: IShare::TYPE_*.
452+ *
453+ * @see IShare::TYPE_* constants
454+ *
455+ * @param int[] $uniqueRootIds
456+ * @return array<int, int[]> Array of the shared node IDs,
457+ * keyed by the share type.
458+ * @throws \OCP\DB\Exception
459+ */
460+ public function getShareInfo (IUser $ user , array $ uniqueRootIds ): array {
461+ $ mountOwnerId = $ user ->getUID ();
462+ // retrieve the share type for the received files
463+ $ qb = $ this ->dbConn ->getQueryBuilder ();
464+ $ qb ->select ('file_source ' , 'share_type ' )
465+ ->from ('share ' )
466+ ->where (
467+ $ qb ->expr ()->in (
468+ 'file_source ' ,
469+ $ qb ->createNamedParameter (
470+ $ uniqueRootIds ,
471+ IQueryBuilder::PARAM_STR_ARRAY
472+ )
473+ )
474+ )
475+ ->andWhere (
476+ $ qb ->expr ()->in (
477+ 'share_type ' ,
478+ $ qb ->createNamedParameter (
479+ self ::SUPPORTED_SHARE_TYPES ,
480+ IQueryBuilder::PARAM_INT_ARRAY
481+ )
482+ )
483+ )
484+ ->andWhere (
485+ $ qb ->expr ()->eq (
486+ 'share_with ' ,
487+ $ qb ->createNamedParameter ($ mountOwnerId )
488+ )
489+ )
490+ ->groupBy ('file_source ' , 'share_type ' );
491+ $ cursor = $ qb ->executeQuery ();
492+
493+ // group IDs of the roots of the mountpoints by type
494+ $ rootIdsByType = [];
495+ while ($ row = $ cursor ->fetch ()) {
496+ $ mappedType = self ::TYPE_MAPPING [$ row ['share_type ' ]] ?? $ row ['share_type ' ];
497+ $ rootIdsByType [$ mappedType ][] = $ row ['file_source ' ];
498+ }
499+ $ cursor ->closeCursor ();
500+
501+ return $ rootIdsByType ;
502+ }
357503}
0 commit comments