Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/richdocuments.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2021-04-23 15:27:56 +0300
committerJulius Härtl <jus@bitgrid.net>2021-04-28 11:40:58 +0300
commit9ecf2aafc64f8e366c7bae5a73c37da8452bb604 (patch)
treefd6d5d479c5c2f15e044823fe5de3c9d66fff292 /lib
parent3067440843cd86d10f99ee6ed06c90882f87e7aa (diff)
Implement token types
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/Controller/DirectViewController.php77
-rw-r--r--lib/Controller/DocumentController.php124
-rw-r--r--lib/Controller/FederationController.php68
-rw-r--r--lib/Controller/OCSController.php122
-rw-r--r--lib/Controller/WopiController.php87
-rw-r--r--lib/Db/Direct.php12
-rw-r--r--lib/Db/DirectMapper.php7
-rw-r--r--lib/Db/Wopi.php44
-rw-r--r--lib/Db/WopiMapper.php22
-rw-r--r--lib/Migration/Version30717Date20210310164901.php21
-rw-r--r--lib/Service/FederationService.php89
-rw-r--r--lib/TokenManager.php100
12 files changed, 505 insertions, 268 deletions
diff --git a/lib/Controller/DirectViewController.php b/lib/Controller/DirectViewController.php
index b6616770..7b5cac06 100644
--- a/lib/Controller/DirectViewController.php
+++ b/lib/Controller/DirectViewController.php
@@ -23,6 +23,7 @@
namespace OCA\Richdocuments\Controller;
use OCA\Richdocuments\AppConfig;
+use OCA\Richdocuments\Db\Direct;
use OCA\Richdocuments\Db\DirectMapper;
use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\TemplateManager;
@@ -34,10 +35,12 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IConfig;
+use OCP\ILogger;
use OCP\IRequest;
class DirectViewController extends Controller {
@@ -62,6 +65,9 @@ class DirectViewController extends Controller {
/** @var FederationService */
private $federationService;
+ /** @var ILogger */
+ private $logger;
+
public function __construct(
$appName,
IRequest $request,
@@ -71,7 +77,8 @@ class DirectViewController extends Controller {
IConfig $config,
AppConfig $appConfig,
TemplateManager $templateManager,
- FederationService $federationService
+ FederationService $federationService,
+ ILogger $logger
) {
parent::__construct($appName, $request);
@@ -82,6 +89,7 @@ class DirectViewController extends Controller {
$this->appConfig = $appConfig;
$this->templateManager = $templateManager;
$this->federationService = $federationService;
+ $this->logger = $logger;
}
/**
@@ -108,6 +116,12 @@ class DirectViewController extends Controller {
// Delete the token. They are for 1 time use only
$this->directMapper->delete($direct);
+ // Direct token for share link
+ if (!empty($direct->getShare())) {
+ return $this->showPublicShare($direct);
+ }
+
+
$folder = $this->rootFolder->getUserFolder($direct->getUid());
if ($this->templateManager->isTemplate($direct->getFileid())) {
$item = $this->templateManager->get($direct->getFileid());
@@ -116,7 +130,6 @@ class DirectViewController extends Controller {
}
try {
-
list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($item, $direct->getUid(), $direct->getTemplateDestination(), true);
} catch (\Exception $e) {
return new JSONResponse([], Http::STATUS_BAD_REQUEST);
@@ -177,4 +190,64 @@ class DirectViewController extends Controller {
}
}
+
+ public function showPublicShare(Direct $direct) {
+ try {
+ $share = \OC::$server->getShareManager()->getShareByToken($direct->getShare());
+
+ $node = $share->getNode();
+ if ($node instanceof Folder) {
+ $nodes = $node->getById($direct->getFileid());
+ $node = array_shift($nodes);
+ if ($node === null) {
+ throw new NotFoundException();
+ }
+ }
+
+ // Handle opening a share link that originates from a remote instance
+ $federatedUrl = $this->federationService->getRemoteRedirectURL($node, $direct, $share);
+ if ($federatedUrl !== null) {
+ $response = new RedirectResponse($federatedUrl);
+ $response->addHeader('X-Frame-Options', 'ALLOW');
+ return $response;
+ }
+
+ $this->settings = \OC::$server->getConfig();
+ if ($node instanceof Node) {
+ $params = [
+ 'permissions' => $share->getPermissions(),
+ 'title' => $node->getName(),
+ 'fileId' => $node->getId() . '_' . $this->settings->getSystemValue('instanceid'),
+ 'path' => '/',
+ 'instanceId' => $this->settings->getSystemValue('instanceid'),
+ 'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
+ 'userId' => null,
+ 'direct' => true
+ ];
+
+ list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($node->getId(), $direct->getShare(), $direct->getUid(), true);
+ if (!empty($direct->getInitiatorHost())) {
+ $this->tokenManager->upgradeFromDirectInitiator($direct, $wopi);
+ }
+ $params['token'] = $token;
+ $params['urlsrc'] = $urlSrc;
+
+ $response = new TemplateResponse('richdocuments', 'documents', $params, 'base');
+ $policy = new ContentSecurityPolicy();
+ $policy->allowInlineScript(true);
+ $policy->addAllowedFrameDomain($this->appConfig->getAppValue('public_wopi_url'));
+ $response->setContentSecurityPolicy($policy);
+ return $response;
+ }
+ } 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');
+
+ }
}
diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php
index 0f6b969a..f315ccdd 100644
--- a/lib/Controller/DocumentController.php
+++ b/lib/Controller/DocumentController.php
@@ -192,56 +192,6 @@ 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 File)) {
- throw new \Exception('Node is not a file');
- }
-
- if ($item->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) {
- $remote = $item->getStorage()->getRemote();
- $remoteCollabora = $this->federationService->getRemoteCollaboraURL($remote);
- if ($remoteCollabora !== '') {
- $absolute = $item->getParent()->getPath();
- $relativeFolderPath = $folder->getRelativePath($absolute);
- $relativeFilePath = $folder->getRelativePath($item->getPath());
- $url = '/index.php/apps/files/?dir=' . $relativeFolderPath .
- '&richdocuments_open=' . $relativeFilePath .
- '&richdocuments_fileId=' . $fileId .
- '&richdocuments_remote_access=' . $remote;
-
- $event = new BeforeFederationRedirectEvent(
- $item, $relativeFolderPath, $remote
- );
- $eventDispatcher = \OC::$server->getEventDispatcher();
- $eventDispatcher->dispatch(BeforeFederationRedirectEvent::class, $event);
- if ($event->getRedirectUrl()) {
- $url = $event->getRedirectUrl();
- }
- 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
@@ -262,7 +212,10 @@ class DocumentController extends Controller {
throw new \Exception();
}
- /** Open file from remote collabora */
+ /**
+ * Open file on source instance if it is originating from a federated share
+ * The generated url will result in {@link remote()}
+ */
$federatedUrl = $this->federationService->getRemoteRedirectURL($item);
if ($federatedUrl !== null) {
$response = new RedirectResponse($federatedUrl);
@@ -304,8 +257,6 @@ class DocumentController extends Controller {
];
return new TemplateResponse('core', 'error', $params, 'guest');
}
-
- return new TemplateResponse('core', '403', [], 'guest');
}
/**
@@ -342,7 +293,6 @@ class DocumentController extends Controller {
$template = $this->templateManager->get($templateId);
list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($template, $this->uid, $file->getId());
- $wopiFileId = $template->getId() . '-' . $file->getId() . '_' . $this->settings->getSystemValue('instanceid');
$wopiFileId = $wopi->getFileid() . '_' . $this->settings->getSystemValue('instanceid');
$params = [
@@ -368,7 +318,7 @@ class DocumentController extends Controller {
*
* @param string $shareToken
* @param string $fileName
- * @return TemplateResponse
+ * @return TemplateResponse|RedirectResponse
* @throws \Exception
*/
public function publicPage($shareToken, $fileName, $fileId) {
@@ -389,6 +339,12 @@ class DocumentController extends Controller {
} else {
$item = $node;
}
+ $federatedUrl = $this->federationService->getRemoteRedirectURL($item, null, $share);
+ if ($federatedUrl !== null) {
+ $response = new RedirectResponse($federatedUrl);
+ $response->addHeader('X-Frame-Options', 'ALLOW');
+ return $response;
+ }
if ($item instanceof Node) {
$params = [
'permissions' => $share->getPermissions(),
@@ -422,6 +378,58 @@ 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 openRemoteFile($fileId) {
+ try {
+ $folder = $this->rootFolder->getUserFolder($this->uid);
+ $item = $folder->getById($fileId)[0];
+ if (!($item instanceof File)) {
+ throw new \Exception('Node is not a file');
+ }
+
+ if ($item->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) {
+ $remote = $item->getStorage()->getRemote();
+ $remoteCollabora = $this->federationService->getRemoteCollaboraURL($remote);
+ if ($remoteCollabora !== '') {
+ $absolute = $item->getParent()->getPath();
+ $relativeFolderPath = $folder->getRelativePath($absolute);
+ $relativeFilePath = $folder->getRelativePath($item->getPath());
+ $url = '/index.php/apps/files/?dir=' . $relativeFolderPath .
+ '&richdocuments_open=' . $relativeFilePath .
+ '&richdocuments_fileId=' . $fileId .
+ '&richdocuments_remote_access=' . $remote;
+
+ $event = new BeforeFederationRedirectEvent(
+ $item, $relativeFolderPath, $remote
+ );
+ $eventDispatcher = \OC::$server->getEventDispatcher();
+ $eventDispatcher->dispatch(BeforeFederationRedirectEvent::class, $event);
+ if ($event->getRedirectUrl()) {
+ $url = $event->getRedirectUrl();
+ }
+ 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');
+ }
+
+ /**
+ * Open file on Source instance with token from Initiator instance
+ *
* @PublicPage
* @NoCSRFRequired
*
@@ -455,10 +463,10 @@ class DocumentController extends Controller {
if ($remoteWopi === null) {
throw new \Exception('Invalid remote file details for ' . $remoteServerToken);
}
- $this->tokenManager->updateToFederationToken($wopi, $shareToken, $remoteServer, $remoteServerToken, $remoteWopi);
+ $this->tokenManager->upgradeToRemoteToken($wopi, $remoteWopi, $shareToken, $remoteServer, $remoteServerToken);
$permissions = $share->getPermissions();
- if (!$remoteWopi['canwrite']) {
+ if (!$remoteWopi->getCanwrite()) {
$permissions = $permissions & ~ Constants::PERMISSION_UPDATE;
}
@@ -471,7 +479,7 @@ class DocumentController extends Controller {
'path' => '/',
'instanceId' => $this->settings->getSystemValue('instanceid'),
'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
- 'userId' => $remoteWopi['editorUid'] . '@' . $remoteServer
+ 'userId' => $remoteWopi->getEditorUid() ? ($remoteWopi->getEditorUid() . '@' . $remoteServer) : null,
];
$response = new TemplateResponse('richdocuments', 'documents', $params, 'base');
diff --git a/lib/Controller/FederationController.php b/lib/Controller/FederationController.php
index 6ec1409d..8a0f9277 100644
--- a/lib/Controller/FederationController.php
+++ b/lib/Controller/FederationController.php
@@ -23,45 +23,44 @@
namespace OCA\Richdocuments\Controller;
use OCP\AppFramework\Db\DoesNotExistException;
-use \OCP\AppFramework\OCSController;
+use OCP\AppFramework\OCS\OCSNotFoundException;
+use OCP\AppFramework\OCSController;
use OCA\Richdocuments\Db\WopiMapper;
use OCP\AppFramework\Http\DataResponse;
-use OCP\AppFramework\OCS\OCSNotFoundException;
-use OCP\Files\NotFoundException;
use OCP\IConfig;
+use OCP\ILogger;
use OCP\IRequest;
-use OCP\Share\Exceptions\ShareNotFound;
-use OCP\Share\IManager;
class FederationController extends OCSController {
/** @var IConfig */
private $config;
+ /** @var ILogger */
+ private $logger;
+
/** @var WopiMapper */
private $wopiMapper;
- /** @var IManager */
- private $shareManager;
-
public function __construct(
string $appName,
IRequest $request,
IConfig $config,
- WopiMapper $wopiMapper,
- IManager $shareManager
+ ILogger $logger,
+ WopiMapper $wopiMapper
) {
parent::__construct($appName, $request);
$this->config = $config;
+ $this->logger = $logger;
$this->wopiMapper = $wopiMapper;
- $this->shareManager = $shareManager;
}
/**
* @PublicPage
* @NoCSRFRequired
+ * @OCSRoute GET /api/v1/federation
*/
- public function index() {
+ public function index(): DataResponse {
$response = new DataResponse([
'wopi_url' => $this->config->getAppValue('richdocuments', 'wopi_url')
]);
@@ -72,6 +71,7 @@ class FederationController extends OCSController {
/**
* @PublicPage
* @NoCSRFRequired
+ * @OCSRoute POST /api/v1/federation
*
* Check the file info of a remote accessing a file
*
@@ -82,17 +82,39 @@ class FederationController extends OCSController {
* @return DataResponse
* @throws DoesNotExistException
*/
- public function remoteWopiToken($token) {
- $wopi = $this->wopiMapper->getWopiForToken($token);
- return new DataResponse([
- 'ownerUid' => $wopi->getOwnerUid(),
- 'editorUid' => $wopi->getEditorUid(),
- 'canwrite' => $wopi->getCanwrite(),
- 'hideDownload' => $wopi->getHideDownload(),
- 'direct' => $wopi->getDirect(),
- 'serverHost' => $wopi->getServerHost(),
- 'guestDisplayname' => $wopi->getGuestDisplayname()
- ]);
+ public function remoteWopiToken($token): DataResponse {
+ try {
+ $wopi = $this->wopiMapper->getWopiForToken($token);
+ $user = \OC::$server->getUserManager()->get($wopi->getEditorUid());
+ if($user !== null) {
+ $wopi->setGuestDisplayname($user->getDisplayName());
+ }
+ $this->logger->debug('COOL-Federation-Initiator: Token ' . $token . ' returned');
+ return new DataResponse($wopi);
+ } catch (DoesNotExistException $e) {
+ $this->logger->debug('COOL-Federation-Initiator: Token ' . $token . 'not found');
+ throw new OCSNotFoundException();
+ }
+ }
+
+ public function initiatorUser($token): DataResponse {
+ try {
+ $wopi = $this->wopiMapper->getWopiForToken($token);
+ $user = \OC::$server->getUserManager()->get($wopi->getEditorUid());
+ if($user !== null) {
+ $wopi->setGuestDisplayname($user->getDisplayName());
+ }
+ $this->logger->debug('COOL-Federation-Initiator-User: Token ' . $token . ' returned');
+ return new DataResponse([
+ 'initiatorHost' => '',
+ 'userId' => '',
+ 'displayName' => '',
+ 'avatar' => ''
+ ]);
+ } catch (DoesNotExistException $e) {
+ $this->logger->debug('COOL-Federation-Initiator-User: Token ' . $token . 'not found');
+ throw new OCSNotFoundException();
+ }
}
}
diff --git a/lib/Controller/OCSController.php b/lib/Controller/OCSController.php
index ea79e0c5..23188a3c 100644
--- a/lib/Controller/OCSController.php
+++ b/lib/Controller/OCSController.php
@@ -26,6 +26,7 @@ namespace OCA\Richdocuments\Controller;
use OCA\Richdocuments\Db\DirectMapper;
use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\TemplateManager;
+use OCA\Richdocuments\TokenManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
@@ -38,6 +39,7 @@ use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IRequest;
use OCP\IURLGenerator;
+use OCP\Share\IManager;
class OCSController extends \OCP\AppFramework\OCSController {
@@ -56,20 +58,15 @@ class OCSController extends \OCP\AppFramework\OCSController {
/** @var TemplateManager */
private $manager;
+ /** @var TokenManager */
+ private $tokenManager;
+
+ /** @var IManager */
+ private $shareManager;
+
/** @var FederationService */
private $federationService;
- /**
- * OCS controller
- *
- * @param string $appName
- * @param IRequest $request
- * @param IRootFolder $rootFolder
- * @param string $userId
- * @param DirectMapper $directMapper
- * @param IURLGenerator $urlGenerator
- * @param TemplateManager $manager
- */
public function __construct(string $appName,
IRequest $request,
IRootFolder $rootFolder,
@@ -77,6 +74,8 @@ class OCSController extends \OCP\AppFramework\OCSController {
DirectMapper $directMapper,
IURLGenerator $urlGenerator,
TemplateManager $manager,
+ TokenManager $tokenManager,
+ IManager $shareManager,
FederationService $federationService
) {
parent::__construct($appName, $request);
@@ -86,19 +85,21 @@ class OCSController extends \OCP\AppFramework\OCSController {
$this->directMapper = $directMapper;
$this->urlGenerator = $urlGenerator;
$this->manager = $manager;
+ $this->tokenManager = $tokenManager;
+ $this->shareManager = $shareManager;
$this->federationService = $federationService;
}
/**
* @NoAdminRequired
*
- * Init an editing session
+ * Init a direct editing session
*
* @param int $fileId
* @return DataResponse
* @throws OCSNotFoundException|OCSBadRequestException
*/
- public function create($fileId) {
+ public function createDirect($fileId) {
try {
$userFolder = $this->rootFolder->getUserFolder($this->userId);
$nodes = $userFolder->getById($fileId);
@@ -125,41 +126,86 @@ class OCSController extends \OCP\AppFramework\OCSController {
}
/**
+ * Generate a direct editing link for a file in a public share to open with the current user
+ *
+ * If
+ *
* @NoAdminRequired
- * @param $shareToken
- * @param $path
- * @param $password
- * @param $guestName
- * @param null $remoteUserHost
- * @param null $remoteUserToken
- * @return DataResponse
- * @throws NotFoundException
* @throws OCSForbiddenException
- * @throws \OCP\Share\Exceptions\ShareNotFound
*/
- public function createPublic(string $shareToken, string $path = '', string $password = null, string $guestName = null, $remoteUserHost = null, $remoteUserToken = null) {
- if ($remoteUserHost && $remoteUserToken) {
- // may be optional depending on the requirements
- // fetch user details from remote host
+ public function createPublic(
+ string $shareTokenSourceInstance = null,
+ string $shareToken,
+ string $path = '',
+ string $password = null
+ ): DataResponse {
+ if ($shareTokenSourceInstance) {
+ $remoteCollabora = $this->federationService->getRemoteCollaboraURL($shareTokenSourceInstance);
+ if ($remoteCollabora === '') {
+ throw new OCSNotFoundException('Failed to connect to remote collabora instance.');
+ }
+
+ $wopi = $this->tokenManager->newInitiatorToken($shareTokenSourceInstance, null, $shareToken, true, $this->userId);
+
+ $client = \OC::$server->getHTTPClientService()->newClient();
+ $response = $client->post(rtrim($shareTokenSourceInstance, '/') . '/ocs/v2.php/apps/richdocuments/api/v1/direct/share/initiator?format=json', [
+ 'body' => [
+ 'initiatorServer' => \OC::$server->getURLGenerator()->getAbsoluteURL(''),
+ 'initiatorToken' => $wopi->getToken(),
+ 'shareToken' => $shareToken,
+ 'path' => $path,
+ 'password' => $password
+ ],
+ 'timeout' => 5
+ ]);
+ $url = \json_decode($response->getBody(), true)['ocs']['data']['url'];
+
+ return new DataResponse([
+ 'url' => $url,
+ ]);
}
- $this->shareManager = \OC::$server->getShareManager();
+
$share = $this->shareManager->getShareByToken($shareToken);
- if ($share->getPassword()) {
- if (!$this->shareManager->checkPassword($share, $password)) {
- throw new OCSForbiddenException();
- }
+ if ($share->getPassword() && !$this->shareManager->checkPassword($share, $password)) {
+ throw new OCSForbiddenException();
+ }
+
+ $node = $share->getNode();
+ if ($node instanceof Folder) {
+ $node = $node->get($path);
+ }
+ $direct = $this->directMapper->newDirect($this->userId, $node->getId(), 0, $shareToken);
+
+ return new DataResponse([
+ 'url' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.directView.show', [
+ 'token' => $direct->getToken()
+ ])
+ ]);
+ }
+
+ /**
+ * @PublicPage
+ * @NoCSRFRequired
+ * @throws OCSForbiddenException
+ */
+ public function createPublicFromInitiator(
+ string $initiatorServer,
+ string $initiatorToken,
+ string $shareToken,
+ string $path = '',
+ string $password = null
+ ): DataResponse {
+ $share = $this->shareManager->getShareByToken($shareToken);
+ if ($share->getPassword() && !$this->shareManager->checkPassword($share, $password)) {
+ throw new OCSForbiddenException();
}
+
$node = $share->getNode();
if ($node instanceof Folder) {
- try {
- $node = $node->get($path);
- } catch (NotFoundException $e) {
- throw new OCSForbiddenException();
- }
+ $node = $node->get($path);
}
- // create new direct token and link with either $guestName or remote user info
- $direct = $this->directMapper->newDirect( - );
+ $direct = $this->directMapper->newDirect(null, $node->getId(), null, $shareToken, $initiatorServer, $initiatorToken);
return new DataResponse([
'url' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.directView.show', [
diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php
index 1449844e..5ee267d2 100644
--- a/lib/Controller/WopiController.php
+++ b/lib/Controller/WopiController.php
@@ -26,6 +26,7 @@ use OCA\Richdocuments\AppConfig;
use OCA\Richdocuments\Db\Wopi;
use OCA\Richdocuments\Db\WopiMapper;
use OCA\Richdocuments\Helper;
+use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\Service\UserScopeService;
use OCA\Richdocuments\TemplateManager;
use OCA\Richdocuments\TokenManager;
@@ -76,6 +77,8 @@ class WopiController extends Controller {
private $shareManager;
/** @var UserScopeService */
private $userScopeService;
+ /** @var FederationService */
+ private $federationService;
/** @var IEncryptionManager */
private $encryptionManager;
@@ -112,6 +115,7 @@ class WopiController extends Controller {
TemplateManager $templateManager,
IShareManager $shareManager,
UserScopeService $userScopeService,
+ FederationService $federationService,
IEncryptionManager $encryptionManager
) {
parent::__construct($appName, $request);
@@ -126,6 +130,7 @@ class WopiController extends Controller {
$this->templateManager = $templateManager;
$this->shareManager = $shareManager;
$this->userScopeService = $userScopeService;
+ $this->federationService = $federationService;
$this->encryptionManager = $encryptionManager;
}
@@ -157,10 +162,10 @@ class WopiController extends Controller {
throw new NotFoundException('No valid file found for ' . $fileId);
}
} catch (NotFoundException $e) {
- $this->logger->debug($e->getMessage(), ['app' => 'richdocuments', '']);
+ $this->logger->debug($e->getMessage(), ['app' => 'richdocuments']);
return new JSONResponse([], Http::STATUS_FORBIDDEN);
} catch (DoesNotExistException $e) {
- $this->logger->debug($e->getMessage(), ['app' => 'richdocuments', '']);
+ $this->logger->debug($e->getMessage(), ['app' => 'richdocuments']);
return new JSONResponse([], Http::STATUS_FORBIDDEN);
} catch (\Exception $e) {
$this->logger->logException($e, ['app' => 'richdocuments']);
@@ -179,8 +184,7 @@ class WopiController extends Controller {
'UserId' => !$isPublic ? $wopi->getEditorUid() : $guestUserId,
'OwnerId' => $wopi->getOwnerUid(),
'UserFriendlyName' => $userDisplayName,
- 'UserExtraInfo' => [
- ],
+ 'UserExtraInfo' => [],
'UserCanWrite' => (bool)$wopi->getCanwrite(),
'UserCanNotWriteRelative' => $this->encryptionManager->isEnabled() || $isPublic,
'PostMessageOrigin' => $wopi->getServerHost(),
@@ -198,7 +202,12 @@ class WopiController extends Controller {
'DownloadAsPostMessage' => $wopi->getDirect(),
];
- if ($wopi->isTemplateToken()) {
+ if ($wopi->hasTemplateId()) {
+ $templateUrl = 'index.php/apps/richdocuments/wopi/template/' . $wopi->getTemplateId() . '?access_token=' . $wopi->getToken();
+ $templateUrl = $this->urlGenerator->getAbsoluteURL($templateUrl);
+ $response['TemplateSource'] = $templateUrl;
+ } elseif ($wopi->isTemplateToken()) {
+ // FIXME: Remove backward compatibility layer once TemplateSource is available in all supported Collabora versions
$userFolder = $this->rootFolder->getUserFolder($wopi->getOwnerUid());
$file = $userFolder->getById($wopi->getTemplateDestination())[0];
$response['TemplateSaveAs'] = $file->getName();
@@ -212,7 +221,6 @@ class WopiController extends Controller {
'themingName' => \OC::$server->getThemingDefaults()->getName(),
'userDisplayName' => $userDisplayName,
'email' => $email,
-
];
$watermarkTemplate = $this->appConfig->getAppValue('watermark_text');
$response['WatermarkText'] = preg_replace_callback('/{(.+?)}/', function ($matches) use ($replacements) {
@@ -220,45 +228,58 @@ class WopiController extends Controller {
}, $watermarkTemplate);
}
- /**
- * New approach for generating files from templates by creating an empty file
- * and providing an URL which returns the actual template
- */
- if ($wopi->hasTemplateId()) {
- $templateUrl = 'index.php/apps/richdocuments/wopi/template/' . $wopi->getTemplateId() . '?access_token=' . $wopi->getToken();
- $templateUrl = $this->urlGenerator->getAbsoluteURL($templateUrl);
- $response['TemplateSource'] = $templateUrl;
- }
-
$user = $this->userManager->get($wopi->getEditorUid());
if($user !== null) {
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => 32]);
}
- if (!empty($wopi->getRemoteServer())) {
+ if ($wopi->isRemoteToken()) {
$response = $this->setFederationFileInfo($wopi, $response);
}
return new JSONResponse($response);
}
- private function setFederationFileInfo($wopi, $response) {
- $remoteUserId = $wopi->getGuestDisplayname();
- $cloudID = \OC::$server->getCloudIdManager()->resolveCloudId($remoteUserId);
- $response['UserFriendlyName'] = $cloudID->getDisplayId();
- $response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => explode('@', $remoteUserId)[0], 'size' => 32]);
- $cleanCloudId = str_replace(['http://', 'https://'], '', $cloudID->getId());
- $addressBookEntries = \OC::$server->getContactsManager()->search($cleanCloudId, ['CLOUD']);
- foreach ($addressBookEntries as $entry) {
- if (isset($entry['CLOUD'])) {
- foreach ($entry['CLOUD'] as $cloudID) {
- if ($cloudID === $cleanCloudId) {
- $response['UserFriendlyName'] = $entry['FN'];
- break;
+
+ private function setFederationFileInfo(Wopi $wopi, $response) {
+ if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER) {
+ $remoteUserId = $wopi->getGuestDisplayname();
+ $cloudID = \OC::$server->getCloudIdManager()->resolveCloudId($remoteUserId);
+ $response['UserId'] = $cloudID->getDisplayId();
+ $response['UserFriendlyName'] = $cloudID->getDisplayId();
+ $response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => explode('@', $remoteUserId)[0], 'size' => 32]);
+ $cleanCloudId = str_replace(['http://', 'https://'], '', $cloudID->getId());
+ $addressBookEntries = \OC::$server->getContactsManager()->search($cleanCloudId, ['CLOUD']);
+ foreach ($addressBookEntries as $entry) {
+ if (isset($entry['CLOUD'])) {
+ foreach ($entry['CLOUD'] as $cloudID) {
+ if ($cloudID === $cleanCloudId) {
+ $response['UserFriendlyName'] = $entry['FN'];
+ break;
+ }
}
}
}
+ } else if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST) {
+ $response['UserId'] = 'Guest-' . \OC::$server->getSecureRandom()->generate(8);
+ }
+
+
+ $initiator = $this->federationService->getRemoteFileDetails($wopi->getRemoteServer(), $wopi->getRemoteServerToken());
+ if ($initiator !== null) {
+ if ($initiator->hasTemplateId()) {
+ $templateUrl = $wopi->getRemoteServer() . '/index.php/apps/richdocuments/wopi/template/' . $initiator->getTemplateId() . '?access_token=' . $initiator->getToken();
+ $response['TemplateSource'] = $templateUrl;
+ }
+ if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER) {
+ $response['UserExtraInfo']['avatar'] = $wopi->getRemoteServer() . '/index.php/avatar/' . $initiator->getEditorUid() . '/32';
+ }
+ if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST && $initiator->getEditorUid()) {
+ $response['UserFriendlyName'] = $initiator->getGuestDisplayname() . ' (Guest)';
+ $response['UserExtraInfo']['avatar'] = $wopi->getRemoteServer() . '/index.php/avatar/' . $initiator->getEditorUid() . '/32';
+ }
}
+
return $response;
}
@@ -534,7 +555,7 @@ class WopiController extends Controller {
// Unless the editor is empty (public link) we modify the files as the current editor
$editor = $wopi->getEditorUid();
- if ($editor === null || !empty($wopi->getRemoteServer())) {
+ if ($editor === null || !$wopi->isRemoteToken()) {
$editor = $wopi->getOwnerUid();
}
@@ -673,8 +694,8 @@ class WopiController extends Controller {
private function getFileForWopiToken(Wopi $wopi) {
$file = null;
- if (!empty($wopi->getRemoteServer())) {
- $share = $this->shareManager->getShareByToken($wopi->getEditorUid());
+ if (!empty($wopi->getShare())) {
+ $share = $this->shareManager->getShareByToken($wopi->getShare());
$node = $share->getNode();
if ($node instanceof Folder) {
$file = $node->getById($wopi->getFileid())[0];
diff --git a/lib/Db/Direct.php b/lib/Db/Direct.php
index 92dcbe05..addd77ff 100644
--- a/lib/Db/Direct.php
+++ b/lib/Db/Direct.php
@@ -58,6 +58,15 @@ class Direct extends Entity {
/** @var int */
protected $templateId;
+ /** @var string */
+ protected $share;
+
+ /** @var string */
+ protected $initiatorHost;
+
+ /** @var string */
+ protected $initiatorToken;
+
public function __construct() {
$this->addType('token', 'string');
$this->addType('uid', 'string');
@@ -65,5 +74,8 @@ class Direct extends Entity {
$this->addType('timestamp', 'int');
$this->addType('template_destination', 'int');
$this->addType('template_id', 'int');
+ $this->addType('share', 'string');
+ $this->addType('initiator_host', 'string');
+ $this->addType('initiator_token', 'string');
}
}
diff --git a/lib/Db/DirectMapper.php b/lib/Db/DirectMapper.php
index e3fa8841..f98b2a40 100644
--- a/lib/Db/DirectMapper.php
+++ b/lib/Db/DirectMapper.php
@@ -51,18 +51,21 @@ class DirectMapper extends Mapper {
}
/**
- * @param string $uid
+ * @param string|null $uid
* @param int $fileid
* @param int $destination
* @return Direct
*/
- public function newDirect($uid, $fileid, $destination = null) {
+ public function newDirect($uid, $fileid, $destination = null, $share = null, $initiatorHost = null, $initiatorToken = null) {
$direct = new Direct();
$direct->setUid($uid);
$direct->setFileid($fileid);
$direct->setToken($this->random->generate(64, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER));
$direct->setTimestamp($this->timeFactory->getTime());
$direct->setTemplateDestination($destination);
+ $direct->setShare($share);
+ $direct->setInitiatorHost($initiatorHost);
+ $direct->setInitiatorToken($initiatorToken);
$direct = $this->insert($direct);
return $direct;
diff --git a/lib/Db/Wopi.php b/lib/Db/Wopi.php
index 06763687..11d7d4ed 100644
--- a/lib/Db/Wopi.php
+++ b/lib/Db/Wopi.php
@@ -43,6 +43,12 @@ use OCP\AppFramework\Db\Entity;
* @method string getServerHost()
* @method void setToken(string $token)
* @method string getToken()
+ * @method void setTokenType(int $tokenType)
+ * @method int getTokenType()
+ * @method void setRemoteServer(string $remoteServer)
+ * @method string getRemoteServer()
+ * @method void setRemoteServerToken(string $remoteToken)
+ * @method string getRemoteServerToken()
* @method void setExpiry(int $expiry)
* @method int getExpiry()
* @method void setGuestDisplayname(string $token)
@@ -52,8 +58,10 @@ use OCP\AppFramework\Db\Entity;
* @method void setTemplateId(int $fileId)
* @method int getTemplateId()
* @method void setShare(string $token)
+ * @method string getShare()
+ * @method static Wopi fromParams(array $params)
*/
-class Wopi extends Entity {
+class Wopi extends Entity implements \JsonSerializable {
/**
* WOPI token to open a file as a user on the current instance
@@ -66,19 +74,19 @@ class Wopi extends Entity {
const TOKEN_TYPE_GUEST = 1;
/**
- * WOPI token to open a file as a user from a federated instane
+ * WOPI token to open a file as a user from a federated instance
*/
const TOKEN_TYPE_REMOTE_USER = 2;
/**
- * WOPI token to open a file as a guest from a federated instane
+ * WOPI token to open a file as a guest from a federated instance
*/
const TOKEN_TYPE_REMOTE_GUEST = 3;
/*
- * Temporary token that is used to share the opener details to a federated instance
+ * Temporary token that is used to share the initiator details to the source instance
*/
- const TOKEN_TYPE_FEDERATION = 4;
+ const TOKEN_TYPE_INITIATOR = 4;
/** @var string */
protected $ownerUid;
@@ -157,20 +165,20 @@ class Wopi extends Entity {
}
public function isGuest() {
- return $this->getTokenType() === Wopi::TOKEN_TYPE_GUEST || Wopi::TOKEN_TYPE_REMOTE_GUEST;
+ return $this->getTokenType() === Wopi::TOKEN_TYPE_GUEST || $this->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST;
+ }
+
+ public function isRemoteToken() {
+ return $this->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER || $this->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST;
}
public function getUserForFileAccess() {
- if ($this->share !== null) {
+ if ($this->share !== null || $this->tokenType === self::TOKEN_TYPE_REMOTE_USER || $this->tokenType === self::TOKEN_TYPE_REMOTE_GUEST) {
return $this->getOwnerUid();
}
return $this->isGuest() ? $this->getOwnerUid() : $this->getEditorUid();
}
- public function getCanwrite() {
- return (bool)$this->canwrite;
- }
-
public function getHideDownload() {
return (bool)$this->hideDownload;
}
@@ -179,4 +187,18 @@ class Wopi extends Entity {
return (bool)$this->direct;
}
+ public function jsonSerialize() {
+ $properties = get_object_vars($this);
+ $reflection = new \ReflectionClass($this);
+ $json = [];
+ foreach ($properties as $property => $value) {
+ if (strpos($property, '_') !== 0 && $reflection->hasProperty($property)) {
+ $propertyReflection = $reflection->getProperty($property);
+ if (!$propertyReflection->isPrivate()) {
+ $json[$property] = $this->getter($property);
+ }
+ }
+ }
+ return $json;
+ }
}
diff --git a/lib/Db/WopiMapper.php b/lib/Db/WopiMapper.php
index 056c6078..eeea8041 100644
--- a/lib/Db/WopiMapper.php
+++ b/lib/Db/WopiMapper.php
@@ -64,7 +64,7 @@ class WopiMapper extends Mapper {
* @param int $templateDestination
* @return Wopi
*/
- public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname, $templateDestination = 0, $hideDownload = false, $direct = false, $templateId = 0, $share = null, $tokenType = Wopi::TOKEN_TYPE_USER) {
+ public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname = null, $templateDestination = 0, $hideDownload = false, $direct = false, $templateId = 0, $share = null) {
$token = $this->random->generate(32, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
$wopi = Wopi::fromParams([
@@ -84,7 +84,25 @@ class WopiMapper extends Mapper {
'remoteServer' => '',
'remoteServerToken' => '',
'share' => $share,
- 'tokenType' => $tokenType
+ 'tokenType' => $guestDisplayname === null ? Wopi::TOKEN_TYPE_USER : Wopi::TOKEN_TYPE_GUEST
+ ]);
+
+ /** @var Wopi $wopi */
+ $wopi = $this->insert($wopi);
+
+ return $wopi;
+ }
+
+ public function generateInitiatorToken($uid, $remoteServer) {
+ $token = $this->random->generate(32, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
+
+ $wopi = Wopi::fromParams([
+ 'fileid' => 0,
+ 'editorUid' => $uid,
+ 'token' => $token,
+ 'expiry' => $this->timeFactory->getTime() + self::TOKEN_LIFETIME_SECONDS,
+ 'remoteServer' => $remoteServer,
+ 'tokenType' => Wopi::TOKEN_TYPE_INITIATOR
]);
/** @var Wopi $wopi */
diff --git a/lib/Migration/Version30717Date20210310164901.php b/lib/Migration/Version30717Date20210310164901.php
index 21bb289b..8f4347f1 100644
--- a/lib/Migration/Version30717Date20210310164901.php
+++ b/lib/Migration/Version30717Date20210310164901.php
@@ -28,6 +28,27 @@ class Version30717Date20210310164901 extends SimpleMigrationStep {
$table->dropColumn('is_remote_token');
}
+ $table = $schema->getTable('richdocuments_direct');
+
+ if (!$table->hasColumn('share')) {
+ $table->addColumn('share', 'string', [
+ 'notnull' => false,
+ 'length' => 64
+ ]);
+ }
+ if (!$table->hasColumn('initiator_host')) {
+ $table->addColumn('initiator_host', 'string', [
+ 'notnull' => false,
+ 'length' => 255
+ ]);
+ }
+ if (!$table->hasColumn('initiator_token')) {
+ $table->addColumn('initiator_token', 'string', [
+ 'notnull' => false,
+ 'length' => 64
+ ]);
+ }
+
return $schema;
}
diff --git a/lib/Service/FederationService.php b/lib/Service/FederationService.php
index d07c61f9..fa555c49 100644
--- a/lib/Service/FederationService.php
+++ b/lib/Service/FederationService.php
@@ -26,6 +26,8 @@ namespace OCA\Richdocuments\Service;
use OCA\Federation\TrustedServers;
use OCA\Files_Sharing\External\Storage as SharingExternalStorage;
+use OCA\Richdocuments\Db\Direct;
+use OCA\Richdocuments\Db\Wopi;
use OCA\Richdocuments\TokenManager;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\QueryException;
@@ -38,6 +40,7 @@ use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
+use OCP\Share\IShare;
class FederationService {
@@ -148,33 +151,21 @@ class FederationService {
return $host;
}
- public function getRemoteDirectUrl($remote, $shareToken, $filePath) {
- if ($this->getRemoteCollaboraURL() === '') {
- return '';
+ /** @return Wopi|null */
+ public function getRemoteFileDetails(string $remote, string $remoteToken) {
+ $cacheKey = md5($remote . $remoteToken);
+ $remoteWopi = $this->cache->get($cacheKey);
+ if ($remoteWopi !== null) {
+ return Wopi::fromParams($remoteWopi);
}
- try {
- $client = $this->clientService->newClient();
- $response = $client->post($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation/direct?format=json', [
- 'timeout' => 5,
- 'body' => [
- 'shareToken' => $shareToken,
- 'filePath' => $filePath
- ]
- ]);
- $data = \json_decode($response->getBody(), true);
- return $data['ocs']['data'];
- } catch (\Throwable $e) {
- $this->logger->info('Unable to determine collabora URL of remote server ' . $remote, ['exception' => $e]);
- }
- return null;
- }
- public function getRemoteFileDetails($remote, $remoteToken) {
if (!$this->isTrustedRemote($remote)) {
- $this->logger->info('Unable to determine collabora URL of remote server ' . $remote . ' - Remote is not a trusted server');
+ $this->logger->info('COOL-Federation-Source: Unable to determine collabora URL of remote server ' . $remote . ' for token ' . $remoteToken . ' - Remote is not a trusted server');
return null;
}
+
try {
+ $this->logger->debug('COOL-Federation-Source: Fetching remote file details from ' . $remote . ' for token ' . $remoteToken);
$client = $this->clientService->newClient();
$response = $client->post($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', [
'timeout' => 5,
@@ -184,10 +175,11 @@ class FederationService {
]);
$responseBody = $response->getBody();
$data = \json_decode($responseBody, true, 512);
- $this->logger->debug('Reveived remote file details for ' . $remoteToken . ' from ' . $remote . ': ' . $responseBody);
- return $data['ocs']['data'];
+ $this->logger->debug('COOL-Federation-Source: Received remote file details for ' . $remoteToken . ' from ' . $remote . ': ' . json_encode($data['ocs']['data']));
+ $this->cache->set($cacheKey, $data['ocs']['data']);
+ return Wopi::fromParams($data['ocs']['data']);
} catch (\Throwable $e) {
- $this->logger->error('Unable to fetch remote file details for ' . $remoteToken . ' from ' . $remote, ['exception' => $e]);
+ $this->logger->error('COOL-Federation-Source: Unable to fetch remote file details for ' . $remoteToken . ' from ' . $remote, ['exception' => $e]);
}
return null;
}
@@ -198,26 +190,37 @@ class FederationService {
* @throws NotFoundException
* @throws InvalidPathException
*/
- public function getRemoteRedirectURL(File $item, $direct = null) {
- if ($item->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
- $remote = $item->getStorage()->getRemote();
- $remoteCollabora = $this->getRemoteCollaboraURL($remote);
- if ($remoteCollabora !== '') {
- if ($direct === null) {
- $wopi = $this->tokenManager->getRemoteToken($item);
- } else {
- $wopi = $this->tokenManager->getRemoteTokenFromDirect($item, $direct->getUid());
- }
- $url = rtrim($remote, '/') . '/index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() .
- '&remoteServer=' . $wopi->getServerHost() .
- '&remoteServerToken=' . $wopi->getToken();
- if ($item->getInternalPath() !== '') {
- $url .= '&filePath=' . $item->getInternalPath();
- }
- return $url;
+ public function getRemoteRedirectURL(File $item, Direct $direct = null, IShare $share = null) {
+ if (!$item->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
+ return null;
+ }
+
+ $remote = $item->getStorage()->getRemote();
+ $remoteCollabora = $this->getRemoteCollaboraURL($remote);
+ if ($remoteCollabora !== '') {
+ $shareToken = $share ? $share->getToken() : null;
+
+ $wopi = $this->tokenManager->newInitiatorToken($remote, $item, $shareToken, ($direct !== null), ($direct ? $direct->getUid() : null));
+ $initiatorServer = $wopi->getServerHost();
+ $initiatorToken = $wopi->getToken();
+
+ if ($direct) {
+ //$wopi->setRemoteServer($direct->getInitiatorHost());
+ //$wopi->setRemoteServerToken($direct->getInitiatorToken());
+ // FIXME: the direct token might have a different originator when a share link originating on a federated stoarge is opened
+ // editor uid is null since we don't fetch it from the initiator of direct so @{link remoteWopiToken()} fails
+ // Currently there is no mapping from the initiator user data to the source then
+ }
+
+ $url = rtrim($remote, '/') . '/index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() .
+ '&remoteServer=' . $initiatorServer .
+ '&remoteServerToken=' . $initiatorToken;
+ if ($item->getInternalPath() !== '') {
+ $url .= '&filePath=' . $item->getInternalPath();
}
- throw new NotFoundException('Failed to connect to remote collabora instance for ' . $item->getId());
+ return $url;
}
- return null;
+
+ throw new NotFoundException('Failed to connect to remote collabora instance for ' . $item->getId());
}
}
diff --git a/lib/TokenManager.php b/lib/TokenManager.php
index 5da5c92c..4a7bebd7 100644
--- a/lib/TokenManager.php
+++ b/lib/TokenManager.php
@@ -21,6 +21,7 @@
namespace OCA\Richdocuments;
+use OCA\Richdocuments\Db\Direct;
use OCA\Richdocuments\Db\WopiMapper;
use OCA\Richdocuments\Db\Wopi;
use OCA\Richdocuments\Service\CapabilitiesService;
@@ -33,6 +34,7 @@ use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Share\IManager;
use OCP\IL10N;
+use OCP\Share\IShare;
use OCP\Util;
class TokenManager {
@@ -61,16 +63,6 @@ class TokenManager {
/** @var Helper */
private $helper;
- /**
- * @param IRootFolder $rootFolder
- * @param IManager $shareManager
- * @param IURLGenerator $urlGenerator
- * @param Parser $wopiParser
- * @param AppConfig $appConfig
- * @param string $UserId
- * @param WopiMapper $wopiMapper
- * @param IL10N $trans
- */
public function __construct(
IRootFolder $rootFolder,
IManager $shareManager,
@@ -191,25 +183,24 @@ class TokenManager {
$fp = $file->fopen('r');
fclose($fp);
- $serverHost = $this->urlGenerator->getAbsoluteURL('/');//$this->request->getServerProtocol() . '://' . $this->request->getServerHost();
+ $serverHost = $this->urlGenerator->getAbsoluteURL('/');
- $guest_name = null;
+ $guestName = null;
if ($this->userId === null) {
- if ($guest_name = $this->helper->getGuestName()) {
- $guest_name = $this->trans->t('%s (Guest)', Util::sanitizeHTML($guest_name));
+ if ($guestName = $this->helper->getGuestName()) {
+ $guestName = $this->trans->t('%s (Guest)', Util::sanitizeHTML($guestName));
$cut = 56;
- while (mb_strlen($guest_name) >= 64) {
- $guest_name = $this->trans->t('%s (Guest)', Util::sanitizeHTML(
- mb_substr($guest_name, 0, $cut)
+ while (mb_strlen($guestName) >= 64) {
+ $guestName = $this->trans->t('%s (Guest)', Util::sanitizeHTML(
+ mb_substr($guestName, 0, $cut)
));
$cut -= 5;
}
} else {
- $guest_name = $this->trans->t('Anonymous guest');
+ $guestName = $this->trans->t('Anonymous guest');
}
}
-
- $wopi = $this->wopiMapper->generateFileToken($fileId, $owneruid, $editoruid, $version, $updatable, $serverHost, $guest_name, 0, $hideDownload, $direct, 0, $shareToken);
+ $wopi = $this->wopiMapper->generateFileToken($fileId, $owneruid, $editoruid, $version, $updatable, $serverHost, $guestName, 0, $hideDownload, $direct, 0, $shareToken);
try {
@@ -224,21 +215,33 @@ class TokenManager {
}
/**
- * @param Wopi $wopi
- * @param $shareToken
- * @param $remoteServer
- * @param $remoteServerToken
- * @param $remoteWopi
- * @return Wopi
+ * This method is receiving the results from the TOKEN_TYPE_FEDERATION generated on the opener server
+ * that is created in {@link newInitiatorToken}
*/
- public function updateToFederationToken(Wopi $wopi, $shareToken, $remoteServer, $remoteServerToken, $remoteWopi) {
- // $wopi->setTokenType(Wopi::TOKEN_TYPE_REMOTE_*);
- $uid = $remoteWopi['editorUid'] ? ($remoteWopi['editorUid'] . '@' . $remoteServer) : null;
- $wopi->setEditorUid($shareToken);
- $wopi->setCanwrite($wopi->getCanwrite() && $remoteWopi['canwrite']);
+ public function upgradeToRemoteToken(Wopi $wopi, Wopi $remoteWopi, string $shareToken, string $remoteServer, string $remoteServerToken): Wopi {
+ if ($remoteWopi->getTokenType() !== Wopi::TOKEN_TYPE_INITIATOR) {
+ return $wopi;
+ }
+
+ $remoteTokenType = $remoteWopi->getEditorUid() !== null ? Wopi::TOKEN_TYPE_REMOTE_USER : Wopi::TOKEN_TYPE_REMOTE_GUEST;
+ $wopi->setTokenType($remoteTokenType);
+ if ($remoteTokenType === Wopi::TOKEN_TYPE_REMOTE_USER) {
+ $wopi->setGuestDisplayname($remoteWopi->getEditorUid() . '@' . $remoteServer);
+ }
+ $wopi->setShare($shareToken);
+ $wopi->setCanwrite($wopi->getCanwrite() && $remoteWopi->getCanwrite());
+ $wopi->setHideDownload($wopi->getHideDownload() || $remoteWopi->getHideDownload());
$wopi->setRemoteServer($remoteServer);
$wopi->setRemoteServerToken($remoteServerToken);
- $wopi->setGuestDisplayname($uid);
+ $this->wopiMapper->update($wopi);
+ return $wopi;
+ }
+
+ public function upgradeFromDirectInitiator(Direct $direct, Wopi $wopi) {
+ $wopi->setTokenType(Wopi::TOKEN_TYPE_REMOTE_GUEST);
+ $wopi->setEditorUid(null);
+ $wopi->setRemoteServer($direct->getInitiatorHost());
+ $wopi->setRemoteServerToken($direct->getInitiatorToken());
$this->wopiMapper->update($wopi);
return $wopi;
}
@@ -287,31 +290,16 @@ class TokenManager {
];
}
- /**
- * @param Node $node
- * @return Wopi
- */
- public function getRemoteToken(Node $node) {
- list($urlSrc, $token, $wopi) = $this->getToken($node->getId(), null, null, false);
- $wopi->setIsRemoteToken(true);
- $wopi->setRemoteServer($node->getStorage()->getRemote());
- $wopi->setTokenType(Wopi::TOKEN_TYPE_REMOTE_USER);
- $this->wopiMapper->update($wopi);
- return $wopi;
- }
+ public function newInitiatorToken($sourceServer, Node $node = null, $shareToken = null, bool $direct = false, $userId = null): Wopi {
+ if ($node !== null) {
+ list($urlSrc, $token, $wopi) = $this->getToken($node->getId(), $shareToken, $userId, $direct);
+ $wopi->setServerHost($sourceServer);
+ $wopi->setTokenType(Wopi::TOKEN_TYPE_INITIATOR);
+ $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);
- $wopi->setIsRemoteToken(true);
- $wopi->setRemoteServer($node->getStorage()->getRemote());
- $wopi->setTokenType(Wopi::TOKEN_TYPE_REMOTE_USER);
- $this->wopiMapper->update($wopi);
- return $wopi;
+ return $this->wopiMapper->generateInitiatorToken($this->userId, $sourceServer);
}
-
}