From 8c87c0bb28be2630ff8592d91a7997163970f23a Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 22 Jun 2022 15:53:12 +0200 Subject: [PATCH 1/3] load widgets only of enabled apps - per design, all enabled apps have their registration run - limitations, e.g. enabled by group, are not considered in that state, because we do not have a session (and might need apps?) - before instantiation of widget it has to be checked whether the providing app is actually enabled for the logged in user. - a public interface is being changed, but it is not meant to be implemented or used outside of the core handling. Therefore save to backport. Signed-off-by: Arthur Schiwon --- .../AppFramework/Bootstrap/Coordinator.php | 2 +- .../Bootstrap/RegistrationContext.php | 4 +-- lib/private/Dashboard/Manager.php | 26 ++++++++++++------- lib/public/Dashboard/IManager.php | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php index 6e05b7fdc8802..d68f9d507f12e 100644 --- a/lib/private/AppFramework/Bootstrap/Coordinator.php +++ b/lib/private/AppFramework/Bootstrap/Coordinator.php @@ -143,7 +143,7 @@ private function registerApps(array $appIds): void { */ $this->registrationContext->delegateCapabilityRegistrations($apps); $this->registrationContext->delegateCrashReporterRegistrations($apps, $this->registry); - $this->registrationContext->delegateDashboardPanelRegistrations($apps, $this->dashboardManager); + $this->registrationContext->delegateDashboardPanelRegistrations($this->dashboardManager); $this->registrationContext->delegateEventListenerRegistrations($this->eventDispatcher); $this->registrationContext->delegateContainerRegistrations($apps); $this->registrationContext->delegateMiddlewareRegistrations($apps); diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php index 6a9073b576bcc..292d453d61490 100644 --- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php +++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php @@ -394,10 +394,10 @@ public function delegateCrashReporterRegistrations(array $apps, Registry $regist /** * @param App[] $apps */ - public function delegateDashboardPanelRegistrations(array $apps, IManager $dashboardManager): void { + public function delegateDashboardPanelRegistrations(IManager $dashboardManager): void { while (($panel = array_shift($this->dashboardPanels)) !== null) { try { - $dashboardManager->lazyRegisterWidget($panel->getService()); + $dashboardManager->lazyRegisterWidget($panel->getService(), $panel->getAppId()); } catch (Throwable $e) { $appId = $panel->getAppId(); $this->logger->error("Error during dashboard registration of $appId: " . $e->getMessage(), [ diff --git a/lib/private/Dashboard/Manager.php b/lib/private/Dashboard/Manager.php index a77c389cdebb2..8c596f470fb37 100644 --- a/lib/private/Dashboard/Manager.php +++ b/lib/private/Dashboard/Manager.php @@ -27,7 +27,7 @@ namespace OC\Dashboard; use InvalidArgumentException; -use OCP\AppFramework\QueryException; +use OCP\App\IAppManager; use OCP\Dashboard\IManager; use OCP\Dashboard\IWidget; use OCP\ILogger; @@ -42,11 +42,12 @@ class Manager implements IManager { /** @var IWidget[] */ private $widgets = []; - /** @var IServerContainer */ - private $serverContainer; + private ContainerInterface $serverContainer; + private IAppManager $appManager; - public function __construct(IServerContainer $serverContainer) { + public function __construct(ContainerInterface $serverContainer, IAppManager $appManager) { $this->serverContainer = $serverContainer; + $this->appManager = $appManager; } private function registerWidget(IWidget $widget): void { @@ -57,17 +58,22 @@ private function registerWidget(IWidget $widget): void { $this->widgets[$widget->getId()] = $widget; } - public function lazyRegisterWidget(string $widgetClass): void { - $this->lazyWidgets[] = $widgetClass; + public function lazyRegisterWidget(string $widgetClass, string $appId): void { + $this->lazyWidgets[] = ['class' => $widgetClass, 'appId' => $appId]; } public function loadLazyPanels(): void { - $classes = $this->lazyWidgets; - foreach ($classes as $class) { + $services = $this->lazyWidgets; + foreach ($services as $service) { + /** @psalm-suppress InvalidCatch */ try { + if (!$this->appManager->isEnabledForUser($service['appId'])) { + // all apps are registered, but some may not be enabled for the user + continue; + } /** @var IWidget $widget */ - $widget = $this->serverContainer->query($class); - } catch (QueryException $e) { + $widget = $this->serverContainer->get($service['class']); + } catch (ContainerExceptionInterface $e) { /* * There is a circular dependency between the logger and the registry, so * we can not inject it. Thus the static call. diff --git a/lib/public/Dashboard/IManager.php b/lib/public/Dashboard/IManager.php index 396624876ef31..d9e73c89eb971 100644 --- a/lib/public/Dashboard/IManager.php +++ b/lib/public/Dashboard/IManager.php @@ -36,7 +36,7 @@ interface IManager { * @param string $widgetClass * @since 20.0.0 */ - public function lazyRegisterWidget(string $widgetClass): void; + public function lazyRegisterWidget(string $widgetClass, string $appId): void; /** * @since 20.0.0 From 5c757f31e1ebe83df59d244ddfa0022bcebab1c6 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 22 Jun 2022 18:19:00 +0200 Subject: [PATCH 2/3] avoid early DI of IAppManager - might break install Signed-off-by: Arthur Schiwon --- lib/private/Dashboard/Manager.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/private/Dashboard/Manager.php b/lib/private/Dashboard/Manager.php index 8c596f470fb37..6a8348ff88f2f 100644 --- a/lib/private/Dashboard/Manager.php +++ b/lib/private/Dashboard/Manager.php @@ -31,7 +31,8 @@ use OCP\Dashboard\IManager; use OCP\Dashboard\IWidget; use OCP\ILogger; -use OCP\IServerContainer; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; use Throwable; class Manager implements IManager { @@ -43,11 +44,10 @@ class Manager implements IManager { private $widgets = []; private ContainerInterface $serverContainer; - private IAppManager $appManager; + private ?IAppManager $appManager = null; - public function __construct(ContainerInterface $serverContainer, IAppManager $appManager) { + public function __construct(ContainerInterface $serverContainer) { $this->serverContainer = $serverContainer; - $this->appManager = $appManager; } private function registerWidget(IWidget $widget): void { @@ -63,6 +63,9 @@ public function lazyRegisterWidget(string $widgetClass, string $appId): void { } public function loadLazyPanels(): void { + if ($this->appManager === null) { + $this->appManager = $this->serverContainer->get(IAppManager::class); + } $services = $this->lazyWidgets; foreach ($services as $service) { /** @psalm-suppress InvalidCatch */ From f955faba1c484c8f1ba94f2b6483f59871e62cca Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Mon, 1 Aug 2022 15:32:02 +0200 Subject: [PATCH 3/3] fix PHP 7.3 compat Signed-off-by: Arthur Schiwon --- lib/private/Dashboard/Manager.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/private/Dashboard/Manager.php b/lib/private/Dashboard/Manager.php index 6a8348ff88f2f..6a381d62babb1 100644 --- a/lib/private/Dashboard/Manager.php +++ b/lib/private/Dashboard/Manager.php @@ -43,8 +43,11 @@ class Manager implements IManager { /** @var IWidget[] */ private $widgets = []; - private ContainerInterface $serverContainer; - private ?IAppManager $appManager = null; + /** @var ContainerInterface */ + private $serverContainer; + + /** @var ?IAppManager */ + private $appManager = null; public function __construct(ContainerInterface $serverContainer) { $this->serverContainer = $serverContainer;