3838use OCP \Files \Node ;
3939use OCP \Files \NotFoundException ;
4040use OCP \IGroupManager ;
41- use OCP \Share \Events \ShareAcceptedEvent ;
41+ use OCP \Share \Events \ShareCreatedEvent ;
4242use OCP \Share \Events \ShareDeletedEvent ;
4343use OCP \Share \IManager ;
4444use Psr \Log \LoggerInterface ;
@@ -53,6 +53,9 @@ final class FileListener implements IEventListener {
5353 private array $ sourceUserIds ;
5454 private ?Node $ source = null ;
5555
56+ /** @var array<string, bool> */
57+ private array $ addedMounts = [];
58+
5659 public function __construct (
5760 private FaceDetectionMapper $ faceDetectionMapper ,
5861 private LoggerInterface $ logger ,
@@ -71,14 +74,14 @@ public function __construct(
7174 }
7275
7376 /**
74- * @param Node $node
77+ * @param int $nodeId
7578 * @return list<string>
7679 * @throws InvalidPathException
7780 * @throws NotFoundException
7881 */
79- private function getUsersWithFileAccess (Node $ node ): array {
82+ private function getUsersWithFileAccess (int $ nodeId ): array {
8083 $ this ->userMountCache ->clear ();
81- $ mountInfos = $ this ->userMountCache ->getMountsForFileId ($ node -> getId () );
84+ $ mountInfos = $ this ->userMountCache ->getMountsForFileId ($ nodeId );
8285 $ userIds = array_map (static function (ICachedMountInfo $ mountInfo ) {
8386 return $ mountInfo ->getUser ()->getUID ();
8487 }, $ mountInfos );
@@ -88,11 +91,31 @@ private function getUsersWithFileAccess(Node $node): array {
8891
8992 public function handle (Event $ event ): void {
9093 try {
91- if ($ event instanceof ShareAcceptedEvent) {
94+ if ($ event instanceof \OCP \Files \Config \Event \UserMountAddedEvent) {
95+ $ rootId = $ event ->mountPoint ->getRootId ();
96+ // Asynchronous, because we potentially recurse and this event needs to be handled fast
97+ $ this ->onAccessUpdate ($ event ->mountPoint ->getStorageId (), $ rootId );
98+ // Remember that this mount was added in the current process (see UserMountRemovedEvent below)
99+ $ this ->addedMounts [$ event ->mountPoint ->getUser ()->getUID () . '- ' . $ rootId ] = true ;
100+ }
101+
102+ if ($ event instanceof \OCP \Files \Config \Event \UserMountRemovedEvent) {
103+ // If we just added this mount, ignore the removal, as the 'removal' event is always fired after
104+ // the 'added' event in server
105+ $ rootId = $ event ->mountPoint ->getRootId ();
106+ $ mountKey = $ event ->mountPoint ->getUser ()->getUID () . '- ' . $ rootId ;
107+ if (array_key_exists ($ mountKey , $ this ->addedMounts ) && $ this ->addedMounts [$ mountKey ] === true ) {
108+ return ;
109+ }
110+ // Asynchronous, because we potentially recurse and this event needs to be handled fast
111+ $ this ->onAccessUpdate ($ event ->mountPoint ->getStorageId (), $ rootId );
112+ }
113+
114+ if ($ event instanceof ShareCreatedEvent) {
92115 $ share = $ event ->getShare ();
93116 $ ownerId = $ share ->getShareOwner ();
94117 $ node = $ share ->getNode ();
95- $ userIds = $ this ->getUsersWithFileAccess ($ node );
118+ $ userIds = $ this ->getUsersWithFileAccess ($ node-> getId () );
96119
97120 if ($ node ->getType () === FileInfo::TYPE_FOLDER ) {
98121 $ mount = $ node ->getMountPoint ();
@@ -126,7 +149,7 @@ public function handle(Event $event): void {
126149 if ($ event instanceof ShareDeletedEvent) {
127150 $ share = $ event ->getShare ();
128151 $ node = $ share ->getNode ();
129- $ userIds = $ this ->getUsersWithFileAccess ($ node );
152+ $ userIds = $ this ->getUsersWithFileAccess ($ node-> getId () );
130153
131154 if ($ node ->getType () === FileInfo::TYPE_FOLDER ) {
132155 $ mount = $ node ->getMountPoint ();
@@ -159,7 +182,7 @@ public function handle(Event $event): void {
159182 } else {
160183 $ this ->movingDirFromIgnoredTerritory = $ this ->getDirIgnores ($ event ->getSource ());
161184 }
162- $ this ->sourceUserIds = $ this ->getUsersWithFileAccess ($ event ->getSource ());
185+ $ this ->sourceUserIds = $ this ->getUsersWithFileAccess ($ event ->getSource ()-> getId () );
163186 $ this ->source = $ event ->getSource ();
164187 return ;
165188 }
@@ -390,7 +413,7 @@ public function postInsert(Node $node, bool $recurse = true, ?array $mimeTypes =
390413 * @throws Exception
391414 */
392415 public function postRename (Node $ source , Node $ target ): void {
393- $ targetUserIds = $ this ->getUsersWithFileAccess ($ target );
416+ $ targetUserIds = $ this ->getUsersWithFileAccess ($ target-> getId () );
394417
395418 $ usersToAdd = array_values (array_diff ($ targetUserIds , $ this ->sourceUserIds ));
396419 $ existingUsers = array_diff ($ targetUserIds , $ usersToAdd );
@@ -412,11 +435,11 @@ public function postRename(Node $source, Node $target): void {
412435 private function copyFaceDetectionsForNode (string $ ownerId , array $ usersToAdd , array $ targetUserIds , Node $ node ): void {
413436 if ($ node instanceof Folder) {
414437 try {
415- foreach ($ node ->getDirectoryListing () as $ node ) {
416- if (!in_array ($ node ->getMimetype (), Constants::IMAGE_FORMATS )) {
438+ foreach ($ node ->getDirectoryListing () as $ n ) {
439+ if (!in_array ($ n ->getMimetype (), Constants::IMAGE_FORMATS )) {
417440 continue ;
418441 }
419- $ this ->copyFaceDetectionsForNode ($ ownerId , $ usersToAdd , $ targetUserIds , $ node );
442+ $ this ->copyFaceDetectionsForNode ($ ownerId , $ usersToAdd , $ targetUserIds , $ n );
420443 }
421444 } catch (NotFoundException |Exception |InvalidPathException $ e ) {
422445 $ this ->logger ->warning ('Error in recognize file listener ' , ['exception ' => $ e ]);
@@ -512,4 +535,30 @@ private function resetIgnoreCache(Node $node) : void {
512535 }
513536 $ this ->ignoreService ->clearCacheForStorage ($ storageId );
514537 }
538+
539+ /**
540+ * @throws NotFoundException
541+ * @throws InvalidPathException
542+ * @throws Exception
543+ */
544+ private function onAccessUpdate (int $ storageId , int $ rootId ): void {
545+ $ userIds = $ this ->getUsersWithFileAccess ($ rootId );
546+ $ files = $ this ->storageService ->getFilesInMount ($ storageId , $ rootId , [ClusteringFaceClassifier::MODEL_NAME ], 0 , 0 );
547+ foreach ($ files as $ fileInfo ) {
548+ $ node = current ($ this ->rootFolder ->getById ($ fileInfo ['fileid ' ])) ?: null ;
549+ $ ownerId = $ node ?->getOwner()?->getUID();
550+ if ($ ownerId === null ) {
551+ return ;
552+ }
553+ foreach ($ userIds as $ userId ) {
554+ if ($ userId === $ ownerId ) {
555+ continue ;
556+ }
557+ if (count ($ this ->faceDetectionMapper ->findByFileIdAndUser ($ fileInfo ['fileid ' ], $ userId )) > 0 ) {
558+ continue ;
559+ }
560+ $ this ->faceDetectionMapper ->copyDetectionsForFileFromUserToUser ($ fileInfo ['fileid ' ], $ ownerId , $ userId );
561+ }
562+ }
563+ }
515564}
0 commit comments