38
38
use OCP \Files \Node ;
39
39
use OCP \Files \NotFoundException ;
40
40
use OCP \IGroupManager ;
41
- use OCP \Share \Events \ShareAcceptedEvent ;
41
+ use OCP \Share \Events \ShareCreatedEvent ;
42
42
use OCP \Share \Events \ShareDeletedEvent ;
43
43
use OCP \Share \IManager ;
44
44
use Psr \Log \LoggerInterface ;
@@ -53,6 +53,9 @@ final class FileListener implements IEventListener {
53
53
private array $ sourceUserIds ;
54
54
private ?Node $ source = null ;
55
55
56
+ /** @var array<string, bool> */
57
+ private array $ addedMounts = [];
58
+
56
59
public function __construct (
57
60
private FaceDetectionMapper $ faceDetectionMapper ,
58
61
private LoggerInterface $ logger ,
@@ -71,14 +74,14 @@ public function __construct(
71
74
}
72
75
73
76
/**
74
- * @param Node $node
77
+ * @param int $nodeId
75
78
* @return list<string>
76
79
* @throws InvalidPathException
77
80
* @throws NotFoundException
78
81
*/
79
- private function getUsersWithFileAccess (Node $ node ): array {
82
+ private function getUsersWithFileAccess (int $ nodeId ): array {
80
83
$ this ->userMountCache ->clear ();
81
- $ mountInfos = $ this ->userMountCache ->getMountsForFileId ($ node -> getId () );
84
+ $ mountInfos = $ this ->userMountCache ->getMountsForFileId ($ nodeId );
82
85
$ userIds = array_map (static function (ICachedMountInfo $ mountInfo ) {
83
86
return $ mountInfo ->getUser ()->getUID ();
84
87
}, $ mountInfos );
@@ -88,11 +91,31 @@ private function getUsersWithFileAccess(Node $node): array {
88
91
89
92
public function handle (Event $ event ): void {
90
93
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) {
92
115
$ share = $ event ->getShare ();
93
116
$ ownerId = $ share ->getShareOwner ();
94
117
$ node = $ share ->getNode ();
95
- $ userIds = $ this ->getUsersWithFileAccess ($ node );
118
+ $ userIds = $ this ->getUsersWithFileAccess ($ node-> getId () );
96
119
97
120
if ($ node ->getType () === FileInfo::TYPE_FOLDER ) {
98
121
$ mount = $ node ->getMountPoint ();
@@ -126,7 +149,7 @@ public function handle(Event $event): void {
126
149
if ($ event instanceof ShareDeletedEvent) {
127
150
$ share = $ event ->getShare ();
128
151
$ node = $ share ->getNode ();
129
- $ userIds = $ this ->getUsersWithFileAccess ($ node );
152
+ $ userIds = $ this ->getUsersWithFileAccess ($ node-> getId () );
130
153
131
154
if ($ node ->getType () === FileInfo::TYPE_FOLDER ) {
132
155
$ mount = $ node ->getMountPoint ();
@@ -159,7 +182,7 @@ public function handle(Event $event): void {
159
182
} else {
160
183
$ this ->movingDirFromIgnoredTerritory = $ this ->getDirIgnores ($ event ->getSource ());
161
184
}
162
- $ this ->sourceUserIds = $ this ->getUsersWithFileAccess ($ event ->getSource ());
185
+ $ this ->sourceUserIds = $ this ->getUsersWithFileAccess ($ event ->getSource ()-> getId () );
163
186
$ this ->source = $ event ->getSource ();
164
187
return ;
165
188
}
@@ -390,7 +413,7 @@ public function postInsert(Node $node, bool $recurse = true, ?array $mimeTypes =
390
413
* @throws Exception
391
414
*/
392
415
public function postRename (Node $ source , Node $ target ): void {
393
- $ targetUserIds = $ this ->getUsersWithFileAccess ($ target );
416
+ $ targetUserIds = $ this ->getUsersWithFileAccess ($ target-> getId () );
394
417
395
418
$ usersToAdd = array_values (array_diff ($ targetUserIds , $ this ->sourceUserIds ));
396
419
$ existingUsers = array_diff ($ targetUserIds , $ usersToAdd );
@@ -412,11 +435,11 @@ public function postRename(Node $source, Node $target): void {
412
435
private function copyFaceDetectionsForNode (string $ ownerId , array $ usersToAdd , array $ targetUserIds , Node $ node ): void {
413
436
if ($ node instanceof Folder) {
414
437
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 )) {
417
440
continue ;
418
441
}
419
- $ this ->copyFaceDetectionsForNode ($ ownerId , $ usersToAdd , $ targetUserIds , $ node );
442
+ $ this ->copyFaceDetectionsForNode ($ ownerId , $ usersToAdd , $ targetUserIds , $ n );
420
443
}
421
444
} catch (NotFoundException |Exception |InvalidPathException $ e ) {
422
445
$ this ->logger ->warning ('Error in recognize file listener ' , ['exception ' => $ e ]);
@@ -512,4 +535,41 @@ private function resetIgnoreCache(Node $node) : void {
512
535
}
513
536
$ this ->ignoreService ->clearCacheForStorage ($ storageId );
514
537
}
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
+ $ userIdsToScheduleClustering = [];
548
+ foreach ($ files as $ fileInfo ) {
549
+ $ node = current ($ this ->rootFolder ->getById ($ fileInfo ['fileid ' ])) ?: null ;
550
+ $ ownerId = $ node ?->getOwner()?->getUID();
551
+ if ($ ownerId === null ) {
552
+ continue ;
553
+ }
554
+ $ detectionsForFile = $ this ->faceDetectionMapper ->findByFileId ($ fileInfo ['fileid ' ]);
555
+ $ userHasDetectionForFile = [];
556
+ foreach ($ detectionsForFile as $ detection ) {
557
+ $ userHasDetectionForFile [$ detection ->getUserId ()] = true ;
558
+ }
559
+ foreach ($ userIds as $ userId ) {
560
+ if ($ userId === $ ownerId ) {
561
+ continue ;
562
+ }
563
+ if ($ userHasDetectionForFile [$ userId ] ?? false ) {
564
+ continue ;
565
+ }
566
+ $ this ->faceDetectionMapper ->copyDetectionsForFileFromUserToUser ($ fileInfo ['fileid ' ], $ ownerId , $ userId );
567
+ $ userIdsToScheduleClustering [$ userId ] = true ;
568
+ }
569
+ $ this ->faceDetectionMapper ->removeDetectionsForFileFromUsersNotInList ($ fileInfo ['fileid ' ], $ userIds );
570
+ }
571
+ foreach (array_keys ($ userIdsToScheduleClustering ) as $ userId ) {
572
+ $ this ->jobList ->add (ClusterFacesJob::class, ['userId ' => $ userId ]);
573
+ }
574
+ }
515
575
}
0 commit comments