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
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2021-12-29 15:25:47 +0300
committerJulius Härtl <jus@bitgrid.net>2022-01-14 18:07:37 +0300
commitc3237172e0004a1ac51a522fd54de9ba6cec2cf5 (patch)
tree053deace604b14398d811347033b4c2635e9af37
parentd0b6ef883ecb3bbfc7278aa9faad8a20d11f110f (diff)
Fix public link file creation
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r--appinfo/routes.php3
-rw-r--r--lib/Controller/DocumentAPIController.php139
-rw-r--r--lib/Controller/DocumentController.php121
-rw-r--r--lib/TemplateManager.php18
-rw-r--r--src/services/api.js38
-rw-r--r--src/view/NewFileMenu.js33
-rw-r--r--tests/psalm-baseline.xml14
7 files changed, 230 insertions, 136 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 877616dd..57e4edc8 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -34,7 +34,6 @@ return [
['name' => 'document#createFromTemplate', 'url' => 'indexTemplate', 'verb' => 'GET'],
['name' => 'document#publicPage', 'url' => '/public', 'verb' => 'GET'],
- ['name' => 'document#create', 'url' => 'ajax/documents/create', 'verb' => 'POST'],
// external api access
['name' => 'document#extAppGetData', 'url' => '/ajax/extapp/data/{fileId}', 'verb' => 'POST'],
@@ -67,6 +66,8 @@ return [
['name' => 'templates#delete', 'url' => '/template/{fileId}', 'verb' => 'DELETE'],
],
'ocs' => [
+ ['name' => 'documentAPI#create', 'url' => '/api/v1/file', 'verb' => 'POST'],
+
['name' => 'OCS#createDirect', 'url' => '/api/v1/document', 'verb' => 'POST'],
['name' => 'OCS#createPublic', 'url' => '/api/v1/share', 'verb' => 'POST'],
['name' => 'OCS#createPublicFromInitiator', 'url' => '/api/v1/direct/share/initiator', 'verb' => 'POST'],
diff --git a/lib/Controller/DocumentAPIController.php b/lib/Controller/DocumentAPIController.php
new file mode 100644
index 00000000..86cb2081
--- /dev/null
+++ b/lib/Controller/DocumentAPIController.php
@@ -0,0 +1,139 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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/>.
+ *
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Richdocuments\Controller;
+
+use Exception;
+use OCA\Richdocuments\AppInfo\Application;
+use OCA\Richdocuments\Helper;
+use OCA\Richdocuments\TemplateManager;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\Share\IManager;
+use Psr\Log\LoggerInterface;
+use Throwable;
+
+class DocumentAPIController extends \OCP\AppFramework\OCSController {
+
+ private $rootFolder;
+ private $shareManager;
+ private $templateManager;
+ private $l10n;
+ private $logger;
+ private $userId;
+
+ public function __construct(IRequest $request, IRootFolder $rootFolder, IManager $shareManager, TemplateManager $templateManager, IL10N $l10n, LoggerInterface $logger, $userId) {
+ parent::__construct(Application::APPNAME, $request);
+ $this->rootFolder = $rootFolder;
+ $this->shareManager = $shareManager;
+ $this->templateManager = $templateManager;
+ $this->l10n = $l10n;
+ $this->logger = $logger;
+ $this->userId = $userId;
+ }
+
+ /**
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function create(string $mimeType, string $fileName, string $directoryPath = '/', string $shareToken = null): JSONResponse {
+ try {
+ if ($shareToken !== null) {
+ $share = $this->shareManager->getShareByToken($shareToken);
+ }
+
+ $rootFolder = $shareToken !== null ? $share->getNode() : $this->rootFolder->getUserFolder($this->userId);
+ $folder = $rootFolder->get($directoryPath);
+
+ if (!($folder instanceof Folder)) {
+ throw new Exception('Node is not a folder');
+ }
+ } catch (Throwable $e) {
+ $this->logger->error('Failed to create document', ['exception' => $e]);
+ return new JSONResponse([
+ 'status' => 'error',
+ 'message' => $this->l10n->t('Cannot create document')
+ ], Http::STATUS_BAD_REQUEST);
+ }
+
+ $basename = $this->l10n->t('New Document.odt');
+ switch ($mimeType) {
+ case 'application/vnd.oasis.opendocument.spreadsheet':
+ $basename = $this->l10n->t('New Spreadsheet.ods');
+ break;
+ case 'application/vnd.oasis.opendocument.presentation':
+ $basename = $this->l10n->t('New Presentation.odp');
+ break;
+ case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
+ $basename = $this->l10n->t('New Document.docx');
+ break;
+ case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
+ $basename = $this->l10n->t('New Spreadsheet.xlsx');
+ break;
+ case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
+ $basename = $this->l10n->t('New Presentation.pptx');
+ break;
+ default:
+ break;
+ }
+
+ if (!$fileName) {
+ $fileName = Helper::getNewFileName($folder, $basename);
+ }
+
+ if ($folder->nodeExists($fileName)) {
+ return new JSONResponse([
+ 'status' => 'error',
+ 'message' => $this->l10n->t('File already exists')
+ ], Http::STATUS_BAD_REQUEST);
+ }
+
+ try {
+ $file = $folder->newFile($fileName);
+ $templateType = $this->templateManager->getTemplateTypeForExtension(pathinfo($fileName, PATHINFO_EXTENSION));
+ $empty = $this->templateManager->getEmpty($templateType);
+ $templateFile = array_shift($empty);
+ $file->putContent($this->templateManager->getEmptyFileContent($file->getExtension()));
+ if ($this->templateManager->isSupportedTemplateSource($templateFile->getExtension())) {
+ // Only use TemplateSource if supported filetype
+ $this->templateManager->setTemplateSource($file->getId(), $templateFile->getId());
+ }
+ } catch (Exception $e) {
+ $this->logger->error('Failed to create file from template', ['exception' => $e]);
+ return new JSONResponse([
+ 'status' => 'error',
+ 'message' => $this->l10n->t('Not allowed to create document')
+ ], Http::STATUS_BAD_REQUEST);
+ }
+ return new JSONResponse([
+ 'status' => 'success',
+ 'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo())
+ ]);
+ }
+}
diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php
index 8e1932a2..23e1bde5 100644
--- a/lib/Controller/DocumentController.php
+++ b/lib/Controller/DocumentController.php
@@ -11,19 +11,16 @@
namespace OCA\Richdocuments\Controller;
-use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Events\BeforeFederationRedirectEvent;
use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\Service\InitialStateService;
+use OCA\Richdocuments\TemplateManager;
use OCA\Richdocuments\TokenManager;
use \OCP\AppFramework\Controller;
-use OCP\AppFramework\Http;
-use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\Constants;
use OCP\Files\File;
use OCP\Files\Folder;
-use OCP\Files\GenericFileException;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
@@ -36,18 +33,14 @@ use \OCP\AppFramework\Http\ContentSecurityPolicy;
use \OCP\AppFramework\Http\FeaturePolicy;
use \OCP\AppFramework\Http\TemplateResponse;
use \OCA\Richdocuments\AppConfig;
-use \OCA\Richdocuments\Helper;
use OCP\ISession;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
-use OC\Files\Type\TemplateManager;
class DocumentController extends Controller {
/** @var string */
private $uid;
- /** @var IL10N */
- private $l10n;
/** @var IConfig */
private $config;
/** @var AppConfig */
@@ -62,36 +55,30 @@ class DocumentController extends Controller {
private $session;
/** @var IRootFolder */
private $rootFolder;
- /** @var \OCA\Richdocuments\TemplateManager */
+ /** @var TemplateManager */
private $templateManager;
/** @var FederationService */
private $federationService;
/** @var InitialStateService */
private $initialState;
- const ODT_TEMPLATE_PATH = '/emptyTemplates/odttemplate.odt';
-
-
public function __construct(
$appName,
IRequest $request,
IConfig $config,
AppConfig $appConfig,
- IL10N $l10n,
IManager $shareManager,
TokenManager $tokenManager,
IRootFolder $rootFolder,
ISession $session,
$UserId,
ILogger $logger,
- \OCA\Richdocuments\TemplateManager $templateManager,
+ TemplateManager $templateManager,
FederationService $federationService,
- Helper $helper,
InitialStateService $initialState
) {
parent::__construct($appName, $request);
$this->uid = $UserId;
- $this->l10n = $l10n;
$this->config = $config;
$this->appConfig = $appConfig;
$this->shareManager = $shareManager;
@@ -501,108 +488,6 @@ class DocumentController extends Controller {
return new TemplateResponse('core', '403', [], 'guest');
}
- /**
- * @NoAdminRequired
- *
- * @param string $mimetype
- * @param string $filename
- * @param string $dir
- * @return JSONResponse
- * @throws NotPermittedException
- * @throws GenericFileException
- */
- public function create($mimetype,
- $filename,
- $dir = '/'){
-
- $root = $this->rootFolder->getUserFolder($this->uid);
- try {
- /** @var Folder $folder */
- $folder = $root->get($dir);
- } catch (NotFoundException $e) {
- return new JSONResponse([
- 'status' => 'error',
- 'message' => $this->l10n->t('Cannot create document')
- ], Http::STATUS_BAD_REQUEST);
- }
-
- if (!($folder instanceof Folder)) {
- return new JSONResponse([
- 'status' => 'error',
- 'message' => $this->l10n->t('Cannot create document')
- ], Http::STATUS_BAD_REQUEST);
- }
-
- $basename = $this->l10n->t('New Document.odt');
- switch ($mimetype) {
- case 'application/vnd.oasis.opendocument.spreadsheet':
- $basename = $this->l10n->t('New Spreadsheet.ods');
- break;
- case 'application/vnd.oasis.opendocument.presentation':
- $basename = $this->l10n->t('New Presentation.odp');
- break;
- case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
- $basename = $this->l10n->t('New Document.docx');
- break;
- case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
- $basename = $this->l10n->t('New Spreadsheet.xlsx');
- break;
- case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
- $basename = $this->l10n->t('New Presentation.pptx');
- break;
- default:
- // to be safe
- $mimetype = 'application/vnd.oasis.opendocument.text';
- break;
- }
-
- if (!$filename){
- $filename = Helper::getNewFileName($folder, $basename);
- }
-
- if ($folder->nodeExists($filename)) {
- return new JSONResponse([
- 'status' => 'error',
- 'message' => $this->l10n->t('Document already exists')
- ], Http::STATUS_BAD_REQUEST);
- }
-
- try {
- $file = $folder->newFile($filename);
- } catch (NotPermittedException $e) {
- return new JSONResponse([
- 'status' => 'error',
- 'message' => $this->l10n->t('Not allowed to create document')
- ], Http::STATUS_BAD_REQUEST);
- }
-
- $content = '';
- if (class_exists(TemplateManager::class)){
- $manager = \OC_Helper::getFileTemplateManager();
- $content = $manager->getTemplate($mimetype);
- }
-
- if (!$content){
- // FIXME: see if this is used,
- $content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH);
- }
-
- if ($content) {
- $file->putContent($content);
-
- return new JSONResponse([
- 'status' => 'success',
- 'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo())
- ]);
- }
-
-
- return new JSONResponse([
- 'status' => 'error',
- 'message' => $this->l10n->t('Cannot create document')
- ]);
- }
-
private function renderErrorPage($message) {
$params = [
'errors' => [['error' => $message]]
diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php
index 1f4d1499..803f8be9 100644
--- a/lib/TemplateManager.php
+++ b/lib/TemplateManager.php
@@ -197,6 +197,24 @@ class TemplateManager {
});
}
+ public function getTemplateTypeForExtension(string $extension): ?string {
+ switch ($extension) {
+ case 'odt':
+ case 'docx':
+ return 'document';
+ case 'ods':
+ case 'xlsx':
+ return 'spreadsheet';
+ case 'odp':
+ case 'pptx':
+ return 'presentation';
+ case 'odg':
+ return 'drawing';
+ }
+
+ return null;
+ }
+
public function getEmpty($type = null) {
$folder = $this->getEmptyTemplateDir();
diff --git a/src/services/api.js b/src/services/api.js
new file mode 100644
index 00000000..cd5d98ad
--- /dev/null
+++ b/src/services/api.js
@@ -0,0 +1,38 @@
+/*
+ * @copyright Copyright (c) 2021 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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/>.
+ *
+ */
+
+import axios from '@nextcloud/axios'
+import { generateOcsUrl } from '@nextcloud/router'
+
+export const createEmptyFile = async(mimeType, fileName) => {
+ const shareToken = document.getElementById('sharingToken')?.value
+ const directoryPath = document.getElementById('dir')?.value
+
+ const response = await axios.post(generateOcsUrl('apps/richdocuments/api/v1', 2) + 'file', {
+ mimeType,
+ fileName,
+ directoryPath,
+ shareToken,
+ })
+
+ return response.data
+}
diff --git a/src/view/NewFileMenu.js b/src/view/NewFileMenu.js
index d713864a..5402d1ff 100644
--- a/src/view/NewFileMenu.js
+++ b/src/view/NewFileMenu.js
@@ -21,6 +21,9 @@
*/
import Types from '../helpers/types'
+import { createEmptyFile } from '../services/api'
+
+const isPublic = window.document.getElementById('isPublic')?.value === '1'
/** @type OC.Plugin */
const NewFileMenu = {
@@ -37,7 +40,7 @@ const NewFileMenu = {
iconClass: 'icon-filetype-document',
fileType: 'x-office-document',
actionHandler(filename) {
- if (OC.getCapabilities().richdocuments.templates) {
+ if (!isPublic && OC.getCapabilities().richdocuments.templates) {
self._openTemplatePicker('document', document.mime, filename)
} else {
self._createDocument(document.mime, filename)
@@ -52,7 +55,7 @@ const NewFileMenu = {
iconClass: 'icon-filetype-spreadsheet',
fileType: 'x-office-spreadsheet',
actionHandler(filename) {
- if (OC.getCapabilities().richdocuments.templates) {
+ if (!isPublic && OC.getCapabilities().richdocuments.templates) {
self._openTemplatePicker('spreadsheet', spreadsheet.mime, filename)
} else {
self._createDocument(spreadsheet.mime, filename)
@@ -67,7 +70,7 @@ const NewFileMenu = {
iconClass: 'icon-filetype-presentation',
fileType: 'x-office-presentation',
actionHandler(filename) {
- if (OC.getCapabilities().richdocuments.templates) {
+ if (!isPublic && OC.getCapabilities().richdocuments.templates) {
self._openTemplatePicker('presentation', presentation.mime, filename)
} else {
self._createDocument(presentation.mime, filename)
@@ -80,17 +83,21 @@ const NewFileMenu = {
OCA.Files.Files.isFileNameValid(filename)
filename = FileList.getUniqueName(filename)
- $.post(
- OC.generateUrl('apps/richdocuments/ajax/documents/create'),
- { mimetype, filename, dir: document.getElementById('dir').value },
- function(response) {
- if (response && response.status === 'success') {
- FileList.add(response.data, { animate: true, scrollTo: true })
- } else {
- OC.dialogs.alert(response.data.message, t('core', 'Could not create file'))
- }
+ createEmptyFile(mimetype, filename).then((response) => {
+ if (response && response.status === 'success') {
+ FileList.add(response.data, { animate: true, scrollTo: true })
+ const fileModel = FileList.getModelForFile(filename)
+ const fileAction = OCA.Files.fileActions.getDefaultFileAction(fileModel.get('mimetype'), 'file', OC.PERMISSION_ALL)
+ fileAction.action(filename, {
+ $file: null,
+ dir: FileList.getCurrentDirectory(),
+ FileList,
+ fileActions: FileList.fileActions,
+ })
+ } else {
+ OC.dialogs.alert(response.data.message, t('core', 'Could not create file'))
}
- )
+ })
},
_createDocumentFromTemplate(templateId, mimetype, filename) {
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
index d705ac7a..9e44e9d3 100644
--- a/tests/psalm-baseline.xml
+++ b/tests/psalm-baseline.xml
@@ -59,6 +59,14 @@
<code>IRootFolder</code>
</MissingDependency>
</file>
+ <file src="lib/Controller/DocumentAPIController.php">
+ <MissingDependency occurrences="1">
+ <code>IRootFolder</code>
+ </MissingDependency>
+ <UndefinedClass occurrences="1">
+ <code>\OCA\Files\Helper</code>
+ </UndefinedClass>
+ </file>
<file src="lib/Controller/DocumentController.php">
<InvalidScalarArgument occurrences="5">
<code>$fileId</code>
@@ -67,8 +75,7 @@
<code>$item-&gt;getId()</code>
<code>$node-&gt;getId()</code>
</InvalidScalarArgument>
- <MissingDependency occurrences="8">
- <code>$this-&gt;rootFolder</code>
+ <MissingDependency occurrences="7">
<code>$this-&gt;rootFolder</code>
<code>$this-&gt;rootFolder</code>
<code>$this-&gt;rootFolder</code>
@@ -80,9 +87,8 @@
<RedundantCondition occurrences="1">
<code>$app !== ''</code>
</RedundantCondition>
- <UndefinedClass occurrences="2">
+ <UndefinedClass occurrences="1">
<code>\OCA\Files_Sharing\External\Storage</code>
- <code>\OC_Helper</code>
</UndefinedClass>
<UndefinedInterfaceMethod occurrences="1">
<code>getRemote</code>