Skip to content

Commit

Permalink
fix(FileListener): Listen to file movements across share boundaries
Browse files Browse the repository at this point in the history
Signed-off-by: Marcel Klehr <[email protected]>
  • Loading branch information
marcelklehr committed Apr 17, 2024
1 parent 2907a2b commit 73a1c3c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
6 changes: 6 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use OCP\Files\Events\Node\NodeDeletedEvent;
use OCP\Files\Events\Node\NodeRenamedEvent;
use OCP\Files\Events\NodeRemovedFromCache;
use OCP\Files\IRootFolder;
use OCP\Share\Events\ShareCreatedEvent;
use OCP\Share\Events\ShareDeletedEvent;

Expand All @@ -42,6 +43,11 @@ public function __construct() {
$dispatcher->addServiceListener(ShareDeletedEvent::class, FileListener::class);
$dispatcher->addServiceListener(CacheEntryInsertedEvent::class, FileListener::class);
$dispatcher->addServiceListener(NodeRemovedFromCache::class, FileListener::class);
$rootFolder = $this->getContainer()->get(IRootFolder::class);
$rootFolder->listen('\OC\Files', 'postRename', function($source, $target) {
$fileListener = $this->getContainer()->get(FileListener::class);
$fileListener->postRename($source, $target);
});
}

public function register(IRegistrationContext $context): void {
Expand Down
85 changes: 84 additions & 1 deletion lib/Hooks/FileListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
use OCP\Share\IManager;
use Psr\Log\LoggerInterface;

/**
* @template-implements IEventListener<Event>
*/
class FileListener implements IEventListener {
private FaceDetectionMapper $faceDetectionMapper;
private LoggerInterface $logger;
Expand Down Expand Up @@ -70,7 +73,7 @@ public function handle(Event $event): void {
$node = $share->getNode();

$accessList = $this->shareManager->getAccessList($node, true, true);
$userIds = array_map(fn ($id) => (string)$id, array_keys($accessList['users']));
$userIds = array_map(fn ($id) => strval($id), array_keys($accessList['users']));

if ($node->getType() === FileInfo::TYPE_FOLDER) {
$mount = $node->getMountPoint();
Expand Down Expand Up @@ -312,6 +315,86 @@ public function postInsert(Node $node, bool $recurse = true): void {
}
}

function preRename(Node $source, Node $target): void {
$sourceAccessList = $this->shareManager->getAccessList($source, true, true);
$sourceUserIds = array_map(fn ($id) => strval($id), array_keys($sourceAccessList['users']));
$targetAccessList = $this->shareManager->getAccessList($target, true, true);
$targetUserIds = array_map(fn ($id) => strval($id), array_keys($targetAccessList['users']));

$usersToRemove = array_diff($sourceUserIds, $targetUserIds);

if ($target->getType() === FileInfo::TYPE_FOLDER) {
$mount = $target->getMountPoint();
if ($mount->getNumericStorageId() === null) {
return;
}
$files = $this->storageService->getFilesInMount($mount->getNumericStorageId(), $source->getId(), [ClusteringFaceClassifier::MODEL_NAME], 0, 0);
foreach ($files as $fileInfo) {
$this->faceDetectionMapper->removeDetectionsForFileFromUsersNotInList($fileInfo['fileid'], $usersToRemove);
}
} else {
$this->faceDetectionMapper->removeDetectionsForFileFromUsersNotInList($source->getId(), $usersToRemove);
}
}

function postRename(Node $source, Node $target): void {
if (in_array($source->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true) &&
!in_array($target->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true)) {
$this->resetIgnoreCache($source);
$this->postInsert($target->getParent());
return;
}

if (!in_array($source->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true) &&
in_array($target->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true)) {
$this->resetIgnoreCache($target);
$this->postDelete($target->getParent());
return;
}

if ($this->isIgnored($target)) {
$this->postDelete($target);
return;
}
if ($this->isIgnored($source) && !$this->isIgnored($target)) {
$this->postInsert($target);
return;
}

$sourceAccessList = $this->shareManager->getAccessList($source, true, true);
$sourceUserIds = array_map(fn ($id) => strval($id), array_keys($sourceAccessList['users']));
$targetAccessList = $this->shareManager->getAccessList($target, true, true);
$targetUserIds = array_map(fn ($id) => strval($id), array_keys($targetAccessList['users']));

$usersToAdd = array_diff($targetUserIds, $sourceUserIds);
$existingUsers = array_diff($targetUserIds, $usersToAdd);
// *handwaving* I know this is a stretch but it's good enough
$ownerId = $existingUsers[0];

if ($target->getType() === FileInfo::TYPE_FOLDER) {
$mount = $target->getMountPoint();
if ($mount->getNumericStorageId() === null) {
return;
}
$files = $this->storageService->getFilesInMount($mount->getNumericStorageId(), $target->getId(), [ClusteringFaceClassifier::MODEL_NAME], 0, 0);
foreach ($files as $fileInfo) {
foreach ($usersToAdd as $userId) {
if (count($this->faceDetectionMapper->findByFileIdAndUser($target->getId(), $userId)) > 0) {
continue;
}
$this->faceDetectionMapper->copyDetectionsForFileFromUserToUser($fileInfo['fileid'], $ownerId, $userId);
}
}
} else {
foreach ($usersToAdd as $userId) {
if (count($this->faceDetectionMapper->findByFileIdAndUser($target->getId(), $userId)) > 0) {
continue;
}
$this->faceDetectionMapper->copyDetectionsForFileFromUserToUser($target->getId(), $ownerId, $userId);
}
}
}

/**
* @param \OCP\Files\Node $node
* @return bool
Expand Down

0 comments on commit 73a1c3c

Please sign in to comment.