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:
authorRoeland Jago Douma <rullzer@users.noreply.github.com>2018-12-20 09:58:55 +0300
committerGitHub <noreply@github.com>2018-12-20 09:58:55 +0300
commitc7becd4ee8cd0e3cdd742ca7fc54ad164ec65c70 (patch)
tree68462abedf9dbab617dd461affd843a29ba9a395 /lib
parentf2b8d73472b6ef936eaaba3f93f0c987b7c21da9 (diff)
parent2beab3e864ef46aadf2a5e4e910559b09787dec7 (diff)
Merge pull request #263 from nextcloud/templates-manager
Template management
Diffstat (limited to 'lib')
-rw-r--r--lib/AppInfo/Application.php20
-rw-r--r--lib/Controller/DirectViewController.php46
-rw-r--r--lib/Controller/DocumentController.php55
-rw-r--r--lib/Controller/OCSController.php96
-rw-r--r--lib/Controller/SettingsController.php43
-rw-r--r--lib/Controller/TemplatesController.php216
-rw-r--r--lib/Controller/WopiController.php137
-rw-r--r--lib/Db/Direct.php6
-rw-r--r--lib/Db/DirectMapper.php4
-rw-r--r--lib/Db/Wopi.php10
-rw-r--r--lib/Db/WopiMapper.php6
-rw-r--r--lib/Settings/Admin.php38
-rw-r--r--lib/Settings/Personal.php78
-rw-r--r--lib/TemplateManager.php456
-rw-r--r--lib/TokenManager.php32
15 files changed, 1183 insertions, 60 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 83ba668d..4d5d49c3 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -2,6 +2,9 @@
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
@@ -15,27 +18,26 @@
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Richdocuments\AppInfo;
-use OC\AppFramework\Utility\TimeFactory;
+use OC\Files\Type\Detection;
use OCA\Richdocuments\Capabilities;
use OCA\Richdocuments\Preview\MSExcel;
use OCA\Richdocuments\Preview\MSWord;
use OCA\Richdocuments\Preview\OOXML;
use OCA\Richdocuments\Preview\OpenDocument;
use OCP\AppFramework\App;
-use OCP\AppFramework\IAppContainer;
use OCP\IPreview;
-class Application extends App {
+class Application extends App {
const APPNAME = 'richdocuments';
- public function __construct (array $urlParams = array()) {
+ public function __construct(array $urlParams = array()) {
parent::__construct(self::APPNAME, $urlParams);
$this->getContainer()->registerCapability(Capabilities::class);
@@ -44,6 +46,14 @@ class Application extends App {
public function registerProvider() {
$container = $this->getContainer();
+ // Register mimetypes
+ /** @var Detection $detector */
+ $detector = $container->query(\OCP\Files\IMimeTypeDetector::class);
+ $detector->getAllMappings();
+ $detector->registerType('ott','application/vnd.oasis.opendocument.text-template');
+ $detector->registerType('ots', 'application/vnd.oasis.opendocument.spreadsheet-template');
+ $detector->registerType('otp', 'application/vnd.oasis.opendocument.presentation-template');
+
/** @var IPreview $previewManager */
$previewManager = $container->query(IPreview::class);
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/DocumentController.php b/lib/Controller/DocumentController.php
index 7219114a..a11399d3 100644
--- a/lib/Controller/DocumentController.php
+++ b/lib/Controller/DocumentController.php
@@ -52,9 +52,12 @@ class DocumentController extends Controller {
private $session;
/** @var IRootFolder */
private $rootFolder;
+ /** @var \OCA\Richdocuments\TemplateManager */
+ private $templateManager;
const ODT_TEMPLATE_PATH = '/assets/odttemplate.odt';
+
/**
* @param string $appName
* @param IRequest $request
@@ -78,7 +81,8 @@ class DocumentController extends Controller {
IRootFolder $rootFolder,
ISession $session,
$UserId,
- ILogger $logger) {
+ ILogger $logger,
+ \OCA\Richdocuments\TemplateManager $templateManager) {
parent::__construct($appName, $request);
$this->uid = $UserId;
$this->l10n = $l10n;
@@ -89,6 +93,7 @@ class DocumentController extends Controller {
$this->rootFolder = $rootFolder;
$this->session = $session;
$this->logger = $logger;
+ $this->templateManager = $templateManager;
}
/**
@@ -225,6 +230,54 @@ class DocumentController extends Controller {
}
/**
+ * @NoAdminRequired
+ *
+ * @param int $templateId
+ * @param string $fileName
+ * @param string $dir
+ * @return TemplateResponse
+ */
+ public function template($templateId, $fileName, $dir) {
+ if (!$this->templateManager->isTemplate($templateId)) {
+ return new TemplateResponse('core', '403', [], 'guest');
+ }
+
+ $userFolder = $this->rootFolder->getUserFolder($this->uid);
+ try {
+ $folder = $userFolder->get($dir);
+ } catch (NotFoundException $e) {
+ return new TemplateResponse('core', '403', [], 'guest');
+ }
+
+ if ((!$folder instanceof Folder)) {
+ return new TemplateResponse('core', '403', [], 'guest');
+ }
+
+ $file = $folder->newFile($fileName);
+
+ $template = $this->templateManager->get($templateId);
+ list($urlSrc, $token) = $this->tokenManager->getTokenForTemplate($template, $this->uid, $file->getId());
+
+ $params = [
+ 'permissions' => $template->getPermissions(),
+ 'title' => $template->getName(),
+ 'fileId' => $template->getId() . '_' . $this->settings->getSystemValue('instanceid'),
+ 'token' => $token,
+ 'urlsrc' => $urlSrc,
+ 'path' => $userFolder->getRelativePath($file->getPath()),
+ 'instanceId' => $this->settings->getSystemValue('instanceid'),
+ 'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
+ ];
+
+ $response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
+ $policy = new ContentSecurityPolicy();
+ $policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('wopi_url')));
+ $policy->allowInlineScript(true);
+ $response->setContentSecurityPolicy($policy);
+ return $response;
+ }
+
+ /**
* @PublicPage
*
* @param string $shareToken
diff --git a/lib/Controller/OCSController.php b/lib/Controller/OCSController.php
index 14651409..cbb93c73 100644
--- a/lib/Controller/OCSController.php
+++ b/lib/Controller/OCSController.php
@@ -3,6 +3,7 @@
* @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
@@ -23,9 +24,11 @@
namespace OCA\Richdocuments\Controller;
use OCA\Richdocuments\Db\DirectMapper;
+use OCA\Richdocuments\TemplateManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSNotFoundException;
+use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
@@ -33,6 +36,7 @@ use OCP\IRequest;
use OCP\IURLGenerator;
class OCSController extends \OCP\AppFramework\OCSController {
+
/** @var IRootFolder */
private $rootFolder;
@@ -45,32 +49,52 @@ class OCSController extends \OCP\AppFramework\OCSController {
/** @var IURLGenerator */
private $urlGenerator;
- public function __construct($appName,
- IRequest $request,
- IRootFolder $rootFolder,
- $userId,
- DirectMapper $directMapper,
- IURLGenerator $urlGenerator) {
+ /** @var TemplateManager */
+ private $manager;
+
+ /**
+ * 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,
+ $userId,
+ DirectMapper $directMapper,
+ IURLGenerator $urlGenerator,
+ TemplateManager $manager) {
parent::__construct($appName, $request);
- $this->rootFolder = $rootFolder;
- $this->userId = $userId;
+ $this->rootFolder = $rootFolder;
+ $this->userId = $userId;
$this->directMapper = $directMapper;
$this->urlGenerator = $urlGenerator;
+ $this->manager = $manager;
}
/**
* @NoAdminRequired
*
+ * Init an editing session
+ *
* @param int $fileId
+ * @return DataResponse
+ * @throws OCSNotFoundException|OCSBadRequestException
*/
public function create($fileId) {
try {
$userFolder = $this->rootFolder->getUserFolder($this->userId);
- $nodes = $userFolder->getById($fileId);
+ $nodes = $userFolder->getById($fileId);
if ($nodes === []) {
- throw new NotFoundException();
+ throw new OCSNotFoundException();
}
$node = $nodes[0];
@@ -79,7 +103,7 @@ class OCSController extends \OCP\AppFramework\OCSController {
}
//TODO check if we can even edit this file with collabora
-
+
$direct = $this->directMapper->newDirect($this->userId, $fileId);
return new DataResponse([
@@ -91,4 +115,54 @@ class OCSController extends \OCP\AppFramework\OCSController {
throw new OCSNotFoundException();
}
}
+
+ /**
+ * @NoAdminRequired
+ *
+ * @param string $type The template type
+ * @return DataResponse
+ * @throws OCSBadRequestException
+ */
+ public function getTemplates($type) {
+ if (array_key_exists($type, TemplateManager::$tplTypes)) {
+ $templates = $this->manager->getAllFormatted($type);
+ return new DataResponse($templates);
+ }
+ throw new OCSBadRequestException('Wrong type');
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @param string $path Where to create the document
+ * @param int $template The template id
+ */
+ public function createFromTemplate($path, $template) {
+ if ($path === null || $template === null) {
+ throw new OCSBadRequestException('path and template must be set');
+ }
+
+ if (!$this->manager->isTemplate($template)) {
+ throw new OCSBadRequestException('Invalid template provided');
+ }
+
+ $info = pathinfo($path);
+
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ $folder = $userFolder->get($info['dirname']);
+ $name = $folder->getNonExistingName($info['basename']);
+ $file = $folder->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/SettingsController.php b/lib/Controller/SettingsController.php
index 2d7222f3..122cf116 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -17,31 +17,43 @@ use OCP\AppFramework\Http\JSONResponse;
use \OCP\IRequest;
use \OCP\IL10N;
use OCA\Richdocuments\AppConfig;
+use OCP\IConfig;
+use OCP\PreConditionNotMetException;
class SettingsController extends Controller{
/** @var IL10N */
private $l10n;
/** @var AppConfig */
private $appConfig;
+ /** @var IConfig */
+ private $config;
/** @var DiscoveryManager */
private $discoveryManager;
+ /** @var string */
+ private $userId;
/**
* @param string $appName
* @param IRequest $request
* @param IL10N $l10n
* @param AppConfig $appConfig
+ * @param IConfig $config
* @param DiscoveryManager $discoveryManager
+ * @param string $userId
*/
public function __construct($appName,
IRequest $request,
IL10N $l10n,
AppConfig $appConfig,
- DiscoveryManager $discoveryManager) {
+ IConfig $config,
+ DiscoveryManager $discoveryManager,
+ $userId) {
parent::__construct($appName, $request);
$this->l10n = $l10n;
$this->appConfig = $appConfig;
+ $this->config = $config;
$this->discoveryManager = $discoveryManager;
+ $this->userId = $userId;
}
/**
@@ -113,4 +125,33 @@ class SettingsController extends Controller{
return new JSONResponse($response);
}
+
+ /**
+ * @NoAdminRequired
+ *
+ * @param $key
+ * @param $value
+ * @return JSONResponse
+ */
+ public function setPersonalSettings($templateFolder) {
+ $message = $this->l10n->t('Saved');
+ $status = 'success';
+
+ if ($templateFolder !== null){
+ try {
+ $this->config->setUserValue($this->userId, 'richdocuments', 'templateFolder', $templateFolder);
+ } catch (PreConditionNotMetException $e) {
+ $message = $this->l10n->t('Error when saving');
+ $status = 'error';
+ }
+ }
+
+ $response = [
+ 'status' => $status,
+ 'data' => ['message' => $message]
+ ];
+
+ return new JSONResponse($response);
+
+ }
}
diff --git a/lib/Controller/TemplatesController.php b/lib/Controller/TemplatesController.php
new file mode 100644
index 00000000..548c3528
--- /dev/null
+++ b/lib/Controller/TemplatesController.php
@@ -0,0 +1,216 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Richdocuments\Controller;
+
+use OCA\Richdocuments\TemplateManager;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\FileDisplayResponse;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\NotFoundResponse;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IL10N;
+use OCP\IPreview;
+use OCP\IRequest;
+use OC\Files\Filesystem;
+
+class TemplatesController extends Controller {
+ /** @var IL10N */
+ private $l10n;
+
+ /** @var TemplateManager */
+ private $manager;
+
+ /** @var IPreview */
+ private $preview;
+
+ /** @var int Max template size */
+ private $maxSize = 20 * 1024 * 1024;
+
+ /**
+ * Templates controller
+ *
+ * @param string $appName
+ * @param IRequest $request
+ * @param L10N $l10n
+ * @param TemplateManager $manager
+ * @param IPreview $preview
+ */
+ public function __construct($appName,
+ IRequest $request,
+ IL10N $l10n,
+ TemplateManager $manager,
+ IPreview $preview) {
+ parent::__construct($appName, $request);
+
+ $this->appName = $appName;
+ $this->request = $request;
+ $this->l10n = $l10n;
+ $this->manager = $manager;
+ $this->preview = $preview;
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * Get preview for a specific template
+ *
+ * @param int $fileId The template id
+ * @param int $x
+ * @param int $y
+ * @param bool $a
+ * @param bool $forceIcon
+ * @param string $mode
+ * @return DataResponse
+ * @throws NotFoundResponse
+ */
+ public function getPreview($fileId,
+ $x = 150,
+ $y = 150,
+ $a = false,
+ $forceIcon = true,
+ $mode = 'fill') {
+
+ if ($fileId === '' || $x === 0 || $y === 0) {
+ return new DataResponse([], Http::STATUS_BAD_REQUEST);
+ }
+
+ try {
+ $template = $this->manager->get($fileId);
+ } catch (NotFoundException $e) {
+ return new DataResponse([], Http::STATUS_NOT_FOUND);
+ }
+
+ if ($template instanceof ISimpleFile) {
+ return new DataResponse([], Http::STATUS_NOT_FOUND);
+ }
+
+ return $this->fetchPreview($template, $x, $y, $a, $forceIcon, $mode);
+ }
+
+ /**
+ * Add a global template
+ *
+ * @return JSONResponse
+ */
+ public function add() {
+ $files = $this->request->getUploadedFile('files');
+
+ if (!is_null($files)) {
+ if ($files['error'][0] === 0
+ && is_uploaded_file($files['tmp_name'][0])
+ && !Filesystem::isFileBlacklisted($files['tmp_name'][0])) {
+
+ // TODO: ensure the size limit is decent for preview
+ if ($files['size'][0] > $this->maxSize) {
+ return new JSONResponse(
+ ['data' => ['message' => $this->l10n->t('File is too big')]],
+ Http::STATUS_BAD_REQUEST
+ );
+ }
+
+ $templateName = $files['name'][0];
+ $templateFile = file_get_contents($files['tmp_name'][0]);
+
+ unlink($files['tmp_name'][0]);
+
+ $template = $this->manager->add($templateName, $templateFile);
+
+ return new JSONResponse(
+ ['data' => $template],
+ Http::STATUS_CREATED
+ );
+ }
+ }
+
+ return new JSONResponse(
+ ['data' => ['message' => $this->l10n->t('Invalid file provided')]],
+ Http::STATUS_BAD_REQUEST
+ );
+ }
+
+ /**
+ * Delete a global template
+ *
+ * @param int $fileId
+ * @return JSONResponse
+ */
+ public function delete($fileId) {
+ try {
+ $this->manager->delete($fileId);
+
+ return new JSONResponse(
+ ['data' => ['status' => 'success']],
+ Http::STATUS_NO_CONTENT
+ );
+ } catch (NotFoundException $e) {
+ return new JSONResponse(
+ ['data' => ['message' => $this->l10n->t('Template not found')]],
+ Http::STATUS_NOT_FOUND
+ );
+ }
+ }
+
+ /**
+ * @param Node $node
+ * @param int $x
+ * @param int $y
+ * @param bool $a
+ * @param bool $forceIcon
+ * @param string $mode
+ * @return DataResponse|FileDisplayResponse
+ */
+ private function fetchPreview(
+ Node $node,
+ $x,
+ $y,
+ $a = false,
+ $forceIcon = true,
+ string $mode): Http\Response {
+
+ if (!($node instanceof Node) || (!$forceIcon && !$this->preview->isAvailable($node))) {
+ return new DataResponse([], Http::STATUS_NOT_FOUND);
+ }
+ if (!$node->isReadable()) {
+ return new DataResponse([], Http::STATUS_FORBIDDEN);
+ }
+
+ try {
+ $f = $this->preview->getPreview($node, $x, $y, !$a, $mode);
+ $response = new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
+ $response->cacheFor(3600 * 24);
+
+ return $response;
+ } catch (NotFoundException $e) {
+ return new DataResponse([], Http::STATUS_NOT_FOUND);
+ } catch (\InvalidArgumentException $e) {
+ return new DataResponse([], Http::STATUS_BAD_REQUEST);
+ }
+ }
+}
diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php
index 13bf5655..9ef12282 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,13 +57,14 @@ 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;
/**
* @param string $appName
- * @param string $UserId
* @param IRequest $request
* @param IRootFolder $rootFolder
* @param IURLGenerator $urlGenerator
@@ -71,9 +73,10 @@ class WopiController extends Controller {
* @param IUserManager $userManager
* @param WopiMapper $wopiMapper
* @param ILogger $logger
+ * @param IUserSession $userSession
+ * @param TemplateManager $templateManager
*/
public function __construct($appName,
- $UserId,
IRequest $request,
IRootFolder $rootFolder,
IURLGenerator $urlGenerator,
@@ -82,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;
@@ -92,6 +96,7 @@ class WopiController extends Controller {
$this->wopiMapper = $wopiMapper;
$this->logger = $logger;
$this->userSession = $userSession;
+ $this->templateManager = $templateManager;
}
/**
@@ -102,26 +107,32 @@ 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()) {
+ $this->templateManager->setUserId($wopi->getOwnerUid());
+ $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)) {
@@ -145,12 +156,15 @@ 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]);
- }
+ if ($wopi->isTemplateToken()) {
+ $userFolder = $this->rootFolder->getUserFolder($wopi->getOwnerUid());
+ $file = $userFolder->getById($wopi->getTemplateDestination())[0];
+ $response['TemplateSaveAs'] = $file->getName();
+ }
+
+ $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);
@@ -177,6 +191,16 @@ class WopiController extends Controller {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
+ // Template is just returned as there is no version logic
+ if ($wopi->isTemplateToken()) {
+ $this->templateManager->setUserId($wopi->getOwnerUid());
+ $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());
@@ -329,6 +353,77 @@ class WopiController extends Controller {
*/
public function putRelativeFile($fileId,
$access_token) {
- return $this->putFile($fileId, $access_token);
+ list($fileId, ,) = Helper::parseFileId($fileId);
+ $wopi = $this->wopiMapper->getPathForToken($access_token);
+
+ if (!$wopi->getCanwrite()) {
+ return new JSONResponse([], Http::STATUS_FORBIDDEN);
+ }
+
+ // Unless the editor is empty (public link) we modify the files as the current editor
+ $editor = $wopi->getEditorUid();
+ if ($editor === null) {
+ $editor = $wopi->getOwnerUid();
+ }
+
+ try {
+ // the new file needs to be installed in the current user dir
+ $userFolder = $this->rootFolder->getUserFolder($editor);
+
+ if ($wopi->isTemplateToken()) {
+ $this->templateManager->setUserId($wopi->getOwnerUid());
+ $file = $userFolder->getById($wopi->getTemplateDestination())[0];
+ } else {
+ $file = $userFolder->getById($fileId)[0];
+
+ $suggested = $this->request->getHeader('X-WOPI-SuggestedTarget');
+ $suggested = iconv('utf-7', 'utf-8', $suggested);
+
+ if ($suggested[0] === '.') {
+ $path = dirname($file->getPath()) . '/New File' . $suggested;
+ } else if ($suggested[0] !== '/') {
+ $path = dirname($file->getPath()) . '/' . $suggested;
+ } else {
+ $path = $userFolder->getPath() . $suggested;
+ }
+
+ if ($path === '') {
+ return new JSONResponse([
+ 'status' => 'error',
+ 'message' => 'Cannot create the file'
+ ]);
+ }
+
+ // create the folder first
+ if (!$this->rootFolder->nodeExists(dirname($path))) {
+ $this->rootFolder->newFolder(dirname($path));
+ }
+
+ // create a unique new file
+ $path = $this->rootFolder->getNonExistingName($path);
+ $file = $this->rootFolder->newFile($path);
+ }
+
+ $content = fopen('php://input', 'rb');
+
+ // Set the user to register the change under his name
+ $editor = $this->userManager->get($wopi->getEditorUid());
+ if (!is_null($editor)) {
+ $this->userSession->setUser($editor);
+ }
+
+ $file->putContent($content);
+
+ // generate a token for the new file (the user still has to be
+ // logged in)
+ list(, $wopiToken) = $this->tokenManager->getToken($file->getId(), null, $wopi->getEditorUid());
+
+ $wopi = 'index.php/apps/richdocuments/wopi/files/' . $file->getId() . '_' . $this->config->getSystemValue('instanceid') . '?access_token=' . $wopiToken;
+ $url = $this->urlGenerator->getAbsoluteURL($wopi);
+
+ return new JSONResponse([ 'Name' => $file->getName(), 'Url' => $url ], Http::STATUS_OK);
+ } catch (\Exception $e) {
+ return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
}
}
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 90f29f96..941e241b 100644
--- a/lib/Db/Wopi.php
+++ b/lib/Db/Wopi.php
@@ -47,6 +47,8 @@ use OCP\AppFramework\Db\Entity;
* @method int getExpiry()
* @method void setGuestDisplayname(string $token)
* @method string getGuestDisplayname()
+ * @method void setTemplateDestination(int $fileId)
+ * @method int getTemplateDestination()
*/
class Wopi extends Entity {
/** @var string */
@@ -76,6 +78,9 @@ class Wopi extends Entity {
/** @var string */
protected $guestDisplayname;
+ /** @var int */
+ protected $templateDestination;
+
public function __construct() {
$this->addType('owner_uid', 'string');
$this->addType('editor_uid', 'string');
@@ -86,6 +91,11 @@ class Wopi extends Entity {
$this->addType('token', 'string');
$this->addType('expiry', 'int');
$this->addType('guest_displayname', 'string');
+ $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 a9c4f18b..01dfded3 100644
--- a/lib/Db/WopiMapper.php
+++ b/lib/Db/WopiMapper.php
@@ -56,14 +56,15 @@ 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
* @param string $guestDisplayname
+ * @param int $templateDestination
* @return Wopi
*/
- public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname) {
+ public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname, $templateDestination = 0) {
$token = $this->random->generate(32, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
$wopi = Wopi::fromParams([
@@ -76,6 +77,7 @@ class WopiMapper extends Mapper {
'token' => $token,
'expiry' => $this->timeFactory->getTime() + self::TOKEN_LIFETIME_SECONDS,
'guestDisplayname' => $guestDisplayname,
+ 'templateDestination' => $templateDestination,
]);
/** @var Wopi $wopi */
diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php
index 0bad4f7c..00a5e8c1 100644
--- a/lib/Settings/Admin.php
+++ b/lib/Settings/Admin.php
@@ -23,20 +23,36 @@
namespace OCA\Richdocuments\Settings;
+use OCA\Richdocuments\Capabilities;
+use OCA\Richdocuments\TemplateManager;
use OCP\AppFramework\Http\TemplateResponse;
-use OCP\Defaults;
use OCP\IConfig;
-use OCP\IL10N;
use OCP\Settings\ISettings;
class Admin implements ISettings {
+
/** @var IConfig */
private $config;
+
+ /** @var TemplateManager */
+ private $manager;
+
+ /** @var array */
+ private $capabilities;
+
/**
+ * Admin template settings
+ *
* @param IConfig $config
+ * @param TemplateManager $manager
+ * @param Capabilities $capabilities
*/
- public function __construct(IConfig $config) {
- $this->config = $config;
+ public function __construct(IConfig $config,
+ TemplateManager $manager,
+ Capabilities $capabilities) {
+ $this->config = $config;
+ $this->manager = $manager;
+ $this->capabilities = $capabilities->getCapabilities()['richdocuments'];
}
/**
* @return TemplateResponse
@@ -46,12 +62,14 @@ class Admin implements ISettings {
'richdocuments',
'admin',
[
- 'wopi_url' => $this->config->getAppValue('richdocuments', 'wopi_url'),
- 'edit_groups' => $this->config->getAppValue('richdocuments', 'edit_groups'),
- 'use_groups' => $this->config->getAppValue('richdocuments', 'use_groups'),
- 'doc_format' => $this->config->getAppValue('richdocuments', 'doc_format'),
- 'external_apps' => $this->config->getAppValue('richdocuments', 'external_apps'),
- 'canonical_webroot' => $this->config->getAppValue('richdocuments', 'canonical_webroot'),
+ 'wopi_url' => $this->config->getAppValue('richdocuments', 'wopi_url'),
+ 'edit_groups' => $this->config->getAppValue('richdocuments', 'edit_groups'),
+ 'use_groups' => $this->config->getAppValue('richdocuments', 'use_groups'),
+ 'doc_format' => $this->config->getAppValue('richdocuments', 'doc_format'),
+ 'external_apps' => $this->config->getAppValue('richdocuments', 'external_apps'),
+ 'canonical_webroot' => $this->config->getAppValue('richdocuments', 'canonical_webroot'),
+ 'templates' => $this->manager->getSystemFormatted(),
+ 'templatesAvailable' => array_key_exists('templates', $this->capabilities) && $this->capabilities['templates']
],
'blank'
);
diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php
new file mode 100644
index 00000000..3aa80803
--- /dev/null
+++ b/lib/Settings/Personal.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Richdocuments\Settings;
+
+use OCA\Richdocuments\Capabilities;
+use OCA\Richdocuments\TemplateManager;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\Settings\ISettings;
+
+class Personal implements ISettings {
+
+ private $config;
+ private $userId;
+ private $capabilities;
+
+ public function __construct(IConfig $config, Capabilities $capabilities, $userId) {
+ $this->config = $config;
+ $this->capabilities = $capabilities->getCapabilities()['richdocuments'];
+ $this->userId = $userId;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ if (array_key_exists('templates', $this->capabilities) && $this->capabilities['templates'] === true) {
+ return new TemplateResponse(
+ 'richdocuments',
+ 'personal',
+ [
+ 'templateFolder' => $this->config->getUserValue($this->userId, 'richdocuments', 'templateFolder', '')
+ ],
+ 'blank'
+ );
+ }
+ }
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ // Only show the personal section if templates are available
+ if (array_key_exists('templates', $this->capabilities) && $this->capabilities['templates'] === true) {
+ return 'richdocuments';
+ }
+ }
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * keep the server setting at the top, right after "server settings"
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php
new file mode 100644
index 00000000..19a7d4cb
--- /dev/null
+++ b/lib/TemplateManager.php
@@ -0,0 +1,456 @@
+<?php
+declare (strict_types = 1);
+/**
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Richdocuments;
+
+use OCP\Files\File;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\IPreview;
+use OCP\IURLGenerator;
+use OC\Files\AppData\Factory;
+
+class TemplateManager {
+
+ /** @var string */
+ protected $appName;
+
+ /** @var string */
+ protected $userId;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var IRootFolder */
+ private $rootFolder;
+
+ /** @var IL10N */
+ private $l;
+
+ /** Accepted templates mime types */
+ const MIMES_DOCUMENTS = [
+ 'application/vnd.oasis.opendocument.text-template'
+ ];
+ const MIMES_SHEETS = [
+ 'application/vnd.oasis.opendocument.spreadsheet-template'
+ ];
+ const MIMES_PRESENTATIONS = [
+ 'application/vnd.oasis.opendocument.presentation-template'
+ ];
+
+ /** @var array Template mime types match */
+ static public $tplTypes = [
+ 'document' => self::MIMES_DOCUMENTS,
+ 'spreadsheet' => self::MIMES_SHEETS,
+ 'presentation' => self::MIMES_PRESENTATIONS
+ ];
+
+ const EMPTY_TEMPLATE_ID_TYPE = [
+ -1 => 'document',
+ -2 => 'spreadsheet',
+ -3 => 'presentation',
+ ];
+ const EMPTY_TEMPLATE_TYPE_ID = [
+ 'document' => -1,
+ 'spreadsheet' => -2,
+ 'presentation' => -3,
+ ];
+ const TYPE_EXTENTION = [
+ 'document' => 'odt',
+ 'spreadsheet' => 'ods',
+ 'presentation' => 'odp',
+ ];
+
+
+ /**
+ * Template manager
+ *
+ * @param string $appName
+ * @param string $userId
+ * @param IConfig $config
+ * @param Factory $appDataFactory
+ * @param IURLGenerator $urlGenerator
+ * @param IRootFolder $rootFolder
+ * @param IL10N $l
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function __construct($appName,
+ $userId,
+ IConfig $config,
+ Factory $appDataFactory,
+ IURLGenerator $urlGenerator,
+ IRootFolder $rootFolder,
+ IL10N $l) {
+ $this->appName = $appName;
+ $this->userId = $userId;
+ $this->config = $config;
+ $this->rootFolder = $rootFolder;
+ $this->urlGenerator = $urlGenerator;
+
+ /*
+ * Init the appdata folder
+ * We need an actual folder for the fileid and previews.
+ * TODO: Fix this at some point
+ */
+ $appData = $appDataFactory->get($appName);
+ try {
+ $appData->getFolder('templates');
+ } catch (NotFoundException $e) {
+ $appData->newFolder('templates');
+ }
+ try {
+ $appData->getFolder('empty_templates');
+ } catch (NotFoundException $e) {
+ $appData->newFolder('empty_templates');
+ }
+
+ $this->l = $l;
+ }
+
+ public function setUserId($userId) {
+ $this->userId = $userId;
+ }
+
+ /**
+ * Get template ISimpleFile|Node
+ *
+ * @param int $fileId
+ * @return File
+ */
+ public function get($fileId) {
+ // is this a global template ?
+ $files = $this->getEmptyTemplateDir()->getDirectoryListing();
+
+ foreach ($files as $file) {
+ if ($file->getId() === $fileId) {
+ return $file;
+ }
+ }
+
+ // is this a global template ?
+ $files = $this->getSystemTemplateDir()->getDirectoryListing();
+
+ foreach ($files as $file) {
+ if ($file->getId() === $fileId) {
+ return $file;
+ }
+ }
+
+ $templateDir = $this->getUserTemplateDir();
+ // finally get the template file
+ $files = $templateDir->getById($fileId);
+ if ($files !== []) {
+ return $files[0];
+ }
+
+ throw new NotFoundException();
+ }
+
+ /**
+ * @param File[] $templates
+ * @return File[]
+ */
+ private function filterTemplates($templates, $type = null) {
+ return array_filter($templates, function (Node $templateFile) use ($type) {
+ if (!($templateFile instanceof File)) {
+ return false;
+ }
+
+ if ($type !== null && !in_array($templateFile->getMimeType(), self::$tplTypes[$type])) {
+ return false;
+ }
+
+ //Todo validate mimetypes etc
+
+ return true;
+ });
+ }
+
+ private function getEmpty($type = null) {
+ $folder = $this->getEmptyTemplateDir();
+
+ $templateFiles = $folder->getDirectoryListing();
+
+ if ($templateFiles === []) {
+ // Empty so lets copy over the basic templates
+ $templates = [
+ 'document.ott',
+ 'spreadsheet.ots',
+ 'presentation.otp',
+ ];
+
+ foreach ($templates as $template) {
+ $file = $folder->newFile($template);
+ $file->putContent(file_get_contents(__DIR__ . '/../assets/' . $template));
+ $templateFiles[] = $file;
+ }
+ }
+
+ return $this->filterTemplates($templateFiles, $type);
+ }
+
+ /**
+ * Get all global templates
+ *
+ * @return File[]
+ */
+ public function getSystem($type = null) {
+ $folder = $this->getSystemTemplateDir();
+
+ $templateFiles = $folder->getDirectoryListing();
+ return $this->filterTemplates($templateFiles, $type);
+ }
+
+ /**
+ * @return array
+ */
+ public function getSystemFormatted($type = null) {
+ $empty = $this->getEmpty($type);
+ $system = $this->getSystem($type);
+
+ $emptyFormatted = array_map(function(File $file) {
+ return $this->formatEmpty($file);
+ }, $empty);
+
+ $systemFormatted = array_map(function(File $file) {
+ return $this->formatNodeReturn($file);
+ }, $system);
+
+ return array_merge($emptyFormatted, $systemFormatted);
+ }
+
+ /**
+ * Get all user templates
+ *
+ * @return File[]
+ */
+ public function getUser($type = null) {
+ try {
+ $templateDir = $this->getUserTemplateDir();
+ $templateFiles = $templateDir->getDirectoryListing();
+
+ return $this->filterTemplates($templateFiles, $type);
+ } catch(NotFoundException $e) {
+ return [];
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getUserFormatted($type) {
+ $templates = $this->getUser($type);
+
+ return array_map(function(File $file) {
+ return $this->formatNodeReturn($file);
+ }, $templates);
+ }
+
+ /**
+ * Get all templates
+ *
+ * @return File[]
+ */
+ public function getAll($type = 'document') {
+ $system = $this->getSystem();
+ $user = $this->getUser();
+
+ if (!array_key_exists($type, self::$tplTypes)) {
+ return [];
+ }
+
+ return array_values(array_filter(array_merge($user, $system), function (File $template) use ($type) {
+ foreach (self::$tplTypes[$type] as $mime) {
+ if ($template->getMimeType() === $mime) {
+ return true;
+ }
+ }
+ return false;
+ }));
+ }
+
+ public function getAllFormatted($type) {
+ if (!array_key_exists($type, self::$tplTypes)) {
+ return [];
+ }
+
+ $system = $this->getSystemFormatted($type);
+ $user = $this->getUserFormatted($type);
+
+ return array_merge($system, $user);
+ }
+
+ /**
+ * Add a template to the global template folder
+ *
+ * @param string $templateName
+ * @param string $templateFile
+ * @return array
+ */
+ public function add($templateName, $templateFile) {
+ $folder = $this->getSystemTemplateDir();
+
+ try {
+ $template = $folder->get($templateName);
+ } catch (NotFoundException $e) {
+ $template = $folder->newFile($templateName);
+ }
+ $template->putContent($templateFile);
+
+ return $this->formatNodeReturn($this->get($template->getId()));
+ }
+
+ /**
+ * Delete a template to the global template folder
+ *
+ * @param int $fileId
+ * @return boolean
+ * @throws NotFoundException
+ */
+ public function delete($fileId) {
+ $files = $this->getSystemTemplateDir()->getDirectoryListing();
+ foreach ($files as $file) {
+ if ($file->getId() === $fileId) {
+ $file->delete();
+ return true;
+ }
+ }
+
+ throw new NotFoundException();
+ }
+
+ /**
+ * Flip $tplTypes to retrieve types by mime
+ *
+ * @return array
+ */
+ private function flipTypes() {
+ $result = [];
+ foreach ($this::$tplTypes as $type => $mime) {
+ $result = array_merge($result, array_fill_keys($mime, $type));
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get the user template directory
+ *
+ * @return Folder
+ * @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 ?
+ $templateDirPath = $this->config->getUserValue($this->userId, $this->appName, 'templateFolder', false);
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+
+ if ($templateDirPath !== false) {
+ $templateDir = $userFolder->get($templateDirPath);
+ } else {
+ // fallback to default template dir
+ try {
+ $templateDir = $userFolder->get('Templates');
+ } catch (NotFoundException $e) {
+ throw new NotFoundException($e->getMessage());
+ }
+ }
+
+ if (!($templateDir instanceof Folder)) {
+ throw new NotFoundException('Template dir points to a file');
+ }
+
+ return $templateDir;
+ }
+
+ /**
+ * @return Folder
+ */
+ private function getSystemTemplateDir() {
+ return $this->rootFolder->get('appdata_' . $this->config->getSystemValue('instanceid', null))
+ ->get('richdocuments')
+ ->get('templates');
+ }
+
+ /**
+ * @return Folder
+ */
+ private function getEmptyTemplateDir() {
+ return $this->rootFolder->get('appdata_' . $this->config->getSystemValue('instanceid', null))
+ ->get('richdocuments')
+ ->get('empty_templates');
+ }
+
+ /**
+ * Format template file for json return object
+ *
+ * @param File $template
+ * @return array
+ */
+ public function formatNodeReturn(File $template) {
+ return [
+ 'id' => $template->getId(),
+ 'name' => $template->getName(),
+ 'preview' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.templates.getPreview', ['fileId' => $template->getId()]),
+ 'type' => $this->flipTypes()[$template->getMimeType()],
+ 'delete' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.templates.delete', ['fileId' => $template->getId()]),
+ 'extension' => self::TYPE_EXTENTION[$this->flipTypes()[$template->getMimeType()]],
+ ];
+ }
+
+ public function isTemplate($fileId) {
+ $empty = $this->getEmpty();
+ $system = $this->getSystem();
+ $user = $this->getUser();
+ /** @var File[] $all */
+ $all = array_merge($empty, $system, $user);
+
+ foreach ($all as $template) {
+ if ($template->getId() === $fileId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function formatEmpty(File $template) {
+ return [
+ 'id' => $template->getId(),
+ 'name' => $this->l->t('Empty'),
+ 'type' => $this->flipTypes()[$template->getMimeType()],
+ 'extension' => self::TYPE_EXTENTION[$this->flipTypes()[$template->getMimeType()]],
+ ];
+ }
+}
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(),
+ ];
+ }
}