From e52793c69ef3633f23a93f4358c361431f401569 Mon Sep 17 00:00:00 2001 From: Julius Härtl Date: Mon, 14 Oct 2019 16:55:39 +0200 Subject: Direct editing API to allow file editing using a one-time token for mobile apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/private/DirectEditing/Manager.php | 232 ++++++++++++++++++++++++++++++++++ lib/private/DirectEditing/Token.php | 76 +++++++++++ lib/private/Server.php | 2 + 3 files changed, 310 insertions(+) create mode 100644 lib/private/DirectEditing/Manager.php create mode 100644 lib/private/DirectEditing/Token.php (limited to 'lib/private') diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php new file mode 100644 index 00000000000..085a7de557a --- /dev/null +++ b/lib/private/DirectEditing/Manager.php @@ -0,0 +1,232 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OC\DirectEditing; + +use Doctrine\DBAL\FetchMode; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DirectEditing\ACreateFromTemplate; +use OCP\DirectEditing\IEditor; +use \OCP\DirectEditing\IManager; +use OCP\DirectEditing\IToken; +use OCP\Files\File; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\IDBConnection; +use OCP\IUserSession; +use OCP\Security\ISecureRandom; +use OCP\Share\IShare; + +class Manager implements IManager { + + private const TOKEN_CLEANUP_TIME = 12 * 60 * 60 ; + + public const TABLE_TOKENS = 'direct_edit'; + + /** @var IEditor[] */ + private $editors; + + /** @var IDBConnection */ + private $connection; + /** + * @var ISecureRandom + */ + private $random; + private $userId; + private $rootFolder; + + public function __construct( + ISecureRandom $random, + IDBConnection $connection, + IUserSession $userSession, + IRootFolder $rootFolder + ) { + $this->random = $random; + $this->connection = $connection; + $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null; + $this->rootFolder = $rootFolder; + } + + public function registerDirectEditor(IEditor $directEditor): void { + $this->editors[$directEditor->getId()] = $directEditor; + } + + public function getEditors(): array { + return $this->editors; + } + + public function getTemplates(string $editor, string $type): array { + if (!array_key_exists($editor, $this->editors)) { + throw new \RuntimeException('No matching editor found'); + } + $templates = []; + foreach ($this->editors[$editor]->getCreators() as $creator) { + if ($creator instanceof ACreateFromTemplate && $creator->getId() === $type) { + $templates = $creator->getTemplates(); + } + } + return $templates; + } + + public function create(string $path, string $editorId, string $creatorId, $templateId = null): string { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $file = $userFolder->newFile($path); + $editor = $this->getEditor($editorId); + $creators = $editor->getCreators(); + foreach ($creators as $creator) { + if ($creator->getId() === $creatorId) { + $creator->create($file, $creatorId, $templateId); + return $this->createToken($editorId, $file); + } + } + throw new \RuntimeException('No creator found'); + } + + public function open(int $fileId, string $editorId = null): string { + $file = $this->rootFolder->getUserFolder($this->userId)->getById($fileId); + if (count($file) === 0 || !($file[0] instanceof File) || $file === null) { + throw new NotFoundException(); + } + /** @var File $file */ + $file = $file[0]; + + if ($editorId === null) { + $editorId = $this->findEditorForFile($file); + } + + return $this->createToken($editorId, $file); + } + + private function findEditorForFile(File $file) { + foreach ($this->editors as $editor) { + if (in_array($file->getMimeType(), $editor->getMimetypes())) { + return $editor->getId(); + } + } + throw new \RuntimeException('No default editor found for files mimetype'); + } + + public function edit(string $token): Response { + try { + /** @var IEditor $editor */ + $tokenObject = $this->getToken($token); + if ($tokenObject->hasBeenAccessed()) { + throw new \RuntimeException('Token has already been used and can only be used for followup requests'); + } + $editor = $this->getEditor($tokenObject->getEditor()); + $this->accessToken($token); + + } catch (\Throwable $throwable) { + $this->invalidateToken($token); + return new NotFoundResponse(); + } + return $editor->open($tokenObject); + } + + public function editSecure(File $file, string $editorId): TemplateResponse { + // TODO: Implementation in follow up + } + + private function getEditor($editorId): IEditor { + if (!array_key_exists($editorId, $this->editors)) { + throw new \RuntimeException('No editor found'); + } + return $this->editors[$editorId]; + } + + public function getToken(string $token): IToken { + $query = $this->connection->getQueryBuilder(); + $query->select('*')->from(self::TABLE_TOKENS) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + if ($tokenRow = $result->fetch(FetchMode::ASSOCIATIVE)) { + return new Token($this, $tokenRow); + } + throw new \RuntimeException('Failed to validate the token'); + } + + public function cleanup(): int { + $query = $this->connection->getQueryBuilder(); + $query->delete(self::TABLE_TOKENS) + ->where($query->expr()->lt('timestamp', $query->createNamedParameter(time() - self::TOKEN_CLEANUP_TIME))); + return $query->execute(); + } + + public function refreshToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->update(self::TABLE_TOKENS) + ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + + public function invalidateToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->delete(self::TABLE_TOKENS) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + public function accessToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->update(self::TABLE_TOKENS) + ->set('accessed', $query->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)) + ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + public function invokeTokenScope($userId): void { + \OC_User::setIncognitoMode(true); + \OC_User::setUserId($userId); + } + + public function createToken($editorId, File $file, IShare $share = null): string { + $token = $this->random->generate(64, ISecureRandom::CHAR_HUMAN_READABLE); + $query = $this->connection->getQueryBuilder(); + $query->insert(self::TABLE_TOKENS) + ->values([ + 'token' => $query->createNamedParameter($token), + 'editor_id' => $query->createNamedParameter($editorId), + 'file_id' => $query->createNamedParameter($file->getId()), + 'user_id' => $query->createNamedParameter($this->userId), + 'share_id' => $query->createNamedParameter($share !== null ? $share->getId(): null), + 'timestamp' => $query->createNamedParameter(time()) + ]); + $query->execute(); + return $token; + } + + public function getFileForToken($userId, $fileId) { + $userFolder = $this->rootFolder->getUserFolder($userId); + return $userFolder->getById($fileId)[0]; + } + +} diff --git a/lib/private/DirectEditing/Token.php b/lib/private/DirectEditing/Token.php new file mode 100644 index 00000000000..946699900b7 --- /dev/null +++ b/lib/private/DirectEditing/Token.php @@ -0,0 +1,76 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OC\DirectEditing; + + +use OCP\DirectEditing\IToken; +use OCP\Files\File; + +class Token implements IToken { + + /** @var Manager */ + private $manager; + private $data; + + public function __construct(Manager $manager, $data) { + $this->manager = $manager; + $this->data = $data; + } + + public function extend(): void { + $this->manager->refreshToken($this->data['token']); + } + + public function invalidate(): void { + $this->manager->invalidateToken($this->data['token']); + } + + public function getFile(): File { + if ($this->data['share_id'] !== null) { + return $this->manager->getShareForToken($this->data['share_id']); + } + return $this->manager->getFileForToken($this->data['user_id'], $this->data['file_id']); + } + + public function getToken(): string { + return $this->data['token']; + } + + public function useTokenScope(): void { + $this->manager->invokeTokenScope($this->data['user_id']); + } + + public function hasBeenAccessed(): bool { + return $this->data['accessed'] === '1'; + } + + public function getEditor(): string { + return $this->data['editor_id']; + } + + public function getUser(): string { + return $this->data['user_id']; + } + +} diff --git a/lib/private/Server.php b/lib/private/Server.php index b4af17ba288..9fb197fcb18 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -199,6 +199,8 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class); $this->registerAlias('ContactsManager', \OCP\Contacts\IManager::class); + $this->registerAlias(\OCP\DirectEditing\IManager::class, \OC\DirectEditing\Manager::class); + $this->registerAlias(IActionFactory::class, ActionFactory::class); -- cgit v1.2.3 From bccf2367384f3d093b2988eb6d09e4f9c9a899a4 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 31 Oct 2019 09:18:05 +0100 Subject: encapsulate templates Signed-off-by: tobiasKaminsky --- lib/private/DirectEditing/Manager.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/private') diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php index 085a7de557a..353faedf7eb 100644 --- a/lib/private/DirectEditing/Manager.php +++ b/lib/private/DirectEditing/Manager.php @@ -88,7 +88,9 @@ class Manager implements IManager { $templates = $creator->getTemplates(); } } - return $templates; + $return = []; + $return['templates'] = $templates; + return $return; } public function create(string $path, string $editorId, string $creatorId, $templateId = null): string { -- cgit v1.2.3 From bc36cc808fb9ed9ff22c42246fe68f06cedb902e Mon Sep 17 00:00:00 2001 From: Julius Härtl Date: Mon, 25 Nov 2019 13:56:22 +0100 Subject: Move editor list to capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- apps/files/appinfo/routes.php | 5 --- apps/files/lib/Capabilities.php | 43 +++++++++++++++++++++- .../lib/Controller/DirectEditingController.php | 42 --------------------- lib/private/DirectEditing/Manager.php | 9 ++++- 4 files changed, 49 insertions(+), 50 deletions(-) (limited to 'lib/private') diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index 6f8a6878aac..f900b5ffbd8 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -99,11 +99,6 @@ $application->registerRoutes( ], ], 'ocs' => [ - [ - 'name' => 'DirectEditing#get', - 'url' => '/api/v1/directEditing', - 'verb' => 'GET' - ], [ 'name' => 'DirectEditing#templates', 'url' => '/api/v1/directEditing/templates/{editorId}/{creatorId}', diff --git a/apps/files/lib/Capabilities.php b/apps/files/lib/Capabilities.php index 2b6bf57b90d..c37e32b6b59 100644 --- a/apps/files/lib/Capabilities.php +++ b/apps/files/lib/Capabilities.php @@ -25,7 +25,11 @@ namespace OCA\Files; +use OC\DirectEditing\Manager; use OCP\Capabilities\ICapability; +use OCP\DirectEditing\ACreateEmpty; +use OCP\DirectEditing\ACreateFromTemplate; +use OCP\DirectEditing\IEditor; use OCP\IConfig; /** @@ -42,8 +46,9 @@ class Capabilities implements ICapability { * * @param IConfig $config */ - public function __construct(IConfig $config) { + public function __construct(IConfig $config, Manager $manager) { $this->config = $config; + $this->directEditingManager = $manager; } /** @@ -56,7 +61,43 @@ class Capabilities implements ICapability { 'files' => [ 'bigfilechunking' => true, 'blacklisted_files' => $this->config->getSystemValue('blacklisted_files', ['.htaccess']), + 'directEditing' => $this->getDirectEditingCapabilitites() ], ]; } + + private function getDirectEditingCapabilitites() { + $capabilities = [ + 'editors' => [], + 'creators' => [] + ]; + + /** + * @var string $id + * @var IEditor $editor + */ + foreach ($this->directEditingManager->getEditors() as $id => $editor) { + $capabilities['editors'][$id] = [ + 'name' => $editor->getName(), + 'mimetypes' => $editor->getMimetypes(), + 'optionalMimetypes' => $editor->getMimetypesOptional(), + 'secure' => $editor->isSecure(), + ]; + /** @var ACreateEmpty|ACreateFromTemplate $creator */ + foreach ($editor->getCreators() as $creator) { + $id = $creator->getId(); + $capabilities['creators'][$id] = [ + 'id' => $id, + 'name' => $creator->getName(), + 'extension' => $creator->getExtension(), + 'templates' => false + ]; + if ($creator instanceof ACreateFromTemplate) { + $capabilities['creators'][$id]['templates'] = true; + } + + } + } + return $capabilities; + } } diff --git a/apps/files/lib/Controller/DirectEditingController.php b/apps/files/lib/Controller/DirectEditingController.php index cf948d20f76..e8791316442 100644 --- a/apps/files/lib/Controller/DirectEditingController.php +++ b/apps/files/lib/Controller/DirectEditingController.php @@ -62,48 +62,6 @@ class DirectEditingController extends OCSController { $this->urlGenerator = $urlGenerator; } - /** - * @NoAdminRequired - * - * @return DataResponse - */ - public function get(): DataResponse { - $this->eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this->directEditingManager)); - - $capabilities = [ - 'editors' => [], - 'creators' => [] - ]; - - /** - * @var string $id - * @var IEditor $editor - */ - foreach ($this->directEditingManager->getEditors() as $id => $editor) { - $capabilities['editors'][$id] = [ - 'name' => $editor->getName(), - 'mimetypes' => $editor->getMimetypes(), - 'optionalMimetypes' => $editor->getMimetypesOptional(), - 'secure' => $editor->isSecure(), - ]; - /** @var ACreateEmpty|ACreateFromTemplate $creator */ - foreach ($editor->getCreators() as $creator) { - $id = $creator->getId(); - $capabilities['creators'][$id] = [ - 'id' => $id, - 'name' => $creator->getName(), - 'extension' => $creator->getExtension(), - 'templates' => false - ]; - if ($creator instanceof ACreateFromTemplate) { - $capabilities['creators'][$id]['templates'] = true; - } - - } - } - return new DataResponse($capabilities); - } - /** * @NoAdminRequired */ diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php index 353faedf7eb..fdf0a1f0f0f 100644 --- a/lib/private/DirectEditing/Manager.php +++ b/lib/private/DirectEditing/Manager.php @@ -32,6 +32,8 @@ use OCP\DirectEditing\ACreateFromTemplate; use OCP\DirectEditing\IEditor; use \OCP\DirectEditing\IManager; use OCP\DirectEditing\IToken; +use OCP\DirectEditing\RegisterDirectEditorEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; @@ -47,7 +49,7 @@ class Manager implements IManager { public const TABLE_TOKENS = 'direct_edit'; /** @var IEditor[] */ - private $editors; + private $editors = []; /** @var IDBConnection */ private $connection; @@ -62,12 +64,15 @@ class Manager implements IManager { ISecureRandom $random, IDBConnection $connection, IUserSession $userSession, - IRootFolder $rootFolder + IRootFolder $rootFolder, + IEventDispatcher $eventDispatcher ) { $this->random = $random; $this->connection = $connection; $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null; $this->rootFolder = $rootFolder; + $eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this)); + } public function registerDirectEditor(IEditor $directEditor): void { -- cgit v1.2.3 From 9a2694fcb0093afee13d0cd91de15b34b747cc62 Mon Sep 17 00:00:00 2001 From: Julius Härtl Date: Mon, 25 Nov 2019 14:09:38 +0100 Subject: Code style fixes and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- .../BackgroundJob/CleanupDirectEditingTokens.php | 2 +- apps/files/lib/Capabilities.php | 16 ++++- .../lib/Controller/DirectEditingController.php | 6 +- core/Migrations/Version18000Date20191014105105.php | 70 +++++++++++----------- lib/private/DirectEditing/Manager.php | 5 +- lib/public/DirectEditing/ACreateFromTemplate.php | 2 +- lib/public/DirectEditing/IEditor.php | 6 +- tests/lib/DirectEditing/ManagerTest.php | 20 ++++++- 8 files changed, 75 insertions(+), 52 deletions(-) (limited to 'lib/private') diff --git a/apps/files/lib/BackgroundJob/CleanupDirectEditingTokens.php b/apps/files/lib/BackgroundJob/CleanupDirectEditingTokens.php index 77907fab281..8d4a3f23787 100644 --- a/apps/files/lib/BackgroundJob/CleanupDirectEditingTokens.php +++ b/apps/files/lib/BackgroundJob/CleanupDirectEditingTokens.php @@ -7,7 +7,7 @@ use OCP\DirectEditing\IManager; class CleanupDirectEditingTokens extends TimedJob { - const INTERVAL_MINUTES = 15 * 60; + private const INTERVAL_MINUTES = 15 * 60; /** * @var IManager diff --git a/apps/files/lib/Capabilities.php b/apps/files/lib/Capabilities.php index c37e32b6b59..19b59971c4c 100644 --- a/apps/files/lib/Capabilities.php +++ b/apps/files/lib/Capabilities.php @@ -30,6 +30,8 @@ use OCP\Capabilities\ICapability; use OCP\DirectEditing\ACreateEmpty; use OCP\DirectEditing\ACreateFromTemplate; use OCP\DirectEditing\IEditor; +use OCP\DirectEditing\RegisterDirectEditorEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; /** @@ -38,17 +40,25 @@ use OCP\IConfig; * @package OCA\Files */ class Capabilities implements ICapability { + /** @var IConfig */ protected $config; + /** @var Manager */ + protected $directEditingManager; + + /** @var IEventDispatcher */ + protected $eventDispatcher; + /** * Capabilities constructor. * * @param IConfig $config */ - public function __construct(IConfig $config, Manager $manager) { + public function __construct(IConfig $config, Manager $manager, IEventDispatcher $eventDispatcher) { $this->config = $config; $this->directEditingManager = $manager; + $this->eventDispatcher = $eventDispatcher; } /** @@ -66,7 +76,9 @@ class Capabilities implements ICapability { ]; } - private function getDirectEditingCapabilitites() { + private function getDirectEditingCapabilitites(): array { + $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager)); + $capabilities = [ 'editors' => [], 'creators' => [] diff --git a/apps/files/lib/Controller/DirectEditingController.php b/apps/files/lib/Controller/DirectEditingController.php index e8791316442..11d09e2f074 100644 --- a/apps/files/lib/Controller/DirectEditingController.php +++ b/apps/files/lib/Controller/DirectEditingController.php @@ -66,7 +66,7 @@ class DirectEditingController extends OCSController { * @NoAdminRequired */ public function create(string $path, string $editorId, string $creatorId, string $templateId = null): DataResponse { - $this->eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this->directEditingManager)); + $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager)); try { $token = $this->directEditingManager->create($path, $editorId, $creatorId, $templateId); @@ -83,7 +83,7 @@ class DirectEditingController extends OCSController { * @NoAdminRequired */ public function open(int $fileId, string $editorId = null): DataResponse { - $this->eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this->directEditingManager)); + $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager)); try { $token = $this->directEditingManager->open($fileId, $editorId); @@ -102,7 +102,7 @@ class DirectEditingController extends OCSController { * @NoAdminRequired */ public function templates(string $editorId, string $creatorId): DataResponse { - $this->eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this->directEditingManager)); + $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager)); try { return new DataResponse($this->directEditingManager->getTemplates($editorId, $creatorId)); diff --git a/core/Migrations/Version18000Date20191014105105.php b/core/Migrations/Version18000Date20191014105105.php index b291c0b5e46..634f9f91faf 100644 --- a/core/Migrations/Version18000Date20191014105105.php +++ b/core/Migrations/Version18000Date20191014105105.php @@ -50,44 +50,42 @@ class Version18000Date20191014105105 extends SimpleMigrationStep { public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { /** @var ISchemaWrapper $schema */ $schema = $schemaClosure(); - if (!$schema->hasTable('direct_edit')) { - $table = $schema->createTable('direct_edit'); + $table = $schema->createTable('direct_edit'); - $table->addColumn('id', Type::BIGINT, [ - 'autoincrement' => true, - 'notnull' => true, - ]); - $table->addColumn('editor_id', Type::STRING, [ - 'notnull' => true, - 'length' => 64, - ]); - $table->addColumn('token', Type::STRING, [ - 'notnull' => true, - 'length' => 64, - ]); - $table->addColumn('file_id', Type::BIGINT, [ - 'notnull' => true, - ]); - $table->addColumn('user_id', Type::STRING, [ - 'notnull' => false, - 'length' => 64, - ]); - $table->addColumn('share_id', Type::BIGINT, [ - 'notnull' => false - ]); - $table->addColumn('timestamp', Type::BIGINT, [ - 'notnull' => true, - 'length' => 20, - 'unsigned' => true, - ]); - $table->addColumn('accessed', Type::BOOLEAN, [ - 'notnull' => true, - 'default' => false - ]); + $table->addColumn('id', Type::BIGINT, [ + 'autoincrement' => true, + 'notnull' => true, + ]); + $table->addColumn('editor_id', Type::STRING, [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('token', Type::STRING, [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('file_id', Type::BIGINT, [ + 'notnull' => true, + ]); + $table->addColumn('user_id', Type::STRING, [ + 'notnull' => false, + 'length' => 64, + ]); + $table->addColumn('share_id', Type::BIGINT, [ + 'notnull' => false + ]); + $table->addColumn('timestamp', Type::BIGINT, [ + 'notnull' => true, + 'length' => 20, + 'unsigned' => true, + ]); + $table->addColumn('accessed', Type::BOOLEAN, [ + 'notnull' => true, + 'default' => false + ]); - $table->setPrimaryKey(['id']); - $table->addIndex(['token']); - } + $table->setPrimaryKey(['id']); + $table->addIndex(['token']); return $schema; } diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php index fdf0a1f0f0f..26adad9e572 100644 --- a/lib/private/DirectEditing/Manager.php +++ b/lib/private/DirectEditing/Manager.php @@ -64,15 +64,12 @@ class Manager implements IManager { ISecureRandom $random, IDBConnection $connection, IUserSession $userSession, - IRootFolder $rootFolder, - IEventDispatcher $eventDispatcher + IRootFolder $rootFolder ) { $this->random = $random; $this->connection = $connection; $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null; $this->rootFolder = $rootFolder; - $eventDispatcher->dispatch(RegisterDirectEditorEvent::class, new RegisterDirectEditorEvent($this)); - } public function registerDirectEditor(IEditor $directEditor): void { diff --git a/lib/public/DirectEditing/ACreateFromTemplate.php b/lib/public/DirectEditing/ACreateFromTemplate.php index a731e8be595..89420a63743 100644 --- a/lib/public/DirectEditing/ACreateFromTemplate.php +++ b/lib/public/DirectEditing/ACreateFromTemplate.php @@ -32,7 +32,7 @@ abstract class ACreateFromTemplate extends ACreateEmpty { * List of available templates for the create from template action * * @since 18.0.0 - * @return array + * @return ATemplate[] */ abstract public function getTemplates(): array; diff --git a/lib/public/DirectEditing/IEditor.php b/lib/public/DirectEditing/IEditor.php index a4fc87f7e15..a2bc0d74255 100644 --- a/lib/public/DirectEditing/IEditor.php +++ b/lib/public/DirectEditing/IEditor.php @@ -56,7 +56,7 @@ interface IEditor { * A list of mimetypes that should open the editor by default * * @since 18.0.0 - * @return array + * @return string[] */ public function getMimetypes(): array; @@ -64,7 +64,7 @@ interface IEditor { * A list of mimetypes that can be opened in the editor optionally * * @since 18.0.0 - * @return array + * @return string[] */ public function getMimetypesOptional(): array; @@ -72,7 +72,7 @@ interface IEditor { * Return a list of file creation options to be presented to the user * * @since 18.0.0 - * @return array of ICreateFromTemplate|ICreateEmpty + * @return ACreateFromTemplate[]|ACreateEmpty[] */ public function getCreators(): array; diff --git a/tests/lib/DirectEditing/ManagerTest.php b/tests/lib/DirectEditing/ManagerTest.php index b2e58efd8e2..a3d29efbce5 100644 --- a/tests/lib/DirectEditing/ManagerTest.php +++ b/tests/lib/DirectEditing/ManagerTest.php @@ -7,7 +7,6 @@ use OC\Files\Node\File; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Http\Response; -use OCP\AppFramework\Http\TemplateResponse; use OCP\DirectEditing\ACreateEmpty; use OCP\DirectEditing\IEditor; use OCP\DirectEditing\IToken; @@ -16,6 +15,7 @@ use OCP\Files\IRootFolder; use OCP\IDBConnection; use OCP\IUserSession; use OCP\Security\ISecureRandom; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class CreateEmpty extends ACreateEmpty { @@ -82,9 +82,25 @@ class ManagerTest extends TestCase { */ private $editor; /** - * @var \PHPUnit\Framework\MockObject\MockObject + * @var MockObject|ISecureRandom */ private $random; + /** + * @var IDBConnection + */ + private $connection; + /** + * @var MockObject|IUserSession + */ + private $userSession; + /** + * @var MockObject|IRootFolder + */ + private $rootFolder; + /** + * @var MockObject|Folder + */ + private $userFolder; protected function setUp() { parent::setUp(); -- cgit v1.2.3