diff options
author | Julius Härtl <jus@bitgrid.net> | 2019-08-16 14:49:25 +0300 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2019-08-27 19:43:24 +0300 |
commit | 0ef0b05bd2a4b232f18f4b64a3863b7f64376fa6 (patch) | |
tree | c45082ad57a9716cddfe830b91b858913605d9dc /lib | |
parent | f65eddfaa11cc726ce4aed70c9b05ab32369a24b (diff) |
Handle CSP properly
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AppInfo/Application.php | 4 | ||||
-rw-r--r-- | lib/Controller/DirectViewController.php | 42 | ||||
-rw-r--r-- | lib/Controller/DocumentController.php | 43 | ||||
-rw-r--r-- | lib/Controller/OCSController.php | 22 | ||||
-rw-r--r-- | lib/Service/FederationService.php | 5 | ||||
-rw-r--r-- | lib/TokenManager.php | 15 |
6 files changed, 100 insertions, 31 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 2ac62482..d69bc858 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -85,7 +85,7 @@ class Application extends App { } - public function updateCSP() { + public function updateCSP(): void { $container = $this->getContainer(); $publicWopiUrl = $container->getServer()->getConfig()->getAppValue('richdocuments', 'public_wopi_url', ''); @@ -111,7 +111,7 @@ class Application extends App { $trustedServers = $container->query(TrustedServers::class); /** @var FederationService $federationService */ $federationService = $container->query(FederationService::class); - $remoteAccess = \OC::$server->getRequest()->getParam('richdocuments_remote_access'); + $remoteAccess = $container->getServer()->getRequest()->getParam('richdocuments_remote_access'); if ($remoteAccess && $trustedServers->isTrustedServer($remoteAccess)) { $remoteCollabora = $federationService->getRemoteCollaboraURL($remoteAccess); diff --git a/lib/Controller/DirectViewController.php b/lib/Controller/DirectViewController.php index 0d5f8c71..8a52777b 100644 --- a/lib/Controller/DirectViewController.php +++ b/lib/Controller/DirectViewController.php @@ -24,6 +24,7 @@ namespace OCA\Richdocuments\Controller; use OCA\Richdocuments\AppConfig; use OCA\Richdocuments\Db\DirectMapper; +use OCA\Richdocuments\Service\FederationService; use OCA\Richdocuments\TemplateManager; use OCA\Richdocuments\TokenManager; use OCP\AppFramework\Controller; @@ -31,6 +32,7 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\Files\IRootFolder; use OCP\Files\Node; @@ -72,6 +74,7 @@ class DirectViewController extends Controller { $this->config = $config; $this->appConfig = $appConfig; $this->templateManager = $templateManager; + $this->federationService = \OC::$server->query(FederationService::class); } /** @@ -85,12 +88,14 @@ class DirectViewController extends Controller { try { $direct = $this->directMapper->getByToken($token); } catch (DoesNotExistException $e) { - //TODO show 404 - return new JSONResponse([], Http::STATUS_NOT_FOUND); + $params = [ + 'errors' => [['error' => $e->getMessage()]] + ]; + return new TemplateResponse('core', 'error', $params, 'guest'); } // Delete the token. They are for 1 time use only - $this->directMapper->delete($direct); + //$this->directMapper->delete($direct); $folder = $this->rootFolder->getUserFolder($direct->getUid()); if ($this->templateManager->isTemplate($direct->getFileid())) { @@ -114,9 +119,33 @@ class DirectViewController extends Controller { throw new \Exception(); } + /** + * Open file from remote collabora + */ + if ($item->getFileInfo()->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) { + $remote = $item->getStorage()->getRemote(); + $remoteCollabora = $this->federationService->getRemoteCollaboraURL($remote); + if ($remoteCollabora !== '') { + $wopi = $this->tokenManager->getRemoteTokenFromDirect($item, $direct->getUid()); + $url = $remote . 'index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() . + '&remoteServer=' . $wopi->getServerHost() . + '&remoteServerToken=' . $wopi->getToken(); + if ($item->getInternalPath() !== '') { + $url .= '&filePath=' . $item->getInternalPath(); + } + $response = new RedirectResponse($url); + $response->addHeader('X-Frame-Options', 'ALLOW'); + return $response; + } else { + $this->logger->warning('Failed to connect to remote collabora instance for ' . $item->getId()); + } + } list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), null, $direct->getUid(), true); } catch (\Exception $e) { - return new JSONResponse([], Http::STATUS_BAD_REQUEST); + $params = [ + 'errors' => [['error' => $e->getMessage()]] + ]; + return new TemplateResponse('core', 'error', $params, 'guest'); } $relativePath = $folder->getRelativePath($item->getPath()); @@ -142,7 +171,10 @@ class DirectViewController extends Controller { $response->setContentSecurityPolicy($policy); return $response; } catch (\Exception $e) { - return new JSONResponse([], Http::STATUS_BAD_REQUEST); + $params = [ + 'errors' => [['error' => $e->getMessage()]] + ]; + return new TemplateResponse('core', 'error', $params, 'guest'); } } diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php index 6ddd97bf..ac27e799 100644 --- a/lib/Controller/DocumentController.php +++ b/lib/Controller/DocumentController.php @@ -170,6 +170,47 @@ class DocumentController extends Controller { } /** + * Redirect to the files app with proper CSP headers set for federated editing + * + * This is a workaround since we cannot set a nonce for allowing dynamic URLs in the richdocument iframe + * + * + * @NoAdminRequired + * @NoCSRFRequired + */ + public function open($fileId) { + try { + $folder = $this->rootFolder->getUserFolder($this->uid); + $item = $folder->getById($fileId)[0]; + if (!($item instanceof Node)) { + throw new \Exception(); + } + + if ($item->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) { + $remote = $item->getStorage()->getRemote(); + $remoteCollabora = $this->federationService->getRemoteCollaboraURL($remote); + if ($remoteCollabora !== '') { + $dir = $item->getInternalPath() === '' ? '/' : $item->getInternalPath(); + $url = '/index.php/apps/files?dir=' . $dir . + '&richdocuments_open=' . $item->getName() . + '&richdocuments_fileId=' . $fileId . + '&richdocuments_remote_access=' . $remote; + return new RedirectResponse($url); + } + $this->logger->warning('Failed to connect to remote collabora instance for ' . $fileId); + } + } catch (\Exception $e) { + $this->logger->logException($e, ['app'=>'richdocuments']); + $params = [ + 'errors' => [['error' => $e->getMessage()]] + ]; + return new TemplateResponse('core', 'error', $params, 'guest'); + } + + return new TemplateResponse('core', '403', [], 'guest'); + } + + /** * @NoAdminRequired * * @param string $fileId @@ -199,6 +240,8 @@ class DocumentController extends Controller { $response = new RedirectResponse($url); $response->addHeader('X-Frame-Options', 'ALLOW'); return $response; + } else { + $this->logger->warning('Failed to connect to remote collabora instance for ' . $fileId); } } list($urlSrc, $token) = $this->tokenManager->getToken($item->getId()); diff --git a/lib/Controller/OCSController.php b/lib/Controller/OCSController.php index fe1e9de5..8574ffb7 100644 --- a/lib/Controller/OCSController.php +++ b/lib/Controller/OCSController.php @@ -109,29 +109,7 @@ class OCSController extends \OCP\AppFramework\OCSController { throw new OCSBadRequestException('Cannot view folder'); } - /** - * Open file from remote collabora - */ - if ($node->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) { - $remote = $node->getStorage()->getRemote(); - $remoteCollabora = $this->federationService->getRemoteDirectToken($remote); - if ($remoteCollabora !== '') { - $wopi = $this->tokenManager->getRemoteToken($item); - $url = $remote . 'index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() . - '&remoteServer=' . $wopi->getServerHost() . - '&remoteServerToken=' . $wopi->getToken(); - if ($item->getInternalPath() !== '') { - $url .= '&filePath=' . $item->getInternalPath(); - } - $response = new RedirectResponse($url); - $response->addHeader('X-Frame-Options', 'ALLOW'); - return $response; - } - } - - //TODO check if we can even edit this file with collabora $direct = $this->directMapper->newDirect($this->userId, $fileId); - // TODO: convert to remote token if needed return new DataResponse([ 'url' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.directView.show', [ diff --git a/lib/Service/FederationService.php b/lib/Service/FederationService.php index 8b2e775d..22b6387b 100644 --- a/lib/Service/FederationService.php +++ b/lib/Service/FederationService.php @@ -28,6 +28,7 @@ use OCA\Federation\TrustedServers; use OCP\AppFramework\QueryException; use OCP\Http\Client\IClientService; use OCP\ICache; +use OCP\ICacheFactory; use OCP\ILogger; class FederationService { @@ -41,8 +42,8 @@ class FederationService { /** @var TrustedServers */ private $trustedServers; - public function __construct(ICache $cache, IClientService $clientService, ILogger $logger) { - $this->cache = $cache; + public function __construct(ICacheFactory $cacheFactory, IClientService $clientService, ILogger $logger) { + $this->cache = $cacheFactory->createLocal('richdocuments_remote/'); $this->clientService = $clientService; $this->logger = $logger; try { diff --git a/lib/TokenManager.php b/lib/TokenManager.php index f73141f6..68278d54 100644 --- a/lib/TokenManager.php +++ b/lib/TokenManager.php @@ -232,4 +232,19 @@ class TokenManager { $this->wopiMapper->update($wopi); return $wopi; } + + /** + * @param Node $node + * @return Wopi + */ + public function getRemoteTokenFromDirect(Node $node, $editorUid) { + list($urlSrc, $token, $wopi) = $this->getToken($node->getId(), null, $editorUid, true, true); + $wopi->setIsRemoteToken(true); + $wopi->setRemoteServer($node->getStorage()->getRemote()); + + $this->wopiMapper->update($wopi); + return $wopi; + } + + } |