diff --git a/.github/workflows/lint-eslint.yml b/.github/workflows/lint-eslint.yml index 96896e33f..36c6ad0f2 100644 --- a/.github/workflows/lint-eslint.yml +++ b/.github/workflows/lint-eslint.yml @@ -10,18 +10,6 @@ name: Lint eslint on: pull_request: - paths: - - '.github/workflows/**' - - 'src/**' - - 'appinfo/info.xml' - - 'package.json' - - 'package-lock.json' - - 'tsconfig.json' - - '.eslintrc.*' - - '.eslintignore' - - '**.js' - - '**.ts' - - '**.vue' permissions: contents: read @@ -31,14 +19,42 @@ concurrency: cancel-in-progress: true jobs: + changes: + runs-on: ubuntu-latest + + outputs: + src: ${{ steps.changes.outputs.src}} + + steps: + - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 + id: changes + continue-on-error: true + with: + filters: | + src: + - '.github/workflows/**' + - 'src/**' + - 'appinfo/info.xml' + - 'package.json' + - 'package-lock.json' + - 'tsconfig.json' + - '.eslintrc.*' + - '.eslintignore' + - '**.js' + - '**.ts' + - '**.vue' + lint: runs-on: ubuntu-latest - name: eslint + needs: changes + if: needs.changes.outputs.src != 'false' + + name: NPM lint steps: - name: Checkout - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Read package.json node and npm engines version uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2 @@ -48,7 +64,7 @@ jobs: fallbackNpm: '^9' - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3 with: node-version: ${{ steps.versions.outputs.nodeVersion }} @@ -56,7 +72,24 @@ jobs: run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" - name: Install dependencies + env: + CYPRESS_INSTALL_BINARY: 0 run: npm ci - name: Lint run: npm run lint + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: [changes, lint] + + if: always() + + # This is the summary, we just avoid to rename it so that branch protection rules still match + name: eslint + + steps: + - name: Summary status + run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index 1510ed4a8..1901f6aa3 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -7,16 +7,6 @@ name: Node on: pull_request: - paths: - - '.github/workflows/**' - - 'src/**' - - 'appinfo/info.xml' - - 'package.json' - - 'package-lock.json' - - 'tsconfig.json' - - '**.js' - - '**.ts' - - '**.vue' push: branches: - main @@ -31,13 +21,39 @@ concurrency: cancel-in-progress: true jobs: + changes: + runs-on: ubuntu-latest + + outputs: + src: ${{ steps.changes.outputs.src}} + + steps: + - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 + id: changes + continue-on-error: true + with: + filters: | + src: + - '.github/workflows/**' + - 'src/**' + - 'appinfo/info.xml' + - 'package.json' + - 'package-lock.json' + - 'tsconfig.json' + - '**.js' + - '**.ts' + - '**.vue' + build: runs-on: ubuntu-latest - name: node + needs: changes + if: needs.changes.outputs.src != 'false' + + name: NPM build steps: - name: Checkout - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Read package.json node and npm engines version uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2 @@ -47,7 +63,7 @@ jobs: fallbackNpm: '^9' - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3 with: node-version: ${{ steps.versions.outputs.nodeVersion }} @@ -55,6 +71,8 @@ jobs: run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" - name: Install dependencies & build + env: + CYPRESS_INSTALL_BINARY: 0 run: | npm ci npm run build --if-present @@ -69,3 +87,18 @@ jobs: git status git --no-pager diff exit 1 # make it red to grab attention + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: [changes, build] + + if: always() + + # This is the summary, we just avoid to rename it so that branch protection rules still match + name: node + + steps: + - name: Summary status + run: if ${{ needs.changes.outputs.src != 'false' && needs.build.result != 'success' }}; then exit 1; fi diff --git a/appinfo/app.php b/appinfo/app.php deleted file mode 100644 index 90b40faf4..000000000 --- a/appinfo/app.php +++ /dev/null @@ -1,52 +0,0 @@ -. - * - */ - -namespace OCA\Officeonline\AppInfo; - -use OCA\Officeonline\PermissionManager; - -$currentUser = \OC::$server->getUserSession()->getUser(); -if ($currentUser !== null) { - /** @var PermissionManager $permissionManager */ - $permissionManager = \OC::$server->query(PermissionManager::class); - if (!$permissionManager->isEnabledForUser($currentUser)) { - return; - } -} - -$eventDispatcher = \OC::$server->getEventDispatcher(); -$eventDispatcher->addListener( - 'OCA\Files::loadAdditionalScripts', - function () { - \OCP\Util::addScript('officeonline', 'files', 'viewer'); - } -); -$eventDispatcher->addListener( - 'OCA\Files_Sharing::loadAdditionalScripts', - function () { - \OCP\Util::addScript('officeonline', 'files', 'viewer'); - } -); - -$app = \OC::$server->query(Application::class); -$app->registerProvider(); -$app->updateCSP(); diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 749515404..081ccc7c4 100755 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -27,9 +27,14 @@ use OC\Files\Type\Detection; use OC\Security\CSP\ContentSecurityPolicy; use OCA\Federation\TrustedServers; +use OCA\Files\Event\LoadAdditionalScriptsEvent; +use OCA\Files_Sharing\Listener\LoadAdditionalListener; use OCA\Officeonline\Capabilities; use OCA\Officeonline\Hooks\WopiLockHooks; +use OCA\Officeonline\Listener\FilesScriptListener; +use OCA\Officeonline\Listener\LoadViewerListener; use OCA\Officeonline\Middleware\WOPIMiddleware; +use OCA\Officeonline\PermissionManager; use OCA\Officeonline\Preview\MSExcel; use OCA\Officeonline\Preview\MSWord; use OCA\Officeonline\Preview\OOXML; @@ -38,44 +43,46 @@ use OCA\Officeonline\Service\FederationService; use OCA\Viewer\Event\LoadViewer; use OCP\AppFramework\App; -use OCP\AppFramework\QueryException; -use OCP\EventDispatcher\IEventDispatcher; +use OCP\AppFramework\Bootstrap\IBootContext; +use OCP\AppFramework\Bootstrap\IBootstrap; +use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\IPreview; use Psr\Log\LoggerInterface; -class Application extends App { +class Application extends App implements IBootstrap { public const APP_ID = 'officeonline'; - /** - * Strips the path and query parameters from the URL. - * - * @param string $url - * @return string - */ - private function domainOnly(string $url): string { - $parsed_url = parse_url(trim($url)); - $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; - $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - return "$scheme$host$port"; - } - public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); + } - try { - /** @var IEventDispatcher $eventDispatcher */ - $eventDispatcher = $this->getContainer()->getServer()->query(IEventDispatcher::class); - if (class_exists(LoadViewer::class)) { - $eventDispatcher->addListener(LoadViewer::class, function () { - \OCP\Util::addScript('officeonline', 'viewer'); - }); + public function register(IRegistrationContext $context): void { + $context->registerCapability(Capabilities::class); + $context->registerMiddleWare(WOPIMiddleware::class); + $context->registerEventListener(LoadAdditionalScriptsEvent::class, FilesScriptListener::class); + $context->registerEventListener(LoadAdditionalListener::class, FilesScriptListener::class); + $context->registerEventListener(LoadViewer::class, LoadViewerListener::class); + } + + public function boot(IBootContext $context): void { + if (!$this->isEnabled()) { + return; + } + $this->registerProvider(); + $this->updateCSP(); + } + + public function isEnabled(): bool { + $currentUser = \OC::$server->getUserSession()->getUser(); + if ($currentUser !== null) { + /** @var PermissionManager $permissionManager */ + $permissionManager = \OCP\Server::get(PermissionManager::class); + if (!$permissionManager->isEnabledForUser($currentUser)) { + return false; } - } catch (QueryException $e) { } - $this->getContainer()->registerCapability(Capabilities::class); - $this->getContainer()->registerMiddleWare(WOPIMiddleware::class); + return true; } public function registerProvider() { @@ -159,4 +166,18 @@ public function updateCSP() { $cspManager->addDefaultPolicy($policy); } + + /** + * Strips the path and query parameters from the URL. + * + * @param string $url + * @return string + */ + private function domainOnly(string $url): string { + $parsed_url = parse_url(trim($url)); + $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; + $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; + $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; + return "$scheme$host$port"; + } } diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php index d8b47ecd4..8286fe45c 100644 --- a/lib/Controller/DocumentController.php +++ b/lib/Controller/DocumentController.php @@ -264,7 +264,6 @@ public function index($fileId, $path = null) { $response = new TemplateResponse('officeonline', 'documents', $params, 'base'); $policy = new ContentSecurityPolicy(); $policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('public_wopi_url'))); - $policy->allowInlineScript(true); $response->setContentSecurityPolicy($policy); $response->addHeader('Cache-Control', 'no-cache, no-store'); $response->addHeader('Expires', '-1'); diff --git a/lib/Listener/FilesScriptListener.php b/lib/Listener/FilesScriptListener.php new file mode 100644 index 000000000..36e7c9590 --- /dev/null +++ b/lib/Listener/FilesScriptListener.php @@ -0,0 +1,12 @@ +