diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2018-10-08 21:44:52 +0300 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2018-12-20 09:38:44 +0300 |
commit | c5df57dfccd2c18bb09d5a57f47bb515ab363a02 (patch) | |
tree | 7d80147d26b96aa84286d0065e4f5477c2e56576 | |
parent | cb6c9315cfe8a6dcd62a16180601a6bfa235e4c6 (diff) |
Open template via OCS (Direct view)
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
-rw-r--r-- | appinfo/database.xml | 6 | ||||
-rw-r--r-- | lib/Controller/DirectViewController.php | 46 | ||||
-rw-r--r-- | lib/Controller/OCSController.php | 20 | ||||
-rw-r--r-- | lib/Controller/WopiController.php | 54 | ||||
-rw-r--r-- | lib/Db/Direct.php | 6 | ||||
-rw-r--r-- | lib/Db/DirectMapper.php | 4 | ||||
-rw-r--r-- | lib/Db/Wopi.php | 6 | ||||
-rw-r--r-- | lib/Db/WopiMapper.php | 2 | ||||
-rw-r--r-- | lib/TemplateManager.php | 35 | ||||
-rw-r--r-- | lib/TokenManager.php | 32 |
10 files changed, 179 insertions, 32 deletions
diff --git a/appinfo/database.xml b/appinfo/database.xml index 5f94bcbf..9d19a070 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -177,6 +177,12 @@ <length>4</length> <default>0</default> </field> + <field> + <name>template_destination</name> + <type>integer</type> + <notnull>false</notnull> + <length>4</length> + </field> <index> <name>rd_direct_token_idx</name> diff --git a/lib/Controller/DirectViewController.php b/lib/Controller/DirectViewController.php index 2ba8d64f..9ce2d2d3 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\TemplateManager; use OCA\Richdocuments\TokenManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Db\DoesNotExistException; @@ -52,13 +53,17 @@ class DirectViewController extends Controller { /** @var AppConfig */ private $appConfig; + /** @var TemplateManager */ + private $templateManager; + public function __construct($appName, IRequest $request, IRootFolder $rootFolder, TokenManager $tokenManager, DirectMapper $directMapper, IConfig $config, - AppConfig $appConfig) { + AppConfig $appConfig, + TemplateManager $templateManager) { parent::__construct($appName, $request); $this->rootFolder = $rootFolder; @@ -66,6 +71,7 @@ class DirectViewController extends Controller { $this->directMapper = $directMapper; $this->config = $config; $this->appConfig = $appConfig; + $this->templateManager = $templateManager; } /** @@ -86,20 +92,44 @@ class DirectViewController extends Controller { // Delete the token. They are for 1 time use only $this->directMapper->delete($direct); - try { - $folder = $this->rootFolder->getUserFolder($direct->getUid()); - $item = $folder->getById($direct->getFileid())[0]; - if(!($item instanceof Node)) { - throw new \Exception(); + $folder = $this->rootFolder->getUserFolder($direct->getUid()); + if ($this->templateManager->isTemplate($direct->getFileid())) { + $item = $this->templateManager->get($direct->getFileid()); + if ($direct->getTemplateDestination() === 0 || $direct->getTemplateDestination() === null) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + + try { + list($urlSrc, $token) = $this->tokenManager->getTokenForTemplate($item, $direct->getUid(), $direct->getTemplateDestination()); + } catch (\Exception $e) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + + $relativePath = '/new.odt'; + + } else { + try { + $item = $folder->getById($direct->getFileid())[0]; + if(!($item instanceof Node)) { + throw new \Exception(); + } + + list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), null, $direct->getUid()); + } catch (\Exception $e) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); } - list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), null, $direct->getUid()); + + $relativePath = $folder->getRelativePath($item->getPath()); + } + + try { $params = [ 'permissions' => $item->getPermissions(), 'title' => $item->getName(), 'fileId' => $item->getId() . '_' . $this->config->getSystemValue('instanceid'), 'token' => $token, 'urlsrc' => $urlSrc, - 'path' => $folder->getRelativePath($item->getPath()), + 'path' => $relativePath, 'instanceId' => $this->config->getSystemValue('instanceid'), 'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'), 'direct' => true, diff --git a/lib/Controller/OCSController.php b/lib/Controller/OCSController.php index 966aae2d..13ec1c8d 100644 --- a/lib/Controller/OCSController.php +++ b/lib/Controller/OCSController.php @@ -143,5 +143,25 @@ class OCSController extends \OCP\AppFramework\OCSController { * @param int $template The template id */ public function createFromTemplate(string $path, int $template) { + if (!$this->manager->isTemplate($template)) { + throw new OCSBadRequestException('Invalid template provided'); + } + + // TODO use actual path + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $name = $userFolder->getNonExistingName('new document.odt'); + $file = $userFolder->newFile($name); + + try { + $direct = $this->directMapper->newDirect($this->userId, $template, $file->getId()); + + return new DataResponse([ + 'url' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.directView.show', [ + 'token' => $direct->getToken() + ]) + ]); + } catch (NotFoundException $e) { + throw new OCSNotFoundException(); + } } } diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php index 93088930..13b9525c 100644 --- a/lib/Controller/WopiController.php +++ b/lib/Controller/WopiController.php @@ -23,6 +23,7 @@ namespace OCA\Richdocuments\Controller; use OC\Files\View; use OCA\Richdocuments\Db\WopiMapper; +use OCA\Richdocuments\TemplateManager; use OCA\Richdocuments\TokenManager; use OCA\Richdocuments\Helper; use OCP\AppFramework\Controller; @@ -56,6 +57,8 @@ class WopiController extends Controller { private $logger; /** @var IUserSession */ private $userSession; + /** @var TemplateManager */ + private $templateManager; // Signifies LOOL that document has been changed externally in this storage const LOOL_STATUS_DOC_CHANGED = 1010; @@ -70,6 +73,8 @@ class WopiController extends Controller { * @param IUserManager $userManager * @param WopiMapper $wopiMapper * @param ILogger $logger + * @param IUserSession $userSession + * @param TemplateManager $templateManager */ public function __construct($appName, IRequest $request, @@ -80,7 +85,8 @@ class WopiController extends Controller { IUserManager $userManager, WopiMapper $wopiMapper, ILogger $logger, - IUserSession $userSession) { + IUserSession $userSession, + TemplateManager $templateManager) { parent::__construct($appName, $request); $this->rootFolder = $rootFolder; $this->urlGenerator = $urlGenerator; @@ -90,6 +96,7 @@ class WopiController extends Controller { $this->wopiMapper = $wopiMapper; $this->logger = $logger; $this->userSession = $userSession; + $this->templateManager = $templateManager; } /** @@ -100,26 +107,31 @@ class WopiController extends Controller { * @PublicPage * * @param string $fileId + * @param string $access_token * @return JSONResponse + * @throws \OCP\Files\InvalidPathException + * @throws \OCP\Files\NotFoundException */ - public function checkFileInfo($fileId) { - $token = $this->request->getParam('access_token'); - + public function checkFileInfo($fileId, $access_token) { list($fileId, , $version) = Helper::parseFileId($fileId); try { - $wopi = $this->wopiMapper->getPathForToken($token); + $wopi = $this->wopiMapper->getPathForToken($access_token); } catch (DoesNotExistException $e) { return new JSONResponse([], Http::STATUS_FORBIDDEN); } - // Login the user to see his mount locations - try { - /** @var File $file */ - $userFolder = $this->rootFolder->getUserFolder($wopi->getOwnerUid()); - $file = $userFolder->getById($fileId)[0]; - } catch (\Exception $e) { - return new JSONResponse([], Http::STATUS_FORBIDDEN); + if ($wopi->isTemplateToken()) { + $file = $this->templateManager->get($wopi->getFileid()); + } else { + // Login the user to see his mount locations + try { + /** @var File $file */ + $userFolder = $this->rootFolder->getUserFolder($wopi->getOwnerUid()); + $file = $userFolder->getById($fileId)[0]; + } catch (\Exception $e) { + return new JSONResponse([], Http::STATUS_FORBIDDEN); + } } if(!($file instanceof File)) { @@ -143,12 +155,9 @@ class WopiController extends Controller { 'EnableShare' => true, ]; - $serverVersion = $this->config->getSystemValue('version'); - if (version_compare($serverVersion, '13', '>=')) { - $user = $this->userManager->get($wopi->getEditorUid()); - if($user !== null && $user->getAvatarImage(32) !== null) { - $response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => 32]); - } + $user = $this->userManager->get($wopi->getEditorUid()); + if($user !== null && $user->getAvatarImage(32) !== null) { + $response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => 32]); } return new JSONResponse($response); @@ -175,6 +184,15 @@ class WopiController extends Controller { return new JSONResponse([], Http::STATUS_FORBIDDEN); } + // Template is just returned as there is no version logic + if ($wopi->isTemplateToken()) { + $file = $this->templateManager->get($wopi->getFileid()); + $response = new StreamResponse($file->fopen('rb')); + $response->addHeader('Content-Disposition', 'attachment'); + $response->addHeader('Content-Type', 'application/octet-stream'); + return $response; + } + try { /** @var File $file */ $userFolder = $this->rootFolder->getUserFolder($wopi->getOwnerUid()); diff --git a/lib/Db/Direct.php b/lib/Db/Direct.php index 26c29672..437df370 100644 --- a/lib/Db/Direct.php +++ b/lib/Db/Direct.php @@ -34,6 +34,8 @@ use OCP\AppFramework\Db\Entity; * @method int getFileid() * @method void setTimestamp(int $timestamp) * @method int getTimestamp() + * @method void setTemplateDestination(int $fileId) + * @method int getTemplateDestination() */ class Direct extends Entity { /** @var string */ @@ -48,10 +50,14 @@ class Direct extends Entity { /** @var int */ protected $timestamp; + /** @var int */ + protected $templateDestination; + public function __construct() { $this->addType('token', 'string'); $this->addType('uid', 'string'); $this->addType('fileid', 'int'); $this->addType('timestamp', 'int'); + $this->addType('template_destination', 'int'); } } diff --git a/lib/Db/DirectMapper.php b/lib/Db/DirectMapper.php index dd414e2b..e3fa8841 100644 --- a/lib/Db/DirectMapper.php +++ b/lib/Db/DirectMapper.php @@ -53,14 +53,16 @@ class DirectMapper extends Mapper { /** * @param string $uid * @param int $fileid + * @param int $destination * @return Direct */ - public function newDirect($uid, $fileid) { + public function newDirect($uid, $fileid, $destination = 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 = $this->insert($direct); return $direct; diff --git a/lib/Db/Wopi.php b/lib/Db/Wopi.php index 9f0ecaaf..941e241b 100644 --- a/lib/Db/Wopi.php +++ b/lib/Db/Wopi.php @@ -91,7 +91,11 @@ class Wopi extends Entity { $this->addType('token', 'string'); $this->addType('expiry', 'int'); $this->addType('guest_displayname', 'string'); - $this->addType('template_destination', 'int'); + $this->addType('templateDestination', 'int'); + } + + public function isTemplateToken() { + return $this->getTemplateDestination() !== 0 && $this->getTemplateDestination() !== null; } } diff --git a/lib/Db/WopiMapper.php b/lib/Db/WopiMapper.php index 3bf06492..01dfded3 100644 --- a/lib/Db/WopiMapper.php +++ b/lib/Db/WopiMapper.php @@ -56,7 +56,7 @@ class WopiMapper extends Mapper { /** * @param int $fileId * @param string $owner - * @param string$editor + * @param string $editor * @param int $version * @param bool $updatable * @param string $serverHost diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php index 5f169a62..0db4465e 100644 --- a/lib/TemplateManager.php +++ b/lib/TemplateManager.php @@ -80,8 +80,8 @@ class TemplateManager { * @param IRootFolder $rootFolder * @param IPreview $previewManager */ - public function __construct(string $appName, - string $userId, + public function __construct($appName, + $userId, IConfig $config, Factory $appDataFactory, IURLGenerator $urlGenerator, @@ -131,6 +131,10 @@ class TemplateManager { throw new NotFoundException(); } + /** + * @param File[] $templates + * @return File[] + */ private function filterTemplates($templates) { return array_filter($templates, function (Node $templateFile) { if (!($templateFile instanceof File)) { @@ -155,6 +159,9 @@ class TemplateManager { return $this->filterTemplates($templateFiles); } + /** + * @return array + */ public function getSystemFormatted() { $templates = $this->getSystem(); @@ -166,7 +173,7 @@ class TemplateManager { /** * Get all user templates * - * @return array + * @return File[] */ public function getUser() { try { @@ -179,6 +186,9 @@ class TemplateManager { } } + /** + * @return array + */ public function getUserFormatted() { $templates = $this->getUser(); @@ -270,6 +280,10 @@ class TemplateManager { * @throws NotFoundException */ private function getUserTemplateDir() { + if ($this->userId === null) { + throw new NotFoundException('userId not set'); + } + // has the user manually set a directory as the default template dir ? $templateDirID = $this->config->getUserValue($this->userId, $this->appName, 'template_dir', false); $userFolder = $this->rootFolder->getUserFolder($this->userId); @@ -317,4 +331,19 @@ class TemplateManager { 'delete' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.templates.delete', ['fileId' => $template->getId()]) ]; } + + public function isTemplate($fileId) { + $system = $this->getSystem(); + $user = $this->getUser(); + /** @var File[] $all */ + $all = array_merge($system, $user); + + foreach ($all as $template) { + if ($template->getId() === $fileId) { + return true; + } + } + + return false; + } } diff --git a/lib/TokenManager.php b/lib/TokenManager.php index f11b1873..98707420 100644 --- a/lib/TokenManager.php +++ b/lib/TokenManager.php @@ -81,6 +81,7 @@ class TokenManager { /** * @param string $fileId * @param string $shareToken + * @param string $editoruid * @return array * @throws \Exception */ @@ -152,4 +153,35 @@ class TokenManager { throw $e; } } + + public function getTokenForTemplate(File $file, $userId, $templateDestination) { + $owneruid = $userId; + $editoruid = $userId; + $rootFolder = $this->rootFolder->getUserFolder($editoruid); + $updatable = $rootFolder->isUpdateable(); + // Check if the editor (user who is accessing) is in editable group + // UserCanWrite only if + // 1. No edit groups are set or + // 2. if they are set, it is in one of the edit groups + $editGroups = array_filter(explode('|', $this->appConfig->getAppValue('edit_groups'))); + if ($updatable && count($editGroups) > 0) { + $updatable = false; + foreach($editGroups as $editGroup) { + $editorGroup = \OC::$server->getGroupManager()->get($editGroup); + if ($editorGroup !== null && sizeof($editorGroup->searchUsers($editoruid)) > 0) { + $updatable = true; + break; + } + } + } + + $serverHost = $this->urlGenerator->getAbsoluteURL('/'); + + $wopi = $this->wopiMapper->generateFileToken($file->getId(), $owneruid, $editoruid, 0, (int)$updatable, $serverHost, null, $templateDestination); + + return [ + $this->wopiParser->getUrlSrc($file->getMimeType())['urlsrc'], + $wopi->getToken(), + ]; + } } |