Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@
'OCA\\Text\\Service\\ConfigService' => $baseDir . '/../lib/Service/ConfigService.php',
'OCA\\Text\\Service\\DocumentService' => $baseDir . '/../lib/Service/DocumentService.php',
'OCA\\Text\\Service\\EncodingService' => $baseDir . '/../lib/Service/EncodingService.php',
'OCA\\Text\\Service\\FileService' => $baseDir . '/../lib/Service/FileService.php',
'OCA\\Text\\Service\\InitialStateProvider' => $baseDir . '/../lib/Service/InitialStateProvider.php',
'OCA\\Text\\Service\\LockService' => $baseDir . '/../lib/Service/LockService.php',
'OCA\\Text\\Service\\NotificationService' => $baseDir . '/../lib/Service/NotificationService.php',
'OCA\\Text\\Service\\SessionService' => $baseDir . '/../lib/Service/SessionService.php',
'OCA\\Text\\Service\\WorkspaceService' => $baseDir . '/../lib/Service/WorkspaceService.php',
Expand Down
2 changes: 2 additions & 0 deletions composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ class ComposerStaticInitText
'OCA\\Text\\Service\\ConfigService' => __DIR__ . '/..' . '/../lib/Service/ConfigService.php',
'OCA\\Text\\Service\\DocumentService' => __DIR__ . '/..' . '/../lib/Service/DocumentService.php',
'OCA\\Text\\Service\\EncodingService' => __DIR__ . '/..' . '/../lib/Service/EncodingService.php',
'OCA\\Text\\Service\\FileService' => __DIR__ . '/..' . '/../lib/Service/FileService.php',
'OCA\\Text\\Service\\InitialStateProvider' => __DIR__ . '/..' . '/../lib/Service/InitialStateProvider.php',
'OCA\\Text\\Service\\LockService' => __DIR__ . '/..' . '/../lib/Service/LockService.php',
'OCA\\Text\\Service\\NotificationService' => __DIR__ . '/..' . '/../lib/Service/NotificationService.php',
'OCA\\Text\\Service\\SessionService' => __DIR__ . '/..' . '/../lib/Service/SessionService.php',
'OCA\\Text\\Service\\WorkspaceService' => __DIR__ . '/..' . '/../lib/Service/WorkspaceService.php',
Expand Down
32 changes: 27 additions & 5 deletions lib/Controller/PublicSessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@
use OCA\Text\Middleware\Attribute\RequireDocumentBaseVersionEtag;
use OCA\Text\Middleware\Attribute\RequireDocumentSession;
use OCA\Text\Service\ApiService;
use OCA\Text\Service\FileService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\PublicShareController;
use OCP\Constants;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
use OCP\IRequest;
use OCP\ISession;
use OCP\Share\Exceptions\ShareNotFound;
Expand All @@ -32,6 +38,8 @@ public function __construct(
ISession $session,
private ShareManager $shareManager,
private ApiService $apiService,
private FileService $fileService,
private IL10N $l10n,
) {
parent::__construct($appName, $request, $session);
}
Expand Down Expand Up @@ -64,21 +72,35 @@ protected function isPasswordProtected(): bool {

#[NoAdminRequired]
#[PublicPage]
public function create(string $token, ?string $file = null, ?string $baseVersionEtag = null, ?string $guestName = null): DataResponse {
return $this->apiService->create(null, $file, $baseVersionEtag, $token, $guestName);
public function create(string $token, ?string $filePath = null, ?string $baseVersionEtag = null, ?string $guestName = null): DataResponse {
$file = $this->fileService->getFileByShareToken($token, $filePath);
/*
* Check if we have proper read access (files drop)
* If not then well 404 it is.
*/
try {
$this->fileService->checkSharePermissions($token, Constants::PERMISSION_READ);
} catch (NotFoundException) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (NotPermittedException) {
return new DataResponse(['error' => $this->l10n->t('This file cannot be displayed as download is disabled by the share')], Http::STATUS_NOT_FOUND);
}

return $this->apiService->create($file, $baseVersionEtag, $token, $guestName);
}

#[NoAdminRequired]
#[PublicPage]
public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse {
return $this->apiService->close($documentId, $sessionId, $sessionToken);
public function close(int $documentId, int $sessionId, string $sessionToken, string $token): DataResponse {
$file = $this->fileService->getFileByIdFromShare($documentId, $token);
return $this->apiService->close($documentId, $sessionId, $sessionToken, $file);
}

#[NoAdminRequired]
#[PublicPage]
#[RequireDocumentBaseVersionEtag]
#[RequireDocumentSession]
public function push(int $documentId, int $sessionId, string $sessionToken, int $version, array $steps, string $awareness, string $token, ?int $recoveryAttempt = null): DataResponse {
public function push(int $version, array $steps, string $awareness, string $token, ?int $recoveryAttempt = null): DataResponse {
return $this->apiService->push($this->getSession(), $this->getDocument(), $version, $steps, $awareness, $recoveryAttempt, $token);
}

Expand Down
35 changes: 32 additions & 3 deletions lib/Controller/SessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,27 @@

namespace OCA\Text\Controller;

use OCA\Text\Exception\InvalidSessionException;
use OCA\Text\Middleware\Attribute\RequireDocumentBaseVersionEtag;
use OCA\Text\Middleware\Attribute\RequireDocumentSession;
use OCA\Text\Service\ApiService;
use OCA\Text\Service\FileService;
use OCA\Text\Service\NotificationService;
use OCA\Text\Service\SessionService;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\DataResponse;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;

class SessionController extends ApiController implements ISessionAwareController {
use TSessionAwareController;
Expand All @@ -33,23 +40,45 @@ public function __construct(
string $appName,
IRequest $request,
private ApiService $apiService,
private FileService $fileService,
private SessionService $sessionService,
private NotificationService $notificationService,
private IUserManager $userManager,
private IUserSession $userSession,
private LoggerInterface $logger,
private IL10N $l10n,
) {
parent::__construct($appName, $request);
}

#[NoAdminRequired]
public function create(?int $fileId = null, ?string $file = null, ?string $baseVersionEtag = null): DataResponse {
return $this->apiService->create($fileId, $file, $baseVersionEtag);
public function create(?int $fileId = null, ?string $baseVersionEtag = null): DataResponse {
$userId = $this->userSession->getUser()?->getUID();
if ($fileId === null || $userId === null) {
return new DataResponse(['error' => 'No valid file argument provided'], Http::STATUS_PRECONDITION_FAILED);
}

try {
$file = $this->fileService->getFileById($fileId, $userId);
} catch (NotFoundException|NotPermittedException $e) {
$this->logger->error('No permission to access this file', [ 'exception' => $e ]);
return new DataResponse([
'error' => $this->l10n->t('File not found')
], Http::STATUS_NOT_FOUND);
}

return $this->apiService->create($file, $baseVersionEtag);
}

#[NoAdminRequired]
#[PublicPage]
public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse {
return $this->apiService->close($documentId, $sessionId, $sessionToken);
$userId = $this->userSession->getUser()?->getUID();
if ($userId === null) {
throw new InvalidSessionException();
}
$file = $this->fileService->getFileById($documentId, $userId);
return $this->apiService->close($documentId, $sessionId, $sessionToken, $file);
}

#[NoAdminRequired]
Expand Down
2 changes: 1 addition & 1 deletion lib/DirectEditing/TextDirectEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public function isSecure(): bool {
public function open(IToken $token): Response {
$token->useTokenScope();
try {
$session = $this->apiService->create($token->getFile()->getId());
$session = $this->apiService->create($token->getFile());
$this->initialStateProvider->provideFile([
'fileId' => $token->getFile()->getId(),
'mimetype' => $token->getFile()->getMimeType(),
Expand Down
67 changes: 10 additions & 57 deletions lib/Middleware/SessionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,18 @@
use OCA\Text\Middleware\Attribute\RequireDocumentSession;
use OCA\Text\Middleware\Attribute\RequireDocumentSessionOrUserOrShareToken;
use OCA\Text\Service\DocumentService;
use OCA\Text\Service\FileService;
use OCA\Text\Service\SessionService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\Constants;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
use ReflectionException;

class SessionMiddleware extends Middleware {
Expand All @@ -42,12 +36,10 @@ public function __construct(
private readonly IRequest $request,
private readonly SessionService $sessionService,
private readonly DocumentService $documentService,
private readonly ISession $session,
private readonly IUserSession $userSession,
private readonly IRootFolder $rootFolder,
private readonly ShareManager $shareManager,
private readonly IL10N $l10n,
private readonly IUserManager $userManager,
private readonly FileService $fileService,
) {
}

Expand Down Expand Up @@ -135,60 +127,21 @@ private function assertDocumentSession(ISessionAwareController $controller): voi
* @throws InvalidSessionException
*/
private function assertUserOrShareToken(ISessionAwareController $controller): void {
$documentId = (int)$this->request->getParam('documentId');
$fileId = (int)$this->request->getParam('documentId');
$shareToken = (string)$this->request->getParam('shareToken');
$userId = $this->userSession->getUser()?->getUID();

if ($shareToken !== '') {
try {
$share = $this->shareManager->getShareByToken($shareToken);
} catch (ShareNotFound) {
throw new InvalidSessionException();
}

$node = $this->rootFolder->getUserFolder($share->getShareOwner())->getFirstNodeById($documentId);
if ($node === null) {
throw new InvalidSessionException();
}

if ($share->getNodeType() === 'folder') {
$folder = $share->getNode();
if (!$folder instanceof Folder) {
throw new InvalidSessionException();
}
$file = $folder->getFirstNodeById($documentId);
if (!$file instanceof File) {
throw new InvalidSessionException();
}
}

if ($share->getPassword() !== null) {
$shareIds = $this->session->get('public_link_authenticated');
$shareIds = is_array($shareIds) ? $shareIds : [$shareIds];

if (!in_array($share->getId(), $shareIds, true)) {
throw new InvalidSessionException();
}
}

if (($share->getPermissions() & Constants::PERMISSION_READ) !== Constants::PERMISSION_READ) {
throw new InvalidSessionException();
}

$attributes = $share->getAttributes();
if ($attributes !== null && $attributes->getAttribute('permissions', 'download') === false) {
throw new InvalidSessionException();
}

$documentId = $this->fileService->getDocumentIdFromShare($fileId, $shareToken);
$controller->setDocumentId($documentId);
return;
}

if (null !== $userId = $this->userSession->getUser()?->getUID()) {
if ($this->rootFolder->getUserFolder($userId)->getFirstNodeById($documentId) !== null) {
$controller->setUserId($userId);
$controller->setDocumentId($documentId);
return;
}
if ($userId !== null) {
$documentId = $this->fileService->getDocumentIdForUser($fileId, $userId);
$controller->setUserId($userId);
$controller->setDocumentId($documentId);
return;
}

throw new InvalidSessionException();
Expand Down
Loading
Loading