Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Start with direct editing
Signed-off-by: Julius Härtl <[email protected]>
  • Loading branch information
juliusknorr committed Dec 2, 2019
commit baa11f406390cca2a890c16bf1cf0b404b2fc700
2 changes: 2 additions & 0 deletions appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@
\OCP\Util::addScript('text', 'public');
\OCP\Util::addStyle('text', 'icons');
});

$app = \OC::$server->query(Application::class);
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
['name' => 'PublicSession#fetch', 'url' => '/public/session/fetch', 'verb' => 'GET'],
['name' => 'PublicSession#sync', 'url' => '/public/session/sync', 'verb' => 'POST'],
['name' => 'PublicSession#push', 'url' => '/public/session/push', 'verb' => 'POST'],

['name' => 'PublicSession#close', 'url' => '/public/session/close', 'verb' => 'GET'],
],
'ocs' => [
Expand Down
12 changes: 12 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@

namespace OCA\Text\AppInfo;

use OCA\Text\DirectEditing\TextDirectEditor;
use OCP\AppFramework\App;
use OCP\DirectEditing\RegisterDirectEditorEvent;
use OCP\EventDispatcher\IEventDispatcher;

class Application extends App {

Expand All @@ -36,9 +39,18 @@ class Application extends App {
* Application constructor.
*
* @param array $params
* @throws \OCP\AppFramework\QueryException
*/
public function __construct(array $params = []) {
parent::__construct(self::APP_NAME, $params);

$container = $this->getContainer();
/** @var IEventDispatcher $eventDispatcher */
$eventDispatcher = $this->getContainer()->getServer()->query(IEventDispatcher::class);
$eventDispatcher->addListener(RegisterDirectEditorEvent::class, function (RegisterDirectEditorEvent $event) use ($container) {
$editor = $container->query(TextDirectEditor::class);
$event->register($editor);
});
}

}
Expand Down
141 changes: 141 additions & 0 deletions lib/Controller/DirectSessionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <[email protected]>
*
* @author Julius Härtl <[email protected]>
*
* @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);
/**
* @copyright Copyright (c) 2019 Julius Härtl <[email protected]>
*
* @author Julius Härtl <[email protected]>
*
* @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\Text\Controller;

use OC\Authentication\Exceptions\InvalidTokenException;
use OCA\Text\Service\ApiService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\PublicShareController;
use OCP\DirectEditing\IManager;
use OCP\ISession;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;
use OCP\Share\IShare;

class DirectSessionController extends Controller {

/** @var ShareManager */
private $shareManager;

/** @var IShare */
private $share;

/** @var ApiService */
private $apiService;
/** @var IManager */
private $directManager;

public function __construct(string $appName, IRequest $request, ShareManager $shareManager, ApiService $apiService, IManager $directManager) {
parent::__construct($appName, $request);
$this->shareManager = $shareManager;
$this->apiService = $apiService;
$this->directManager = $directManager;
}

/**
* @PublicPage
*/
public function create(string $token, string $file = null, $guestName = null, bool $forceRecreate = false): DataResponse {
try {
$tokenObject = $this->directManager->getToken($token);
$tokenObject->extend();
$tokenObject->useTokenScope();
$node = $tokenObject->getFile();
$node->touch();
return new DataResponse([
'mtime' => $node->getMTime()
]);
} catch (InvalidTokenException $e) {
return new DataResponse('error');
}
//return $this->apiService->create(null, $file, $token, $guestName, $forceRecreate);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function fetch(int $documentId, string $sessionId, string $sessionToken): Response {
return $this->apiService->fetch($documentId, $sessionId, $sessionToken);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse {
return $this->apiService->close($documentId, $sessionId, $sessionToken);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function push(int $documentId, int $sessionId, string $sessionToken, int $version, array $steps, string $token): DataResponse {
return $this->apiService->push($documentId, $sessionId, $sessionToken, $version, $steps, $token);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function sync(string $token, int $documentId, int $sessionId, string $sessionToken, int $version = 0, string $autosaveContent = null, bool $force = false, bool $manualSave = false): DataResponse {
return $this->apiService->sync($documentId, $sessionId, $sessionToken, $version, $autosaveContent, $force, $manualSave, $token);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function updateSession(int $documentId, int $sessionId, string $sessionToken, string $guestName) {
return $this->apiService->updateSession($documentId, $sessionId, $sessionToken, $guestName);
}

}
4 changes: 4 additions & 0 deletions lib/Controller/SessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,31 @@ public function create(int $fileId = null, string $file = null, bool $forceRecre

/**
* @NoAdminRequired
* @PublicPage
*/
public function fetch(int $documentId, int $sessionId, string $sessionToken): Response {
return $this->apiService->fetch($documentId, $sessionId, $sessionToken);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse {
return $this->apiService->close($documentId, $sessionId, $sessionToken);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function push(int $documentId, int $sessionId, string $sessionToken, int $version, array $steps): DataResponse {
return $this->apiService->push($documentId, $sessionId, $sessionToken, $version, $steps);
}

/**
* @NoAdminRequired
* @PublicPage
*/
public function sync(int $documentId, int $sessionId, string $sessionToken, int $version = 0, string $autosaveContent = null, bool $force = false, bool $manualSave = false): DataResponse {
return $this->apiService->sync($documentId, $sessionId, $sessionToken, $version, $autosaveContent, $force, $manualSave);
Expand Down
5 changes: 5 additions & 0 deletions lib/Db/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

use OCP\AppFramework\Db\Entity;

/**
* @method setLastContact(int $getTime)
* @method getDocumentId()
* @method getUserId()
*/
class Session extends Entity implements \JsonSerializable {

public $id;
Expand Down
151 changes: 151 additions & 0 deletions lib/DirectEditing/TextDirectEditor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <[email protected]>
*
* @author Julius Härtl <[email protected]>
*
* @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\Text\DirectEditing;

use OCA\Files\Controller\ApiController;
use OCA\Text\AppInfo\Application;
use OCA\Text\Service\ApiService;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\DirectEditing\IEditor;
use OCP\DirectEditing\IToken;
use OCP\Files\InvalidPathException;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IInitialStateService;
use OCP\IL10N;

class TextDirectEditor implements IEditor {

/** @var IL10N */
private $l10n;

/** @var IInitialStateService */
private $initialStateService;

/** @var ApiService */
private $apiService;

public function __construct(IL10N $l10n, IInitialStateService $initialStateService, ApiService $apiService) {
$this->l10n = $l10n;
$this->initialStateService = $initialStateService;
$this->apiService = $apiService;
}

/**
* Return a unique identifier for the editor
*
* e.g. richdocuments
*
* @return string
*/
public function getId(): string {
return Application::APP_NAME;
}

/**
* Return a readable name for the editor
*
* e.g. Collabora Online
*
* @return string
*/
public function getName(): string {
return $this->l10n->t('Nextcloud Text');
}

/**
* A list of mimetypes that should open the editor by default
*
* @return array
*/
public function getMimetypes(): array {
return [
'text/markdown'
];
}

/**
* A list of mimetypes that can be opened in the editor optionally
*
* @return array
*/
public function getMimetypesOptional(): array {
return [
'text/plain'
];
}

/**
* Return a list of file creation options to be presented to the user
*
* @return array of ACreateFromTemplate|ACreateEmpty
*/
public function getCreators(): array {
return [
new TextDocumentCreator($this->l10n),
new TextDocumentTemplateCreator($this->l10n)
];
}

/**
* Return if the view is able to securely view a file without downloading it to the browser
*
* @return bool
*/
public function isSecure(): bool {
return false;
}

/**
* Return a template response for displaying the editor
*
* open can only be called once when the client requests the editor with a one-time-use token
* For handling editing and later requests, editors need to impelement their own token handling and take care of invalidation
*
* This behavior is similar to the current direct editing implementation in collabora where we generate a one-time token and switch over to the regular wopi token for the actual editing/saving process
*
* @param IToken $token
* @return Response
*/
public function open(IToken $token): Response {
$token->useTokenScope();
try {
$session = $this->apiService->create($token->getFile()->getId());
$this->initialStateService->provideInitialState('text', 'file', [
'fileId' => $token->getFile()->getId(),
'content' => $token->getFile()->getContent(),
'session' => \json_encode($session->getData())
]);
$this->initialStateService->provideInitialState('text', 'directEditingToken', $token->getToken());
return new TemplateResponse('text', 'main', [], 'base');
} catch (InvalidPathException $e) {
} catch (NotFoundException $e) {
} catch (NotPermittedException $e) {
}
return new NotFoundResponse();
}

}
Loading