diff --git a/appinfo/routes.php b/appinfo/routes.php index a9b511c51c8..316c6c1bd4c 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -25,35 +25,57 @@ namespace OCA\Text\AppInfo; +use OCA\Text\Controller; + return [ 'routes' => [ + /** @see Controller\AttachmentController::insertAttachmentFile() */ ['name' => 'Attachment#insertAttachmentFile', 'url' => '/attachment/filepath', 'verb' => 'POST'], + /** @see Controller\AttachmentController::uploadAttachment() */ ['name' => 'Attachment#uploadAttachment', 'url' => '/attachment/upload', 'verb' => 'POST'], + /** @see Controller\AttachmentController::getImageFile() */ ['name' => 'Attachment#getImageFile', 'url' => '/image', 'verb' => 'GET'], + /** @see Controller\AttachmentController::getMediaFile() */ ['name' => 'Attachment#getMediaFile', 'url' => '/media', 'verb' => 'GET'], + /** @see Controller\AttachmentController::getMediaFilePreview() */ ['name' => 'Attachment#getMediaFilePreview', 'url' => '/mediaPreview', 'verb' => 'GET'], + /** @see Controller\AttachmentController::getMediaFileMetadata() */ ['name' => 'Attachment#getMediaFileMetadata', 'url' => '/mediaMetadata', 'verb' => 'GET'], + /** @see Controller\SessionController::create() */ ['name' => 'Session#create', 'url' => '/session/create', 'verb' => 'PUT'], + /** @see Controller\SessionController::sync() */ ['name' => 'Session#sync', 'url' => '/session/sync', 'verb' => 'POST'], + /** @see Controller\SessionController::push() */ ['name' => 'Session#push', 'url' => '/session/push', 'verb' => 'POST'], + /** @see Controller\SessionController::close() */ ['name' => 'Session#close', 'url' => '/session/close', 'verb' => 'POST'], + /** @see Controller\SessionController::mention() */ ['name' => 'Session#mention', 'url' => '/session/mention', 'verb' => 'PUT'], + /** @see Controller\PublicSessionController::create() */ ['name' => 'PublicSession#create', 'url' => '/public/session/create', 'verb' => 'PUT'], + /** @see Controller\PublicSessionController::updateSession() */ ['name' => 'PublicSession#updateSession', 'url' => '/public/session', 'verb' => 'POST'], + /** @see Controller\PublicSessionController::sync() */ ['name' => 'PublicSession#sync', 'url' => '/public/session/sync', 'verb' => 'POST'], + /** @see Controller\PublicSessionController::push() */ ['name' => 'PublicSession#push', 'url' => '/public/session/push', 'verb' => 'POST'], - + /** @see Controller\PublicSessionController::close() */ ['name' => 'PublicSession#close', 'url' => '/public/session/close', 'verb' => 'POST'], + /** @see Controller\SettingsController::updateConfig() */ ['name' => 'Settings#updateConfig', 'url' => '/settings', 'verb' => 'POST'], + /** @see Controller\UserApiController::index() */ ['name' => 'UserApi#index', 'url' => '/api/v1/users', 'verb' => 'POST'], ], 'ocs' => [ + /** @see Controller\WorkspaceController::folder() */ ['name' => 'Workspace#folder', 'url' => '/workspace', 'verb' => 'GET'], + /** @see Controller\WorkspaceController::publicFolder() */ ['name' => 'Workspace#publicFolder', 'url' => '/public/workspace', 'verb' => 'GET'], + /** @see Controller\WorkspaceController::direct() */ ['name' => 'Workspace#direct', 'url' => '/workspace/direct', 'verb' => 'POST'], ] ]; diff --git a/composer/composer/autoload_classmap.php b/composer/composer/autoload_classmap.php index d72c32971b8..c8354ba643e 100644 --- a/composer/composer/autoload_classmap.php +++ b/composer/composer/autoload_classmap.php @@ -9,12 +9,13 @@ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'OCA\\Text\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', 'OCA\\Text\\Command\\ResetDocument' => $baseDir . '/../lib/Command/ResetDocument.php', - 'OCA\\Text\\Controller\\ASessionAwareController' => $baseDir . '/../lib/Controller/ASessionAwareController.php', 'OCA\\Text\\Controller\\AttachmentController' => $baseDir . '/../lib/Controller/AttachmentController.php', + 'OCA\\Text\\Controller\\ISessionAwareController' => $baseDir . '/../lib/Controller/ISessionAwareController.php', 'OCA\\Text\\Controller\\NavigationController' => $baseDir . '/../lib/Controller/NavigationController.php', 'OCA\\Text\\Controller\\PublicSessionController' => $baseDir . '/../lib/Controller/PublicSessionController.php', 'OCA\\Text\\Controller\\SessionController' => $baseDir . '/../lib/Controller/SessionController.php', 'OCA\\Text\\Controller\\SettingsController' => $baseDir . '/../lib/Controller/SettingsController.php', + 'OCA\\Text\\Controller\\TSessionAwareController' => $baseDir . '/../lib/Controller/TSessionAwareController.php', 'OCA\\Text\\Controller\\UserApiController' => $baseDir . '/../lib/Controller/UserApiController.php', 'OCA\\Text\\Controller\\WorkspaceController' => $baseDir . '/../lib/Controller/WorkspaceController.php', 'OCA\\Text\\Cron\\Cleanup' => $baseDir . '/../lib/Cron/Cleanup.php', diff --git a/composer/composer/autoload_static.php b/composer/composer/autoload_static.php index e15e7fa5700..534ee24ebef 100644 --- a/composer/composer/autoload_static.php +++ b/composer/composer/autoload_static.php @@ -24,12 +24,13 @@ class ComposerStaticInitText 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'OCA\\Text\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', 'OCA\\Text\\Command\\ResetDocument' => __DIR__ . '/..' . '/../lib/Command/ResetDocument.php', - 'OCA\\Text\\Controller\\ASessionAwareController' => __DIR__ . '/..' . '/../lib/Controller/ASessionAwareController.php', 'OCA\\Text\\Controller\\AttachmentController' => __DIR__ . '/..' . '/../lib/Controller/AttachmentController.php', + 'OCA\\Text\\Controller\\ISessionAwareController' => __DIR__ . '/..' . '/../lib/Controller/ISessionAwareController.php', 'OCA\\Text\\Controller\\NavigationController' => __DIR__ . '/..' . '/../lib/Controller/NavigationController.php', 'OCA\\Text\\Controller\\PublicSessionController' => __DIR__ . '/..' . '/../lib/Controller/PublicSessionController.php', 'OCA\\Text\\Controller\\SessionController' => __DIR__ . '/..' . '/../lib/Controller/SessionController.php', 'OCA\\Text\\Controller\\SettingsController' => __DIR__ . '/..' . '/../lib/Controller/SettingsController.php', + 'OCA\\Text\\Controller\\TSessionAwareController' => __DIR__ . '/..' . '/../lib/Controller/TSessionAwareController.php', 'OCA\\Text\\Controller\\UserApiController' => __DIR__ . '/..' . '/../lib/Controller/UserApiController.php', 'OCA\\Text\\Controller\\WorkspaceController' => __DIR__ . '/..' . '/../lib/Controller/WorkspaceController.php', 'OCA\\Text\\Cron\\Cleanup' => __DIR__ . '/..' . '/../lib/Cron/Cleanup.php', diff --git a/cypress/e2e/api/UsersApi.spec.js b/cypress/e2e/api/UsersApi.spec.js index 141776f0e77..2e3d72287ea 100644 --- a/cypress/e2e/api/UsersApi.spec.js +++ b/cypress/e2e/api/UsersApi.spec.js @@ -55,6 +55,7 @@ describe('The user mention API', function() { cy.wrap(connection) .its('document.id') .should('equal', fileId) + const requestData = { method: 'POST', url: '/apps/text/api/v1/users', @@ -66,43 +67,39 @@ describe('The user mention API', function() { }, failOnStatusCode: false, } + const invalidRequestData = { ...requestData } cy.request(requestData).then(({ status }) => { expect(status).to.eq(200) - }) - const invalidRequestData = { ...requestData } - cy.wrap(() => { invalidRequestData.body = { ...requestData.body, sessionToken: 'invalid', } }) + cy.request(invalidRequestData).then(({ status }) => { expect(status).to.eq(403) - }) - - cy.wrap(() => { invalidRequestData.body = { ...requestData.body, sessionId: 0, } }) + cy.request(invalidRequestData).then(({ status }) => { expect(status).to.eq(403) - }) - cy.wrap(() => { invalidRequestData.body = { ...requestData.body, documentId: 0, } }) + cy.request(invalidRequestData).then(({ status }) => { expect(status).to.eq(403) }) - cy.wrap(connection.close()) + cy.wrap(null).then(() => connection.close()) cy.request(requestData).then(({ status, body }) => { expect(status).to.eq(403) diff --git a/lib/Controller/ASessionAwareController.php b/lib/Controller/ASessionAwareController.php deleted file mode 100644 index 6ec6f389793..00000000000 --- a/lib/Controller/ASessionAwareController.php +++ /dev/null @@ -1,25 +0,0 @@ -session = $session; - } - - public function getSession(): Session { - if ($this->session === null) { - throw new InvalidSessionException(); - } - - return $this->session; - } -} diff --git a/lib/Controller/AttachmentController.php b/lib/Controller/AttachmentController.php index 7276f792f88..28898655d88 100644 --- a/lib/Controller/AttachmentController.php +++ b/lib/Controller/AttachmentController.php @@ -29,6 +29,7 @@ use OCA\Text\Exception\UploadException; use OCA\Text\Middleware\Attribute\RequireDocumentSession; use OCA\Text\Service\AttachmentService; +use OCP\AppFramework\ApiController; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; @@ -42,7 +43,8 @@ use OCP\Util; use Psr\Log\LoggerInterface; -class AttachmentController extends ASessionAwareController { +class AttachmentController extends ApiController implements ISessionAwareController { + use TSessionAwareController; public const IMAGE_MIME_TYPES = [ 'image/png', 'image/jpeg', diff --git a/lib/Controller/ISessionAwareController.php b/lib/Controller/ISessionAwareController.php new file mode 100644 index 00000000000..00236bfdc4e --- /dev/null +++ b/lib/Controller/ISessionAwareController.php @@ -0,0 +1,13 @@ +shareManager = $shareManager; - $this->apiService = $apiService; } protected function getPasswordHash(): string { @@ -62,43 +69,36 @@ protected function isPasswordProtected(): bool { return $this->share->getPassword() !== null; } - /** - * @NoAdminRequired - * @PublicPage - */ + #[NoAdminRequired] + #[PublicPage] public function create(string $token, string $file = null, $guestName = null): DataResponse { return $this->apiService->create(null, $file, $token, $guestName); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[NoAdminRequired] + #[PublicPage] public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse { return $this->apiService->close($documentId, $sessionId, $sessionToken); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] public function push(int $documentId, int $sessionId, string $sessionToken, int $version, array $steps, string $awareness, string $token): DataResponse { - return $this->apiService->push($documentId, $sessionId, $sessionToken, $version, $steps, $awareness, $token); + return $this->apiService->push($this->getSession(), $this->getDocument(), $version, $steps, $awareness, $token); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] public function sync(string $token, int $documentId, int $sessionId, string $sessionToken, int $version = 0, string $autosaveContent = null, string $documentState = null, bool $force = false, bool $manualSave = false): DataResponse { - return $this->apiService->sync($documentId, $sessionId, $sessionToken, $version, $autosaveContent, $documentState, $force, $manualSave, $token); + return $this->apiService->sync($this->getSession(), $this->getDocument(), $version, $autosaveContent, $documentState, $force, $manualSave, $token); } - /** - * @NoAdminRequired - * @PublicPage - */ - public function updateSession(int $documentId, int $sessionId, string $sessionToken, string $guestName) { - return $this->apiService->updateSession($documentId, $sessionId, $sessionToken, $guestName); + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] + public function updateSession(string $guestName) { + return $this->apiService->updateSession($this->getSession(), $guestName); } } diff --git a/lib/Controller/SessionController.php b/lib/Controller/SessionController.php index c38e8dc6948..af60aa15655 100644 --- a/lib/Controller/SessionController.php +++ b/lib/Controller/SessionController.php @@ -25,98 +25,87 @@ namespace OCA\Text\Controller; +use OCA\Text\Middleware\Attribute\RequireDocumentSession; use OCA\Text\Service\ApiService; use OCA\Text\Service\NotificationService; use OCA\Text\Service\SessionService; -use OCP\AppFramework\Controller; +use OCP\AppFramework\ApiController; +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\IRequest; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; -class SessionController extends Controller { - private ApiService $apiService; - private SessionService $sessionService; - private NotificationService $notificationService; - private IUserManager $userManager; - private IUserSession $userSession; +class SessionController extends ApiController implements ISessionAwareController { + use TSessionAwareController; private bool $restoreUser = false; private ?IUser $userToRestore = null; - public function __construct(string $appName, IRequest $request, ApiService $apiService, SessionService $sessionService, NotificationService $notificationService, IUserManager $userManager, IUserSession $userSession) { + public function __construct( + string $appName, + IRequest $request, + private ApiService $apiService, + private SessionService $sessionService, + private NotificationService $notificationService, + private IUserManager $userManager, + private IUserSession $userSession) { parent::__construct($appName, $request); - $this->apiService = $apiService; - $this->sessionService = $sessionService; - $this->notificationService = $notificationService; - $this->userManager = $userManager; - $this->userSession = $userSession; } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] public function create(int $fileId = null, string $file = null): DataResponse { return $this->apiService->create($fileId, $file, null, null); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[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 $awareness): DataResponse { + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] + public function push(int $version, array $steps, string $awareness): DataResponse { try { - $this->loginSessionUser($documentId, $sessionId, $sessionToken); - return $this->apiService->push($documentId, $sessionId, $sessionToken, $version, $steps, $awareness); + $this->loginSessionUser(); + return $this->apiService->push($this->getSession(), $this->getDocument(), $version, $steps, $awareness); } finally { $this->restoreSessionUser(); } } - /** - * @NoAdminRequired - * @PublicPage - */ - public function sync(int $documentId, int $sessionId, string $sessionToken, int $version = 0, string $autosaveContent = null, string $documentState = null, bool $force = false, bool $manualSave = false): DataResponse { + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] + public function sync(int $version = 0, string $autosaveContent = null, string $documentState = null, bool $force = false, bool $manualSave = false): DataResponse { try { - $this->loginSessionUser($documentId, $sessionId, $sessionToken); - return $this->apiService->sync($documentId, $sessionId, $sessionToken, $version, $autosaveContent, $documentState, $force, $manualSave); + $this->loginSessionUser(); + return $this->apiService->sync($this->getSession(), $this->getDocument(), $version, $autosaveContent, $documentState, $force, $manualSave); } finally { $this->restoreSessionUser(); } } - /** - * @NoAdminRequired - * @PublicPage - * @UserRateThrottle(limit=5, period=120) - */ - public function mention(int $documentId, int $sessionId, string $sessionToken, string $mention): DataResponse { - if (!$this->sessionService->isValidSession($documentId, $sessionId, $sessionToken)) { + #[NoAdminRequired] + #[PublicPage] + #[RequireDocumentSession] + #[UserRateLimit(limit: 5, period: 120)] + public function mention(string $mention): DataResponse { + if ($this->getSession()->getUserId() === null && !$this->sessionService->isUserInDocument($this->getDocument()->getId(), $mention)) { return new DataResponse([], 403); } - $currentSession = $this->sessionService->getSession($documentId, $sessionId, $sessionToken); - - if ($currentSession->getUserId() === null && !$this->sessionService->isUserInDocument($documentId, $mention)) { - return new DataResponse([], 403); - } - - return new DataResponse($this->notificationService->mention($documentId, $mention)); + return new DataResponse($this->notificationService->mention($this->getDocument()->getId(), $mention)); } - private function loginSessionUser(int $documentId, int $sessionId, string $sessionToken) { - $currentSession = $this->sessionService->getSession($documentId, $sessionId, $sessionToken); - if ($currentSession !== null && !$this->userSession->isLoggedIn()) { + private function loginSessionUser() { + $currentSession = $this->getSession(); + if (!$this->userSession->isLoggedIn()) { $user = $this->userManager->get($currentSession->getUserId()); if ($user !== null) { $this->restoreUser = true; diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index c55b3764934..a901bc611e9 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -26,6 +26,7 @@ use OCA\Text\AppInfo\Application; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\IConfig; use OCP\IRequest; @@ -46,16 +47,14 @@ public function __construct($appName, IRequest $request, IConfig $config, $userI } /** - * @NoAdminRequired - * @param string $key - * @param string $value - * @return DataResponse * @throws \OCP\PreConditionNotMetException */ + #[NoAdminRequired] public function updateConfig(string $key, $value) { if (!in_array($key, self::ACCEPTED_KEYS, true)) { return new DataResponse(['message' => 'Invalid config key'], Http::STATUS_BAD_REQUEST); } + /** @psalm-suppress PossiblyNullArgument */ $this->config->setUserValue($this->userId, Application::APP_NAME, $key, $value); return new DataResponse([ $key => $value diff --git a/lib/Controller/TSessionAwareController.php b/lib/Controller/TSessionAwareController.php new file mode 100644 index 00000000000..b4eb200acef --- /dev/null +++ b/lib/Controller/TSessionAwareController.php @@ -0,0 +1,39 @@ +textSession = $session; + } + + public function setDocument(?Document $document): void { + $this->document = $document; + } + + public function getSession(): Session { + if ($this->textSession === null) { + throw new InvalidSessionException(); + } + + return $this->textSession; + } + + public function getDocument(): Document { + if ($this->document === null) { + throw new InvalidSessionException(); + } + + return $this->document; + } + +} diff --git a/lib/Controller/UserApiController.php b/lib/Controller/UserApiController.php index ff48a843e15..e8beab58cac 100644 --- a/lib/Controller/UserApiController.php +++ b/lib/Controller/UserApiController.php @@ -6,6 +6,7 @@ use OCA\Text\Middleware\Attribute\RequireDocumentSession; use OCA\Text\Service\SessionService; +use OCP\AppFramework\ApiController; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; @@ -14,7 +15,9 @@ use OCP\IUserManager; use OCP\Share\IShare; -class UserApiController extends ASessionAwareController { +class UserApiController extends ApiController implements ISessionAwareController { + use TSessionAwareController; + public function __construct( string $appName, IRequest $request, diff --git a/lib/Controller/WorkspaceController.php b/lib/Controller/WorkspaceController.php index 31ef6ace052..dd76762e639 100644 --- a/lib/Controller/WorkspaceController.php +++ b/lib/Controller/WorkspaceController.php @@ -48,19 +48,22 @@ use Exception; use OCA\Text\AppInfo\Application; +use OCA\Text\DirectEditing\TextDocumentCreator; use OCA\Text\Service\WorkspaceService; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\Constants; use OCP\DirectEditing\IManager as IDirectEditingManager; use OCP\DirectEditing\RegisterDirectEditorEvent; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; -use OCP\Files\StorageNotAvailableException; use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; @@ -69,43 +72,31 @@ use Psr\Log\LoggerInterface; class WorkspaceController extends OCSController { - private IRootFolder $rootFolder; - private IManager $shareManager; - private WorkspaceService $workspaceService; - private ?string $userId; - private IDirectEditingManager $directEditingManager; - private IURLGenerator $urlGenerator; - - /** @var IEventDispatcher */ - private $eventDispatcher; - - /** @var LoggerInterface */ - private $logger; - - /** @var ISession */ - private $session; - - public function __construct($appName, IRequest $request, IRootFolder $rootFolder, IManager $shareManager, IDirectEditingManager $directEditingManager, IURLGenerator $urlGenerator, WorkspaceService $workspaceService, IEventDispatcher $eventDispatcher, LoggerInterface $logger, ISession $session, $userId) { + public function __construct( + string $appName, + IRequest $request, + private IRootFolder $rootFolder, + private IManager $shareManager, + private IDirectEditingManager $directEditingManager, + private IURLGenerator $urlGenerator, + private WorkspaceService $workspaceService, + private IEventDispatcher $eventDispatcher, + private LoggerInterface $logger, + private ISession $session, + private ?string $userId + ) { parent::__construct($appName, $request); - $this->rootFolder = $rootFolder; - $this->shareManager = $shareManager; - $this->workspaceService = $workspaceService; - $this->userId = $userId; - $this->directEditingManager = $directEditingManager; - $this->urlGenerator = $urlGenerator; - $this->eventDispatcher = $eventDispatcher; - $this->logger = $logger; - $this->session = $session; } /** - * @NoAdminRequired - * * Checks for available files in the current folder and returns required details to present * the rich workspace */ + #[NoAdminRequired] public function folder(string $path = '/'): DataResponse { + /** */ try { + /** @psalm-suppress PossiblyNullArgument */ $userFolder = $this->rootFolder->getUserFolder($this->userId); $folder = $userFolder->get($path); if ($folder instanceof Folder) { @@ -131,21 +122,23 @@ public function folder(string $path = '/'): DataResponse { ] ]); } - } catch (NotFoundException | NotPermittedException $e) { + } catch (NotFoundException|NotPermittedException) { return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } catch (Exception $e) { $this->logger->error('Failed to get workspace file', ['exception' => $e]); return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } + + return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } /** - * @NoAdminRequired - * @PublicPage - * * Checks for available files in the current folder and returns required details to present * the rich workspace + * @api */ + #[NoAdminRequired] + #[PublicPage] public function publicFolder(string $shareToken, string $path = '/'): DataResponse { try { $share = $this->shareManager->getShareByToken($shareToken); @@ -158,9 +151,11 @@ public function publicFolder(string $shareToken, string $path = '/'): DataRespon throw new ShareNotFound(); } } - $folder = $share->getNode()->get($path); - if ($folder instanceof Folder) { - $file = $this->workspaceService->getFile($folder); + + $shareNode = $share->getNode(); + $node = $shareNode instanceof File ? $shareNode : $shareNode->get($path); + if ($node instanceof Folder) { + $file = $this->workspaceService->getFile($node); if ($file === null) { return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } @@ -174,26 +169,27 @@ public function publicFolder(string $shareToken, string $path = '/'): DataRespon ] ]); } - } catch (NotFoundException | ShareNotFound | StorageNotAvailableException $e) { + } catch (NotFoundException|ShareNotFound) { return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } catch (Exception $e) { $this->logger->error('Failed to get public workspace file', ['exception' => $e]); return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } + + return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] public function direct(string $path): DataResponse { $this->eventDispatcher->dispatchTyped(new RegisterDirectEditorEvent($this->directEditingManager)); try { + /** @psalm-suppress PossiblyNullArgument */ $folder = $this->rootFolder->getUserFolder($this->userId)->get($path); if ($folder instanceof Folder) { $file = $this->getFile($folder); if ($file === null) { - $token = $this->directEditingManager->create($path . '/'. $this->workspaceService->getSupportedFilenames()[0], Application::APP_NAME, 'textdocument'); + $token = $this->directEditingManager->create($path . '/'. $this->workspaceService->getSupportedFilenames()[0], Application::APP_NAME, TextDocumentCreator::CREATOR_ID); } else { $token = $this->directEditingManager->open($path . '/'. $file->getName(), Application::APP_NAME); } @@ -205,14 +201,19 @@ public function direct(string $path): DataResponse { $this->logger->error('Exception when creating a new file through direct editing', ['exception' => $e]); return new DataResponse('Failed to create file', Http::STATUS_FORBIDDEN); } + + return new DataResponse(['message' => 'No workspace file found'], Http::STATUS_NOT_FOUND); } - private function getFile(Folder $folder) { + private function getFile(Folder $folder): ?File { $file = null; foreach ($this->workspaceService->getSupportedFilenames() as $filename) { - if ($folder->nodeExists($filename)) { - $file = $folder->get($filename); - continue; + try { + $node = $folder->get($filename); + if ($node instanceof File) { + $file = $node; + } + } catch (NotFoundException) { } } return $file; diff --git a/lib/DirectEditing/TextDirectEditor.php b/lib/DirectEditing/TextDirectEditor.php index 357c73c641b..dfec634ac2d 100644 --- a/lib/DirectEditing/TextDirectEditor.php +++ b/lib/DirectEditing/TextDirectEditor.php @@ -79,7 +79,7 @@ public function getName(): string { /** * A list of mimetypes that should open the editor by default * - * @return array + * @return string[] */ public function getMimetypes(): array { return [ @@ -112,7 +112,7 @@ public function getMimetypes(): array { /** * A list of mimetypes that can be opened in the editor optionally * - * @return array + * @return string[] */ public function getMimetypesOptional(): array { return []; @@ -121,7 +121,7 @@ public function getMimetypesOptional(): array { /** * Return a list of file creation options to be presented to the user * - * @return array of ACreateFromTemplate|ACreateEmpty + * @return TextDocumentCreator[] */ public function getCreators(): array { return [ diff --git a/lib/DirectEditing/TextDocumentCreator.php b/lib/DirectEditing/TextDocumentCreator.php index 9d09870fbfd..3de22b15299 100644 --- a/lib/DirectEditing/TextDocumentCreator.php +++ b/lib/DirectEditing/TextDocumentCreator.php @@ -27,6 +27,7 @@ use OCP\IL10N; class TextDocumentCreator extends ACreateEmpty { + public const CREATOR_ID = 'textdocument'; /** * @var IL10N @@ -38,7 +39,7 @@ public function __construct(IL10N $l10n) { } public function getId(): string { - return 'textdocument'; + return self::CREATOR_ID; } public function getName(): string { diff --git a/lib/Listeners/BeforeNodeDeletedListener.php b/lib/Listeners/BeforeNodeDeletedListener.php index 182f02f82e9..2f1143b4e0d 100644 --- a/lib/Listeners/BeforeNodeDeletedListener.php +++ b/lib/Listeners/BeforeNodeDeletedListener.php @@ -45,8 +45,9 @@ public function handle(Event $event): void { if (!$event instanceof BeforeNodeDeletedEvent) { return; } - if ($event->getNode() instanceof File && $event->getNode()->getMimeType() === 'text/markdown') { - $this->attachmentService->deleteAttachments($event->getNode()); + $node = $event->getNode(); + if ($node instanceof File && $node->getMimeType() === 'text/markdown') { + $this->attachmentService->deleteAttachments($node); } } } diff --git a/lib/Listeners/BeforeNodeRenamedListener.php b/lib/Listeners/BeforeNodeRenamedListener.php index b82a2ab59a9..dec178ee851 100644 --- a/lib/Listeners/BeforeNodeRenamedListener.php +++ b/lib/Listeners/BeforeNodeRenamedListener.php @@ -45,11 +45,13 @@ public function handle(Event $event): void { if (!$event instanceof BeforeNodeRenamedEvent) { return; } - if ($event->getSource() instanceof File - && $event->getSource()->getMimeType() === 'text/markdown' - && $event->getTarget() instanceof File + $source = $event->getSource(); + $target = $event->getTarget(); + if ($source instanceof File + && $source->getMimeType() === 'text/markdown' + && $target instanceof File ) { - $this->attachmentService->moveAttachments($event->getSource(), $event->getTarget()); + $this->attachmentService->moveAttachments($source, $target); } } } diff --git a/lib/Listeners/NodeCopiedListener.php b/lib/Listeners/NodeCopiedListener.php index 8807cc22cb3..4f465a7f8e3 100644 --- a/lib/Listeners/NodeCopiedListener.php +++ b/lib/Listeners/NodeCopiedListener.php @@ -45,12 +45,14 @@ public function handle(Event $event): void { if (!$event instanceof NodeCopiedEvent) { return; } - if ($event->getSource() instanceof File - && $event->getSource()->getMimeType() === 'text/markdown' - && $event->getTarget() instanceof File - && $event->getTarget()->getMimeType() === 'text/markdown' + $source = $event->getSource(); + $target = $event->getTarget(); + if ($source instanceof File + && $source->getMimeType() === 'text/markdown' + && $target instanceof File + && $target->getMimeType() === 'text/markdown' ) { - $this->attachmentService->copyAttachments($event->getSource(), $event->getTarget()); + $this->attachmentService->copyAttachments($source, $target); } } } diff --git a/lib/Middleware/SessionMiddleware.php b/lib/Middleware/SessionMiddleware.php index 7c403958387..6205f287581 100644 --- a/lib/Middleware/SessionMiddleware.php +++ b/lib/Middleware/SessionMiddleware.php @@ -2,9 +2,10 @@ namespace OCA\Text\Middleware; -use OCA\Text\Controller\ASessionAwareController; +use OCA\Text\Controller\ISessionAwareController; use OCA\Text\Exception\InvalidSessionException; use OCA\Text\Middleware\Attribute\RequireDocumentSession; +use OCA\Text\Service\DocumentService; use OCA\Text\Service\SessionService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; @@ -16,6 +17,7 @@ class SessionMiddleware extends \OCP\AppFramework\Middleware { public function __construct( private IRequest $request, private SessionService $sessionService, + private DocumentService $documentService, ) { } @@ -24,7 +26,7 @@ public function __construct( * @throws InvalidSessionException */ public function beforeController(Controller $controller, string $methodName) { - if (!$controller instanceof ASessionAwareController) { + if (!$controller instanceof ISessionAwareController) { return; } @@ -35,7 +37,7 @@ public function beforeController(Controller $controller, string $methodName) { } } - private function assertDocumentSession(ASessionAwareController $controller): void { + private function assertDocumentSession(ISessionAwareController $controller): void { $documentId = (int)$this->request->getParam('documentId'); $sessionId = (int)$this->request->getParam('sessionId'); $token = (string)$this->request->getParam('sessionToken'); @@ -45,7 +47,13 @@ private function assertDocumentSession(ASessionAwareController $controller): voi throw new InvalidSessionException(); } + $document = $this->documentService->getDocument($documentId); + if (!$document) { + throw new InvalidSessionException(); + } + $controller->setSession($session); + $controller->setDocument($document); } public function afterException($controller, $methodName, \Exception $exception) { diff --git a/lib/Service/ApiService.php b/lib/Service/ApiService.php index 5cb3f2b1f83..421e3aa3647 100644 --- a/lib/Service/ApiService.php +++ b/lib/Service/ApiService.php @@ -28,9 +28,10 @@ use Exception; use InvalidArgumentException; -use OC\Files\Node\File; use OCA\Files_Sharing\SharedStorage; use OCA\Text\AppInfo\Application; +use OCA\Text\Db\Document; +use OCA\Text\Db\Session; use OCA\Text\Exception\DocumentSaveConflictException; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; @@ -71,9 +72,8 @@ public function __construct(IRequest $request, $this->l10n = $l10n; } - public function create($fileId = null, $filePath = null, $token = null, $guestName = null): DataResponse { + public function create($fileId = null, $filePath = null, ?string $token = null, $guestName = null): DataResponse { try { - /** @var File $file */ if ($token) { $file = $this->documentService->getFileByShareToken($token, $this->request->getParam('filePath')); @@ -104,7 +104,8 @@ public function create($fileId = null, $filePath = null, $token = null, $guestNa if ($storage->instanceOfStorage(SharedStorage::class)) { /** @var IShare $share */ $share = $storage->getShare(); - if ($share->getAttributes()->getAttribute('permissions', 'download') === false) { + $shareAttribtues = $share->getAttributes(); + if ($shareAttribtues !== null && $shareAttribtues->getAttribute('permissions', 'download') === false) { return new DataResponse($this->l10n->t('This file cannot be displayed as download is disabled by the share'), 403); } } @@ -112,7 +113,7 @@ public function create($fileId = null, $filePath = null, $token = null, $guestNa $readOnly = $this->documentService->isReadOnly($file, $token); $this->sessionService->removeInactiveSessionsWithoutSteps($file->getId()); - $document = $this->documentService->getDocument($file); + $document = $this->documentService->getDocument($file->getId()); $freshSession = $document === null; if ($freshSession) { @@ -184,16 +185,9 @@ public function close($documentId, $sessionId, $sessionToken): DataResponse { * @throws NotFoundException * @throws DoesNotExistException */ - public function push($documentId, $sessionId, $sessionToken, $version, $steps, $awareness, $token = null): DataResponse { - if (!$this->sessionService->isValidSession($documentId, $sessionId, $sessionToken)) { - return new DataResponse([], 403); - } - $session = $this->sessionService->getSession($documentId, $sessionId, $sessionToken); - if (!$session) { - return new DataResponse([], 403); - } + public function push(Session $session, Document $document, $version, $steps, $awareness, $token = null): DataResponse { try { - $this->sessionService->updateSessionAwareness($documentId, $sessionId, $sessionToken, $awareness); + $session = $this->sessionService->updateSessionAwareness($session, $awareness); } catch (DoesNotExistException $e) { // Session was removed in the meantime. #3875 return new DataResponse([], 403); @@ -206,7 +200,7 @@ public function push($documentId, $sessionId, $sessionToken, $version, $steps, $ return new DataResponse([], 403); } try { - $result = $this->documentService->addStep($documentId, $sessionId, $steps, $version); + $result = $this->documentService->addStep($document, $session, $steps, $version); } catch (InvalidArgumentException $e) { return new DataResponse($e->getMessage(), 422); } catch (DoesNotExistException $e) { @@ -216,19 +210,15 @@ public function push($documentId, $sessionId, $sessionToken, $version, $steps, $ return new DataResponse($result); } - public function sync($documentId, $sessionId, $sessionToken, $version = 0, $autosaveContent = null, $documentState = null, bool $force = false, bool $manualSave = false, $token = null): DataResponse { - if (!$this->sessionService->isValidSession($documentId, $sessionId, $sessionToken)) { - return new DataResponse([], 403); - } - + public function sync(Session $session, Document $document, $version = 0, $autosaveContent = null, $documentState = null, bool $force = false, bool $manualSave = false, $token = null): DataResponse { + $documentId = $session->getDocumentId(); try { $result = [ 'steps' => $this->documentService->getSteps($documentId, $version), 'sessions' => $this->sessionService->getAllSessions($documentId), - 'document' => $this->documentService->get($documentId) + 'document' => $document, ]; - $session = $this->sessionService->getSession($documentId, $sessionId, $sessionToken); $file = $this->documentService->getFileForSession($session, $token); } catch (NotFoundException $e) { $this->logger->info($e->getMessage(), ['exception' => $e]); @@ -243,7 +233,7 @@ public function sync($documentId, $sessionId, $sessionToken, $version = 0, $auto } try { - $result['document'] = $this->documentService->autosave($file, $documentId, $version, $autosaveContent, $documentState, $force, $manualSave, $token, $this->request->getParam('filePath')); + $result['document'] = $this->documentService->autosave($document, $file, $version, $autosaveContent, $documentState, $force, $manualSave, $token, $this->request->getParam('filePath')); } catch (DocumentSaveConflictException $e) { try { $result['outsideChange'] = $file->getContent(); @@ -262,15 +252,8 @@ public function sync($documentId, $sessionId, $sessionToken, $version = 0, $auto return new DataResponse($result, isset($result['outsideChange']) ? 409 : 200); } - /** - * @throws DoesNotExistException - */ - public function updateSession(int $documentId, int $sessionId, string $sessionToken, string $guestName): DataResponse { - if (!$this->sessionService->isValidSession($documentId, $sessionId, $sessionToken)) { - return new DataResponse([], 403); - } - - return new DataResponse($this->sessionService->updateSession($documentId, $sessionId, $sessionToken, $guestName)); + public function updateSession(Session $session, string $guestName): DataResponse { + return new DataResponse($this->sessionService->updateSession($session, $guestName)); } private function loadContent(\OCP\Files\File $file): ?string { diff --git a/lib/Service/DocumentService.php b/lib/Service/DocumentService.php index aadfc825c67..83f0bab7d2f 100644 --- a/lib/Service/DocumentService.php +++ b/lib/Service/DocumentService.php @@ -37,7 +37,6 @@ use OCA\Text\Exception\DocumentHasUnsavedChangesException; use OCA\Text\Exception\DocumentSaveConflictException; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Db\Entity; use OCP\Constants; use OCP\DB\Exception; use OCP\DirectEditing\IManager; @@ -112,24 +111,23 @@ public function __construct(DocumentMapper $documentMapper, StepMapper $stepMapp } } - public function getDocument(File $file): ?Document { + public function getDocument(int $id): ?Document { try { - return $this->documentMapper->find($file->getId()); + return $this->documentMapper->find($id); } catch (DoesNotExistException|NotFoundException $e) { return null; } } /** - * @param File $file - * @return Entity * @throws NotFoundException * @throws InvalidPathException * @throws NotPermittedException + * @throws Exception */ public function createDocument(File $file): Document { try { - $document = $this->documentMapper->find($file->getFileInfo()->getId()); + $document = $this->documentMapper->find($file->getId()); // Do not hard reset if changed from outside since this will throw away possible steps // This way the user can still resolve conflicts in the editor view @@ -149,9 +147,9 @@ public function createDocument(File $file): Document { } $document = new Document(); - $document->setId($file->getFileInfo()->getId()); + $document->setId($file->getId()); $document->setLastSavedVersion(0); - $document->setLastSavedVersionTime($file->getFileInfo()->getMtime()); + $document->setLastSavedVersionTime($file->getMTime()); $document->setLastSavedVersionEtag($file->getEtag()); $document->setBaseVersionEtag($file->getEtag()); try { @@ -160,7 +158,7 @@ public function createDocument(File $file): Document { } catch (Exception $e) { if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) { // Document might have been created in the meantime - return $this->documentMapper->find($file->getFileInfo()->getId()); + return $this->documentMapper->find($file->getId()); } throw $e; @@ -207,11 +205,6 @@ public function writeDocumentState(int $documentId, string $content): void { $documentStateFile->putContent($content); } - - public function get($documentId) { - return $this->documentMapper->find($documentId); - } - /** * @param $documentId * @param $sessionId @@ -221,7 +214,9 @@ public function get($documentId) { * @throws DoesNotExistException * @throws InvalidArgumentException */ - public function addStep($documentId, $sessionId, $steps, $version): array { + public function addStep(Document $document, Session $session, $steps, $version): array { + $sessionId = $session->getId(); + $documentId = $session->getDocumentId(); $stepsToInsert = []; $querySteps = []; $getStepsSinceVersion = null; @@ -238,7 +233,7 @@ public function addStep($documentId, $sessionId, $steps, $version): array { } } if (sizeof($stepsToInsert) > 0) { - $newVersion = $this->insertSteps($documentId, $sessionId, $stepsToInsert, $version); + $newVersion = $this->insertSteps($document, $session, $stepsToInsert, $version); } // If there were any queries in the steps send the entire history $getStepsSinceVersion = count($querySteps) > 0 ? 0 : $version; @@ -264,34 +259,30 @@ public function addStep($documentId, $sessionId, $steps, $version): array { * @throws DoesNotExistException * @throws InvalidArgumentException */ - private function insertSteps($documentId, $sessionId, $steps, $version): int { - $document = null; + private function insertSteps(Document $document, Session $session, $steps, $version): int { $stepsVersion = null; try { - $document = $this->documentMapper->find($documentId); $stepsJson = json_encode($steps); if (!is_array($steps) || $stepsJson === null) { throw new InvalidArgumentException('Failed to encode steps'); } $stepsVersion = $this->stepMapper->getLatestVersion($document->getId()); $newVersion = $stepsVersion + count($steps); - $this->logger->debug("Adding steps to $documentId: bumping version from $stepsVersion to $newVersion"); + $this->logger->debug("Adding steps to " . $document->getId() . ": bumping version from $stepsVersion to $newVersion"); $this->cache->set('document-version-' . $document->getId(), $newVersion); $step = new Step(); $step->setData($stepsJson); - $step->setSessionId($sessionId); - $step->setDocumentId($documentId); + $step->setSessionId($session->getId()); + $step->setDocumentId($document->getId()); $step->setVersion($newVersion); $this->stepMapper->insert($step); // TODO write steps to cache for quicker reading return $newVersion; - } catch (DoesNotExistException $e) { - throw $e; } catch (\Throwable $e) { if ($document !== null && $stepsVersion !== null) { $this->logger->error('This should never happen. An error occurred when storing the version, trying to recover the last stable one', ['exception' => $e]); $this->cache->set('document-version-' . $document->getId(), $stepsVersion); - $this->stepMapper->deleteAfterVersion($documentId, $stepsVersion); + $this->stepMapper->deleteAfterVersion($document->getId(), $stepsVersion); } throw $e; } @@ -312,10 +303,8 @@ public function getSteps($documentId, $lastVersion): array { * @throws NotPermittedException * @throws Exception */ - public function autosave(?File $file, int $documentId, int $version, ?string $autoSaveDocument, ?string $documentState, bool $force = false, bool $manualSave = false, ?string $shareToken = null, ?string $filePath = null): Document { - /** @var Document $document */ - $document = $this->documentMapper->find($documentId); - + public function autosave(Document $document, ?File $file, int $version, ?string $autoSaveDocument, ?string $documentState, bool $force = false, bool $manualSave = false, ?string $shareToken = null, ?string $filePath = null): Document { + $documentId = $document->getId(); if ($file === null) { throw new NotFoundException(); } @@ -342,7 +331,7 @@ public function autosave(?File $file, int $documentId, int $version, ?string $au // Do not save if newer version already saved // Note that $version is the version of the steps the client has fetched. // It may have added steps on top of that - so if the versions match we still save. - $stepsVersion = $this->stepMapper->getLatestVersion($documentId); + $stepsVersion = $this->stepMapper->getLatestVersion($documentId)?: 0; $savedVersion = $document->getLastSavedVersion(); $outdated = $savedVersion > 0 && $savedVersion > $version; if (!$force && ($outdated || $version > (string)$stepsVersion)) { @@ -438,15 +427,17 @@ public function getAll() { } /** - * @param Session $session - * @param $shareToken - * @return File * @throws NotFoundException */ public function getFileForSession(Session $session, ?string $shareToken = null): File { - if ($session->getUserId() !== null && $shareToken === null) { + if ($session->getUserId() !== null) { return $this->getFileById($session->getDocumentId(), $session->getUserId()); } + + if ($shareToken === null) { + throw new \InvalidArgumentException('No proper share data'); + } + try { $share = $this->shareManager->getShareByToken($shareToken); } catch (ShareNotFound $e) { @@ -498,13 +489,19 @@ public function getFileById($fileId, $userId = null): File { return ($b->getPermissions() & Constants::PERMISSION_UPDATE) <=> ($a->getPermissions() & Constants::PERMISSION_UPDATE); }); - return array_shift($files); + $file = array_shift($files); + + if (!$file instanceof File) { + throw new NotFoundException(); + } + + return $file; } /** * @throws NotFoundException */ - public function getFileByShareToken($shareToken, ?string $path = null): File { + public function getFileByShareToken(string $shareToken, ?string $path = null): File { try { $share = $this->shareManager->getShareByToken($shareToken); } catch (ShareNotFound $e) { @@ -512,7 +509,7 @@ public function getFileByShareToken($shareToken, ?string $path = null): File { } $node = $share->getNode(); - if ($node instanceof Folder) { + if ($path !== null && $node instanceof Folder) { $node = $node->get($path); } if ($node instanceof File) { @@ -560,7 +557,7 @@ public function getLockInfo($file): ?ILock { * @return void * @throws NotFoundException|NotPermittedException */ - public function checkSharePermissions($shareToken, $permission = Constants::PERMISSION_READ): void { + public function checkSharePermissions(string $shareToken, $permission = Constants::PERMISSION_READ): void { try { $share = $this->shareManager->getShareByToken($shareToken); } catch (ShareNotFound $e) { diff --git a/lib/Service/SessionService.php b/lib/Service/SessionService.php index 34b1e8b6dcc..ddcda3038ec 100644 --- a/lib/Service/SessionService.php +++ b/lib/Service/SessionService.php @@ -115,8 +115,9 @@ public function getAllSessions(int $documentId): array { $sessions = $this->sessionMapper->findAll($documentId); return array_map(function (Session $session) { $result = $session->jsonSerialize(); - if ($session->getUserId() !== null) { - $result['displayName'] = $this->userManager->getDisplayName($session->getUserId()); + $userId = $session->getUserId(); + if ($userId !== null) { + $result['displayName'] = $this->userManager->getDisplayName($userId); } return $result; }, $sessions); @@ -126,16 +127,18 @@ public function getActiveSessions(int $documentId): array { $sessions = $this->sessionMapper->findAllActive($documentId); return array_map(function (Session $session) { $result = $session->jsonSerialize(); - if ($session->getUserId() !== null) { - $result['displayName'] = $this->userManager->getDisplayName($session->getUserId()); + $userId = $session->getUserId(); + if ($userId !== null) { + $result['displayName'] = $this->userManager->getDisplayName($userId); } return $result; }, $sessions); } public function getNameForSession(Session $session): ?string { - if ($session->getUserId() !== null) { - return $this->userManager->getDisplayName($session->getUserId()); + $userId = $session->getUserId(); + if ($userId !== null) { + return $this->userManager->getDisplayName($userId); } return $session->getGuestName(); @@ -217,11 +220,10 @@ public function isValidSession($documentId, $sessionId, $token): bool { * @return Session * @throws DoesNotExistException */ - public function updateSession(int $documentId, int $sessionId, string $sessionToken, string $guestName): Session { + public function updateSession(Session $session, string $guestName): Session { if ($this->userId !== null) { throw new \Exception('Logged in users cannot set a guest name'); } - $session = $this->sessionMapper->find($documentId, $sessionId, $sessionToken); $session->setGuestName($guestName); $session->setColor($this->getColorForGuestName($guestName)); return $this->sessionMapper->update($session); @@ -235,8 +237,7 @@ public function updateSession(int $documentId, int $sessionId, string $sessionTo * @return Session * @throws DoesNotExistException */ - public function updateSessionAwareness(int $documentId, int $sessionId, string $sessionToken, string $message): Session { - $session = $this->sessionMapper->find($documentId, $sessionId, $sessionToken); + public function updateSessionAwareness(Session $session, string $message): Session { if (empty($message)) { return $session; } diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 917bf996c2a..89e312639a9 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -1,112 +1,22 @@ - - - - RegisterDirectEditorEventListener::class - - - BeforeTemplateRenderedEvent - LoadAdditionalScriptsEvent - LoadViewer - - - - - InvalidTokenException - - + - - DataResponse - DataResponse - DataResponse - - - $this->rootFolder - $this->rootFolder - IRootFolder - IRootFolder - - + open - + ServerPlugin - - array - array - array - - + getToken - - - LoadAdditionalScriptsEvent - - - - - LoadViewer - - - - - - - - Entity - - - $this->rootFolder - IRootFolder - IRootFolder - - - \OC\User\NoUserException - - - - - $this->rootFolder - $this->rootFolder - $this->rootFolder - $this->rootFolder - IRootFolder - IRootFolder - - - ClientException - ConnectException - ServerException - - - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - \OC\User\NoUserException - - - + $jobList diff --git a/tests/stub.phpstub b/tests/stub.phpstub index dd05e5794a4..327ea0cb171 100644 --- a/tests/stub.phpstub +++ b/tests/stub.phpstub @@ -10,6 +10,10 @@ namespace OC\AppFramework\OCS { class BaseResponse {} } +namespace OCA\Files\Event { + class LoadAdditionalScriptsEvent extends \OCP\EventDispatcher\Event {} +} + namespace OCA\Viewer\Event { class LoadViewer extends \OCP\EventDispatcher\Event {} }