diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php index 0ba6ba1b8167f..138746aad8f83 100644 --- a/apps/files_sharing/composer/composer/autoload_classmap.php +++ b/apps/files_sharing/composer/composer/autoload_classmap.php @@ -72,6 +72,7 @@ 'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => $baseDir . '/../lib/Listener/ShareInteractionListener.php', 'OCA\\Files_Sharing\\Listener\\SharesUpdatedListener' => $baseDir . '/../lib/Listener/SharesUpdatedListener.php', 'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => $baseDir . '/../lib/Listener/UserAddedToGroupListener.php', + 'OCA\\Files_Sharing\\Listener\\UserHomeSetupListener' => $baseDir . '/../lib/Listener/UserHomeSetupListener.php', 'OCA\\Files_Sharing\\Listener\\UserShareAcceptanceListener' => $baseDir . '/../lib/Listener/UserShareAcceptanceListener.php', 'OCA\\Files_Sharing\\Middleware\\OCSShareAPIMiddleware' => $baseDir . '/../lib/Middleware/OCSShareAPIMiddleware.php', 'OCA\\Files_Sharing\\Middleware\\ShareInfoMiddleware' => $baseDir . '/../lib/Middleware/ShareInfoMiddleware.php', @@ -98,6 +99,7 @@ 'OCA\\Files_Sharing\\Settings\\Personal' => $baseDir . '/../lib/Settings/Personal.php', 'OCA\\Files_Sharing\\ShareBackend\\File' => $baseDir . '/../lib/ShareBackend/File.php', 'OCA\\Files_Sharing\\ShareBackend\\Folder' => $baseDir . '/../lib/ShareBackend/Folder.php', + 'OCA\\Files_Sharing\\ShareRecipientUpdater' => $baseDir . '/../lib/ShareRecipientUpdater.php', 'OCA\\Files_Sharing\\ShareTargetValidator' => $baseDir . '/../lib/ShareTargetValidator.php', 'OCA\\Files_Sharing\\SharedMount' => $baseDir . '/../lib/SharedMount.php', 'OCA\\Files_Sharing\\SharedStorage' => $baseDir . '/../lib/SharedStorage.php', diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php index 03906cda0473b..3decf0b9c1acc 100644 --- a/apps/files_sharing/composer/composer/autoload_static.php +++ b/apps/files_sharing/composer/composer/autoload_static.php @@ -87,6 +87,7 @@ class ComposerStaticInitFiles_Sharing 'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/ShareInteractionListener.php', 'OCA\\Files_Sharing\\Listener\\SharesUpdatedListener' => __DIR__ . '/..' . '/../lib/Listener/SharesUpdatedListener.php', 'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => __DIR__ . '/..' . '/../lib/Listener/UserAddedToGroupListener.php', + 'OCA\\Files_Sharing\\Listener\\UserHomeSetupListener' => __DIR__ . '/..' . '/../lib/Listener/UserHomeSetupListener.php', 'OCA\\Files_Sharing\\Listener\\UserShareAcceptanceListener' => __DIR__ . '/..' . '/../lib/Listener/UserShareAcceptanceListener.php', 'OCA\\Files_Sharing\\Middleware\\OCSShareAPIMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/OCSShareAPIMiddleware.php', 'OCA\\Files_Sharing\\Middleware\\ShareInfoMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/ShareInfoMiddleware.php', @@ -113,6 +114,7 @@ class ComposerStaticInitFiles_Sharing 'OCA\\Files_Sharing\\Settings\\Personal' => __DIR__ . '/..' . '/../lib/Settings/Personal.php', 'OCA\\Files_Sharing\\ShareBackend\\File' => __DIR__ . '/..' . '/../lib/ShareBackend/File.php', 'OCA\\Files_Sharing\\ShareBackend\\Folder' => __DIR__ . '/..' . '/../lib/ShareBackend/Folder.php', + 'OCA\\Files_Sharing\\ShareRecipientUpdater' => __DIR__ . '/..' . '/../lib/ShareRecipientUpdater.php', 'OCA\\Files_Sharing\\ShareTargetValidator' => __DIR__ . '/..' . '/../lib/ShareTargetValidator.php', 'OCA\\Files_Sharing\\SharedMount' => __DIR__ . '/..' . '/../lib/SharedMount.php', 'OCA\\Files_Sharing\\SharedStorage' => __DIR__ . '/..' . '/../lib/SharedStorage.php', diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index da4984d378533..3af5f5265035b 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -27,6 +27,7 @@ use OCA\Files_Sharing\Listener\ShareInteractionListener; use OCA\Files_Sharing\Listener\SharesUpdatedListener; use OCA\Files_Sharing\Listener\UserAddedToGroupListener; +use OCA\Files_Sharing\Listener\UserHomeSetupListener; use OCA\Files_Sharing\Listener\UserShareAcceptanceListener; use OCA\Files_Sharing\Middleware\OCSShareAPIMiddleware; use OCA\Files_Sharing\Middleware\ShareInfoMiddleware; @@ -48,6 +49,7 @@ use OCP\Files\Events\BeforeDirectFileDownloadEvent; use OCP\Files\Events\BeforeZipCreatedEvent; use OCP\Files\Events\Node\BeforeNodeReadEvent; +use OCP\Files\Events\UserHomeSetupEvent; use OCP\Group\Events\GroupChangedEvent; use OCP\Group\Events\GroupDeletedEvent; use OCP\Group\Events\UserAddedEvent; @@ -121,6 +123,7 @@ function () use ($c) { $context->registerEventListener(UserAddedEvent::class, SharesUpdatedListener::class); $context->registerEventListener(UserRemovedEvent::class, SharesUpdatedListener::class); $context->registerEventListener(UserShareAccessUpdatedEvent::class, SharesUpdatedListener::class); + $context->registerEventListener(UserHomeSetupEvent::class, UserHomeSetupListener::class); $context->registerConfigLexicon(ConfigLexicon::class); } diff --git a/apps/files_sharing/lib/Config/ConfigLexicon.php b/apps/files_sharing/lib/Config/ConfigLexicon.php index c063153765e26..5dde41ad4020f 100644 --- a/apps/files_sharing/lib/Config/ConfigLexicon.php +++ b/apps/files_sharing/lib/Config/ConfigLexicon.php @@ -24,6 +24,9 @@ class ConfigLexicon implements ILexicon { public const SHOW_FEDERATED_AS_INTERNAL = 'show_federated_shares_as_internal'; public const SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL = 'show_federated_shares_to_trusted_servers_as_internal'; public const EXCLUDE_RESHARE_FROM_EDIT = 'shareapi_exclude_reshare_from_edit'; + public const UPDATE_SINGLE_CUTOFF = 'update_single_cutoff'; + public const UPDATE_ALL_CUTOFF = 'update_all_cutoff'; + public const USER_NEEDS_SHARE_REFRESH = 'user_needs_share_refresh'; public function getStrictness(): Strictness { return Strictness::IGNORE; @@ -34,10 +37,15 @@ public function getAppConfigs(): array { new Entry(self::SHOW_FEDERATED_AS_INTERNAL, ValueType::BOOL, false, 'shows federated shares as internal shares', true), new Entry(self::SHOW_FEDERATED_TO_TRUSTED_AS_INTERNAL, ValueType::BOOL, false, 'shows federated shares to trusted servers as internal shares', true), new Entry(self::EXCLUDE_RESHARE_FROM_EDIT, ValueType::BOOL, false, 'Exclude reshare permission from "Allow editing" bundled permissions'), + + new Entry(self::UPDATE_SINGLE_CUTOFF, ValueType::INT, 10, 'For how many users do we update the share date immediately for single-share updates'), + new Entry(self::UPDATE_ALL_CUTOFF, ValueType::INT, 3, 'For how many users do we update the share date immediately for all-share updates'), ]; } public function getUserConfigs(): array { - return []; + return [ + new Entry(self::USER_NEEDS_SHARE_REFRESH, ValueType::BOOL, false, 'whether a user needs to have the receiving share data refreshed for possible changes'), + ]; } } diff --git a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php index ccef71bad5c87..39f9e4e928940 100644 --- a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php +++ b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php @@ -8,16 +8,16 @@ namespace OCA\Files_Sharing\Listener; +use OCA\Files_Sharing\AppInfo\Application; +use OCA\Files_Sharing\Config\ConfigLexicon; use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent; -use OCA\Files_Sharing\MountProvider; -use OCA\Files_Sharing\ShareTargetValidator; +use OCA\Files_Sharing\ShareRecipientUpdater; +use OCP\Config\IUserConfig; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\Files\Config\ICachedMountInfo; -use OCP\Files\Config\IUserMountCache; -use OCP\Files\Storage\IStorageFactory; use OCP\Group\Events\UserAddedEvent; use OCP\Group\Events\UserRemovedEvent; +use OCP\IAppConfig; use OCP\IUser; use OCP\Share\Events\BeforeShareDeletedEvent; use OCP\Share\Events\ShareCreatedEvent; @@ -30,71 +30,79 @@ * @template-implements IEventListener */ class SharesUpdatedListener implements IEventListener { - private array $inUpdate = []; + /** + * for how many users do we update the share date immediately, + * before just marking the other users when we know the relevant share + */ + private int $cutOffMarkAllSingleShare; + /** + * for how many users do we update the share date immediately, + * before just marking the other users when the relevant shares are unknown + */ + private int $cutOffMarkAllShares ; + + private int $updatedCount = 0; public function __construct( private readonly IManager $shareManager, - private readonly IUserMountCache $userMountCache, - private readonly MountProvider $shareMountProvider, - private readonly ShareTargetValidator $shareTargetValidator, - private readonly IStorageFactory $storageFactory, + private readonly ShareRecipientUpdater $shareUpdater, + private readonly IUserConfig $userConfig, + IAppConfig $appConfig, ) { + $this->cutOffMarkAllSingleShare = $appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UPDATE_SINGLE_CUTOFF, 10); + $this->cutOffMarkAllShares = $appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UPDATE_ALL_CUTOFF, 3); } + public function handle(Event $event): void { if ($event instanceof UserShareAccessUpdatedEvent) { foreach ($event->getUsers() as $user) { - $this->updateForUser($user, true); + $this->updateOrMarkUser($user, true); } } if ($event instanceof UserAddedEvent || $event instanceof UserRemovedEvent) { - $this->updateForUser($event->getUser(), true); + $this->updateOrMarkUser($event->getUser(), true); } - if ( - $event instanceof ShareCreatedEvent - || $event instanceof ShareTransferredEvent - ) { - foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) { - $this->updateForUser($user, true); + if ($event instanceof ShareCreatedEvent || $event instanceof ShareTransferredEvent) { + $share = $event->getShare(); + $shareTarget = $share->getTarget(); + foreach ($this->shareManager->getUsersForShare($share) as $user) { + if ($share->getSharedBy() !== $user->getUID()) { + $this->updatedCount++; + if ($this->cutOffMarkAllSingleShare === -1 || $this->updatedCount <= $this->cutOffMarkAllSingleShare) { + $this->shareUpdater->updateForShare($user, $share); + // Share target validation might have changed the target, restore it for the next user + $share->setTarget($shareTarget); + } else { + $this->markUserForRefresh($user); + } + } } } if ($event instanceof BeforeShareDeletedEvent) { foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) { - $this->updateForUser($user, false, [$event->getShare()]); + $this->updateOrMarkUser($user, false, [$event->getShare()]); } } } - private function updateForUser(IUser $user, bool $verifyMountPoints, array $ignoreShares = []): void { - // prevent recursion - if (isset($this->inUpdate[$user->getUID()])) { - return; + private function updateOrMarkUser(IUser $user, bool $verifyMountPoints, array $ignoreShares = []): void { + $this->updatedCount++; + if ($this->cutOffMarkAllShares === -1 || $this->updatedCount <= $this->cutOffMarkAllShares) { + $this->shareUpdater->updateForUser($user, $verifyMountPoints, $ignoreShares); + } else { + $this->markUserForRefresh($user); } - $this->inUpdate[$user->getUID()] = true; - $cachedMounts = $this->userMountCache->getMountsForUser($user); - $shareMounts = array_filter($cachedMounts, fn (ICachedMountInfo $mount) => $mount->getMountProvider() === MountProvider::class); - $mountPoints = array_map(fn (ICachedMountInfo $mount) => $mount->getMountPoint(), $cachedMounts); - $mountsByPath = array_combine($mountPoints, $cachedMounts); - - $shares = $this->shareMountProvider->getSuperSharesForUser($user, $ignoreShares); + } - $mountsChanged = count($shares) !== count($shareMounts); - foreach ($shares as &$share) { - [$parentShare, $groupedShares] = $share; - $mountPoint = '/' . $user->getUID() . '/files/' . trim($parentShare->getTarget(), '/') . '/'; - $mountKey = $parentShare->getNodeId() . '::' . $mountPoint; - if (!isset($cachedMounts[$mountKey])) { - $mountsChanged = true; - if ($verifyMountPoints) { - $this->shareTargetValidator->verifyMountPoint($user, $parentShare, $mountsByPath, $groupedShares); - } - } - } + private function markUserForRefresh(IUser $user): void { + $this->userConfig->setValueBool($user->getUID(), Application::APP_ID, ConfigLexicon::USER_NEEDS_SHARE_REFRESH, true); + } - if ($mountsChanged) { - $newMounts = $this->shareMountProvider->getMountsFromSuperShares($user, $shares, $this->storageFactory); - $this->userMountCache->registerMounts($user, $newMounts, [MountProvider::class]); - } + public function setCutOffMarkAllSingleShare(int $cutOffMarkAllSingleShare): void { + $this->cutOffMarkAllSingleShare = $cutOffMarkAllSingleShare; + } - unset($this->inUpdate[$user->getUID()]); + public function setCutOffMarkAllShares(int $cutOffMarkAllShares): void { + $this->cutOffMarkAllShares = $cutOffMarkAllShares; } } diff --git a/apps/files_sharing/lib/Listener/UserHomeSetupListener.php b/apps/files_sharing/lib/Listener/UserHomeSetupListener.php new file mode 100644 index 0000000000000..8886660879fa9 --- /dev/null +++ b/apps/files_sharing/lib/Listener/UserHomeSetupListener.php @@ -0,0 +1,44 @@ + + */ +class UserHomeSetupListener implements IEventListener { + public function __construct( + private readonly ShareRecipientUpdater $updater, + private readonly IUserConfig $userConfig, + ) { + } + + public function handle(Event $event): void { + if (!$event instanceof UserHomeSetupEvent) { + return; + } + + $user = $event->getUser(); + if ($this->userConfig->getValueBool($user->getUID(), Application::APP_ID, ConfigLexicon::USER_NEEDS_SHARE_REFRESH)) { + $this->updater->updateForUser($user); + $this->userConfig->setValueBool($user->getUID(), Application::APP_ID, ConfigLexicon::USER_NEEDS_SHARE_REFRESH, false); + } + } + +} diff --git a/apps/files_sharing/lib/ShareRecipientUpdater.php b/apps/files_sharing/lib/ShareRecipientUpdater.php new file mode 100644 index 0000000000000..97de93a29bedf --- /dev/null +++ b/apps/files_sharing/lib/ShareRecipientUpdater.php @@ -0,0 +1,79 @@ +inUpdate[$user->getUID()])) { + return; + } + $this->inUpdate[$user->getUID()] = true; + + $cachedMounts = $this->userMountCache->getMountsForUser($user); + $shareMounts = array_filter($cachedMounts, fn (ICachedMountInfo $mount) => $mount->getMountProvider() === MountProvider::class); + $mountPoints = array_map(fn (ICachedMountInfo $mount) => $mount->getMountPoint(), $cachedMounts); + $mountsByPath = array_combine($mountPoints, $cachedMounts); + + $shares = $this->shareMountProvider->getSuperSharesForUser($user, $ignoreShares); + + $mountsChanged = count($shares) !== count($shareMounts); + foreach ($shares as &$share) { + [$parentShare, $groupedShares] = $share; + $mountPoint = '/' . $user->getUID() . '/files/' . trim($parentShare->getTarget(), '/') . '/'; + $mountKey = $parentShare->getNodeId() . '::' . $mountPoint; + if (!isset($cachedMounts[$mountKey])) { + $mountsChanged = true; + if ($verifyMountPoints) { + $this->shareTargetValidator->verifyMountPoint($user, $parentShare, $mountsByPath, $groupedShares); + } + } + } + + if ($mountsChanged) { + $newMounts = $this->shareMountProvider->getMountsFromSuperShares($user, $shares, $this->storageFactory); + $this->userMountCache->registerMounts($user, $newMounts, [MountProvider::class]); + } + + unset($this->inUpdate[$user->getUID()]); + } + + /** + * Validate a single received share for a user + */ + public function updateForShare(IUser $user, IShare $share): void { + $cachedMounts = $this->userMountCache->getMountsForUser($user); + $mountPoints = array_map(fn (ICachedMountInfo $mount) => $mount->getMountPoint(), $cachedMounts); + $mountsByPath = array_combine($mountPoints, $cachedMounts); + + $target = $this->shareTargetValidator->verifyMountPoint($user, $share, $mountsByPath, [$share]); + $mountPoint = '/' . $user->getUID() . '/files/' . trim($target, '/') . '/'; + + $this->userMountCache->addMount($user, $mountPoint, $share->getNode()->getData(), MountProvider::class); + } +} diff --git a/apps/files_sharing/tests/TestCase.php b/apps/files_sharing/tests/TestCase.php index 6b72ecb259cab..9ed3bacc39175 100644 --- a/apps/files_sharing/tests/TestCase.php +++ b/apps/files_sharing/tests/TestCase.php @@ -15,6 +15,7 @@ use OC\User\DisplayNameCache; use OCA\Files_Sharing\AppInfo\Application; use OCA\Files_Sharing\External\MountProvider as ExternalMountProvider; +use OCA\Files_Sharing\Listener\SharesUpdatedListener; use OCA\Files_Sharing\MountProvider; use OCP\Files\Config\IMountProviderCollection; use OCP\Files\IRootFolder; @@ -99,6 +100,9 @@ public static function setUpBeforeClass(): void { $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER4, 'group3'); $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_GROUP1); Server::get(IGroupManager::class)->addBackend($groupBackend); + + Server::get(SharesUpdatedListener::class)->setCutOffMarkAllShares(-1); + Server::get(SharesUpdatedListener::class)->setCutOffMarkAllSingleShare(-1); } protected function setUp(): void { diff --git a/apps/files_trashbin/lib/Trash/TrashItem.php b/apps/files_trashbin/lib/Trash/TrashItem.php index 70d5164747f0b..2864a8cd942f4 100644 --- a/apps/files_trashbin/lib/Trash/TrashItem.php +++ b/apps/files_trashbin/lib/Trash/TrashItem.php @@ -6,6 +6,7 @@ */ namespace OCA\Files_Trashbin\Trash; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\FileInfo; use OCP\IUser; @@ -169,4 +170,8 @@ public function getDeletedBy(): ?IUser { public function getMetadata(): array { return $this->fileInfo->getMetadata(); } + + public function getData(): ICacheEntry { + return $this->fileInfo->getData(); + } } diff --git a/build/integration/features/bootstrap/SharingContext.php b/build/integration/features/bootstrap/SharingContext.php index c442317a32a38..2652667f02590 100644 --- a/build/integration/features/bootstrap/SharingContext.php +++ b/build/integration/features/bootstrap/SharingContext.php @@ -32,6 +32,8 @@ protected function resetAppConfigs() { $this->deleteServerConfig('core', 'shareapi_allow_federation_on_public_shares'); $this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled'); $this->deleteServerConfig('core', 'shareapi_allow_view_without_download'); + $this->deleteServerConfig('files_sharing', 'update_single_cutoff'); + $this->deleteServerConfig('files_sharing', 'update_all_cutoff'); $this->runOcc(['config:system:delete', 'share_folder']); } diff --git a/build/integration/sharing_features/sharing-v1-part2.feature b/build/integration/sharing_features/sharing-v1-part2.feature index 0c83975fc39b5..a2b7682db1d73 100644 --- a/build/integration/sharing_features/sharing-v1-part2.feature +++ b/build/integration/sharing_features/sharing-v1-part2.feature @@ -47,6 +47,50 @@ Feature: sharing | share_with | user2 | | share_with_displayname | user2 | +Scenario: getting all shares of a file with a received share after revoking the resharing rights with delayed share check + Given user "user0" exists + And parameter "update_single_cutoff" of app "files_sharing" is set to "0" + And parameter "update_all_cutoff" of app "files_sharing" is set to "0" + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user1" is shared with user "user0" + And user "user0" accepts last share + And Updating last share with + | permissions | 1 | + And file "textfile0.txt" of user "user1" is shared with user "user2" + When As an "user0" + And sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=/textfile0 (2).txt" + Then the list of returned shares has 1 shares + And share 0 is returned with + | share_type | 0 | + | uid_owner | user1 | + | displayname_owner | user1 | + | path | /textfile0 (2).txt | + | item_type | file | + | mimetype | text/plain | + | storage_id | shared::/textfile0 (2).txt | + | file_target | /textfile0.txt | + | share_with | user2 | + | share_with_displayname | user2 | + # After user2 does an FS setup the share is renamed + When As an "user2" + And Downloading file "/textfile0 (2).txt" with range "bytes=10-18" + Then Downloaded content should be "test text" + When As an "user0" + And sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=/textfile0 (2).txt" + Then the list of returned shares has 1 shares + And share 0 is returned with + | share_type | 0 | + | uid_owner | user1 | + | displayname_owner | user1 | + | path | /textfile0 (2).txt | + | item_type | file | + | mimetype | text/plain | + | storage_id | shared::/textfile0 (2).txt | + | file_target | /textfile0 (2).txt | + | share_with | user2 | + | share_with_displayname | user2 | + Scenario: getting all shares of a file with a received share also reshared after revoking the resharing rights Given user "user0" exists And user "user1" exists diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 634b83f8731e8..b9b48145257d8 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3518,7 +3518,6 @@ - diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index b2008b286ca25..0b663cabc3c7b 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -470,6 +470,7 @@ 'OCP\\Files\\Events\\Node\\NodeRenamedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeRenamedEvent.php', 'OCP\\Files\\Events\\Node\\NodeTouchedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeTouchedEvent.php', 'OCP\\Files\\Events\\Node\\NodeWrittenEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeWrittenEvent.php', + 'OCP\\Files\\Events\\UserHomeSetupEvent' => $baseDir . '/lib/public/Files/Events/UserHomeSetupEvent.php', 'OCP\\Files\\File' => $baseDir . '/lib/public/Files/File.php', 'OCP\\Files\\FileInfo' => $baseDir . '/lib/public/Files/FileInfo.php', 'OCP\\Files\\FileNameTooLongException' => $baseDir . '/lib/public/Files/FileNameTooLongException.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index fb4a73103f5b3..137723c68f38b 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -511,6 +511,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Files\\Events\\Node\\NodeRenamedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeRenamedEvent.php', 'OCP\\Files\\Events\\Node\\NodeTouchedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeTouchedEvent.php', 'OCP\\Files\\Events\\Node\\NodeWrittenEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeWrittenEvent.php', + 'OCP\\Files\\Events\\UserHomeSetupEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/UserHomeSetupEvent.php', 'OCP\\Files\\File' => __DIR__ . '/../../..' . '/lib/public/Files/File.php', 'OCP\\Files\\FileInfo' => __DIR__ . '/../../..' . '/lib/public/Files/FileInfo.php', 'OCP\\Files\\FileNameTooLongException' => __DIR__ . '/../../..' . '/lib/public/Files/FileNameTooLongException.php', diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php index 967d404b8a4f0..cc01c8f6c79fc 100644 --- a/lib/private/Files/FileInfo.php +++ b/lib/private/Files/FileInfo.php @@ -7,8 +7,8 @@ */ namespace OC\Files; +use OC\Files\Cache\CacheEntry; use OC\Files\Mount\HomeMountPoint; -use OCA\Files_Sharing\External\Mount; use OCA\Files_Sharing\ISharedMountPoint; use OCP\Files\Cache\ICacheEntry; use OCP\Files\Mount\IMountPoint; @@ -223,8 +223,12 @@ public function getType() { return $this->data['type']; } - public function getData() { - return $this->data; + public function getData(): ICacheEntry { + if ($this->data instanceof ICacheEntry) { + return $this->data; + } else { + return new CacheEntry($this->data); + } } /** diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php index d04c8aefb7e06..0e11855fc32c0 100644 --- a/lib/private/Files/Node/LazyFolder.php +++ b/lib/private/Files/Node/LazyFolder.php @@ -10,6 +10,7 @@ use OC\Files\Filesystem; use OC\Files\Utils\PathHelper; use OCP\Constants; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; @@ -563,6 +564,10 @@ public function getMetadata(): array { return $this->data['metadata'] ?? $this->__call(__FUNCTION__, func_get_args()); } + public function getData(): ICacheEntry { + return $this->__call(__FUNCTION__, func_get_args()); + } + public function verifyPath($fileName, $readonly = false): void { $this->__call(__FUNCTION__, func_get_args()); } diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php index fd8d84883d964..7a7867e6a4e7a 100644 --- a/lib/private/Files/Node/Node.php +++ b/lib/private/Files/Node/Node.php @@ -12,6 +12,7 @@ use OC\Files\Utils\PathHelper; use OCP\EventDispatcher\GenericEvent; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\FileInfo; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; @@ -486,4 +487,8 @@ public function getParentId(): int { public function getMetadata(): array { return $this->fileInfo->getMetadata(); } + + public function getData(): ICacheEntry { + return $this->fileInfo->getData(); + } } diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index c8945de7caed1..89690f9ed202e 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -43,6 +43,7 @@ use OCP\Files\Events\InvalidateMountCacheEvent; use OCP\Files\Events\Node\BeforeNodeRenamedEvent; use OCP\Files\Events\Node\FilesystemTornDownEvent; +use OCP\Files\Events\UserHomeSetupEvent; use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\Files\Mount\IMountPoint; @@ -327,6 +328,9 @@ private function oneTimeUserSetup(IUser $user) { $this->eventLogger->end('fs:setup:user:home:scan'); } $this->eventLogger->end('fs:setup:user:home'); + + $event = new UserHomeSetupEvent($user, $homeMount); + $this->eventDispatcher->dispatchTyped($event); } else { $this->mountManager->addMount(new MountPoint( new NullStorage([]), diff --git a/lib/public/Files/Events/UserHomeSetupEvent.php b/lib/public/Files/Events/UserHomeSetupEvent.php new file mode 100644 index 0000000000000..5a7df994f8e1b --- /dev/null +++ b/lib/public/Files/Events/UserHomeSetupEvent.php @@ -0,0 +1,46 @@ +user; + } + + /** + * @since 34.0.0 + */ + public function getHomeMount(): IMountPoint { + return $this->homeMount; + } +} diff --git a/lib/public/Files/FileInfo.php b/lib/public/Files/FileInfo.php index 95419d6354ac4..117408f23bc63 100644 --- a/lib/public/Files/FileInfo.php +++ b/lib/public/Files/FileInfo.php @@ -8,6 +8,7 @@ namespace OCP\Files; use OCP\AppFramework\Attribute\Consumable; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\Storage\IStorage; /** @@ -298,4 +299,12 @@ public function getParentId(): int; * @since 28.0.0 */ public function getMetadata(): array; + + /** + * Get the filecache data for the file + * + * @return ICacheEntry + * @since 34.0.0 + */ + public function getData(): ICacheEntry; }