From 08bec7ef055a4865884f967489bcc94b9028cc8c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 12 Feb 2026 15:42:16 +0100 Subject: [PATCH] feat: postpone receiving share validation after processing a certain number of users Signed-off-by: Robin Appelman --- .../composer/composer/autoload_classmap.php | 1 + .../composer/composer/autoload_static.php | 1 + .../files_sharing/lib/AppInfo/Application.php | 3 ++ .../lib/Config/ConfigLexicon.php | 10 +++- .../lib/Listener/SharesUpdatedListener.php | 53 ++++++++++++++++--- .../lib/Listener/UserHomeSetupListener.php | 44 +++++++++++++++ 6 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 apps/files_sharing/lib/Listener/UserHomeSetupListener.php diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php index c3dea9de9ce..138746aad8f 100644 --- a/apps/files_sharing/composer/composer/autoload_classmap.php +++ b/apps/files_sharing/composer/composer/autoload_classmap.php @@ -72,6 +72,7 @@ return array( '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', diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php index 57cf4cc29fb..3decf0b9c1a 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', diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index 75fa6915b88..0cdb2e71f24 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\LoadSidebarListener; 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\Config\IMountProviderCollection; 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; @@ -123,6 +125,7 @@ class Application extends App implements IBootstrap { $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 c063153765e..a6fb9f11ae6 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 @@ class ConfigLexicon implements ILexicon { 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 data immediately for single-share updates'), + new Entry(self::UPDATE_ALL_CUTOFF, ValueType::INT, 3, 'For how many users do we update the share data 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 3cfe3c3a3a5..5e9d26a53da 100644 --- a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php +++ b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php @@ -8,12 +8,17 @@ declare(strict_types=1); 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\ShareRecipientUpdater; +use OCP\Config\IUserConfig; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; 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; use OCP\Share\Events\ShareTransferredEvent; @@ -25,35 +30,71 @@ use OCP\Share\IManager; * @template-implements IEventListener */ class SharesUpdatedListener implements IEventListener { + /** + * 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 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->shareUpdater->updateForUser($user, true); + $this->updateOrMarkUser($user, true); } } if ($event instanceof UserAddedEvent || $event instanceof UserRemovedEvent) { - $this->shareUpdater->updateForUser($event->getUser(), true); + $this->updateOrMarkUser($event->getUser(), 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->shareUpdater->updateForShare($user, $share); - // Share target validation might have changed the target, restore it for the next user - $share->setTarget($shareTarget); + $this->updatedCount++; + if ($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->shareManager->updateForUser($user, false, [$event->getShare()]); + $this->updateOrMarkUser($user, false, [$event->getShare()]); } } } + + private function updateOrMarkUser(IUser $user, bool $verifyMountPoints, array $ignoreShares = []): void { + $this->updatedCount++; + if ($this->updatedCount <= $this->cutOffMarkAllShares) { + $this->shareUpdater->updateForUser($user, $verifyMountPoints, $ignoreShares); + } else { + $this->markUserForRefresh($user); + } + } + + private function markUserForRefresh(IUser $user): void { + $this->userConfig->setValueBool($user->getUID(), Application::APP_ID, ConfigLexicon::USER_NEEDS_SHARE_REFRESH, true); + } } diff --git a/apps/files_sharing/lib/Listener/UserHomeSetupListener.php b/apps/files_sharing/lib/Listener/UserHomeSetupListener.php new file mode 100644 index 00000000000..8886660879f --- /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); + } + } + +}