diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index fcbd45f..e232184 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -9,17 +9,15 @@
namespace OCA\JSLoader\AppInfo;
-use OC\Security\CSP\ContentSecurityPolicy;
-use OC\Security\CSP\ContentSecurityPolicyNonceManager;
+use OCA\JSLoader\Listeners\AddContentSecurityPolicyListener;
+use OCA\JSLoader\Listeners\BeforeTemplateRenderedListener;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
-use OCP\IAppConfig;
-use OCP\IURLGenerator;
-use OCP\Security\IContentSecurityPolicyManager;
-use OCP\Server;
-use OCP\Util;
+use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent;
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
+use OCP\Security\CSP\AddContentSecurityPolicyEvent;
class Application extends App implements IBootstrap {
public const APP_ID = 'jsloader';
@@ -29,38 +27,12 @@ public function __construct(array $urlParams = []) {
}
public function register(IRegistrationContext $context): void {
- // nothing to do here
+ $context->registerEventListener(AddContentSecurityPolicyEvent::class, AddContentSecurityPolicyListener::class);
+ $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
+ $context->registerEventListener(BeforeLoginTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
}
public function boot(IBootContext $context): void {
- $appConfig = Server::get(IAppConfig::class);
- $urlGenerator = Server::get(IURLGenerator::class);
- $contentSecurityPolicyManager = Server::get(IContentSecurityPolicyManager::class);
- $contentSecurityPolicyNonceManager = Server::get(ContentSecurityPolicyNonceManager::class);
-
- $snippet = $appConfig->getValueString(self::APP_ID, 'snippet', '');
- if ($snippet !== '') {
- $linkToJs = $urlGenerator->linkToRoute('jsloader.JS.script', [
- 'v' => $appConfig->getValueString(self::APP_ID, 'cachebuster', '0'),
- ]);
-
- Util::addHeader(
- 'script',
- [
- 'src' => $linkToJs,
- 'nonce' => $contentSecurityPolicyNonceManager->getNonce()
- ], ''
- );
-
- // whitelist the URL to allow loading JS from this external domain
- $url = $appConfig->getValueString(self::APP_ID, 'url');
- if ($url !== '') {
- $policy = new ContentSecurityPolicy();
- $policy->addAllowedScriptDomain($url);
- $policy->addAllowedImageDomain($url);
- $policy->addAllowedConnectDomain($url);
- $contentSecurityPolicyManager->addDefaultPolicy($policy);
- }
- }
+ // nop
}
}
diff --git a/lib/Listeners/AddContentSecurityPolicyListener.php b/lib/Listeners/AddContentSecurityPolicyListener.php
new file mode 100644
index 0000000..9c1e148
--- /dev/null
+++ b/lib/Listeners/AddContentSecurityPolicyListener.php
@@ -0,0 +1,45 @@
+
+ */
+class AddContentSecurityPolicyListener implements IEventListener {
+
+ public function __construct(
+ private readonly \OCP\IAppConfig $appConfig,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!$event instanceof AddContentSecurityPolicyEvent) {
+ return;
+ }
+
+ // whitelist the URL to allow loading JS from this external domain
+ $url = $this->appConfig->getValueString(Application::APP_ID, 'url');
+ if ($url !== '') {
+ $policy = new ContentSecurityPolicy();
+ $policy->addAllowedScriptDomain($url);
+ $policy->addAllowedImageDomain($url);
+ $policy->addAllowedConnectDomain($url);
+ $event->addPolicy($policy);
+ }
+ }
+}
diff --git a/lib/Listeners/BeforeTemplateRenderedListener.php b/lib/Listeners/BeforeTemplateRenderedListener.php
new file mode 100644
index 0000000..05fa176
--- /dev/null
+++ b/lib/Listeners/BeforeTemplateRenderedListener.php
@@ -0,0 +1,58 @@
+
+ */
+class BeforeTemplateRenderedListener implements IEventListener {
+
+ public function __construct(
+ private readonly IAppConfig $appConfig,
+ private readonly IURLGenerator $urlGenerator,
+ private readonly ContentSecurityPolicyNonceManager $contentSecurityPolicyNonceManager,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof BeforeTemplateRenderedEvent) && !($event instanceof BeforeLoginTemplateRenderedEvent)) {
+ return;
+ }
+
+ $snippet = $this->appConfig->getValueString(Application::APP_ID, 'snippet', '');
+ if ($snippet === '') {
+ return;
+ }
+
+ $linkToJs = $this->urlGenerator->linkToRoute('jsloader.JS.script', [
+ 'v' => $this->appConfig->getValueString(Application::APP_ID, 'cachebuster', '0'),
+ ]);
+
+ Util::addHeader(
+ 'script',
+ [
+ 'src' => $linkToJs,
+ 'nonce' => $this->contentSecurityPolicyNonceManager->getNonce()
+ ], ''
+ );
+ }
+}
diff --git a/psalm.xml b/psalm.xml
index d736243..47c58da 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -1,6 +1,6 @@
-
-
+
+
+
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
index 5792e59..5c064bb 100644
--- a/tests/psalm-baseline.xml
+++ b/tests/psalm-baseline.xml
@@ -1,9 +1,2 @@
-
-
-
-
-
-
-
-
+
diff --git a/tests/stubs/oc_security_csp_ContentSecurityPolicyNonceManager.php b/tests/stubs/oc_security_csp_ContentSecurityPolicyNonceManager.php
new file mode 100644
index 0000000..b3d46ed
--- /dev/null
+++ b/tests/stubs/oc_security_csp_ContentSecurityPolicyNonceManager.php
@@ -0,0 +1,25 @@
+