diff --git a/lib/Controller/WorkspaceController.php b/lib/Controller/WorkspaceController.php index 52ea5e843e9..d83f9f365f6 100644 --- a/lib/Controller/WorkspaceController.php +++ b/lib/Controller/WorkspaceController.php @@ -132,7 +132,9 @@ public function publicFolder(string $shareToken, string $path = '/'): DataRespon /** @psalm-suppress RedundantConditionGivenDocblockType */ if ($share->getPassword() !== null) { $shareIds = $this->session->get('public_link_authenticated'); - if ($share->getId() !== $shareIds && (is_array($shareIds) && !in_array($share->getId(), $shareIds, true))) { + $shareIds = is_array($shareIds) ? $shareIds : [$shareIds]; + + if (!in_array($share->getId(), $shareIds, true)) { throw new ShareNotFound(); } } diff --git a/lib/Middleware/SessionMiddleware.php b/lib/Middleware/SessionMiddleware.php index fa9d4255c55..b291d9a66fc 100644 --- a/lib/Middleware/SessionMiddleware.php +++ b/lib/Middleware/SessionMiddleware.php @@ -144,7 +144,9 @@ private function assertUserOrShareToken(ISessionAwareController $controller): vo if ($share->getPassword() !== null) { $shareIds = $this->session->get('public_link_authenticated'); - if ($share->getId() !== $shareIds && (is_array($shareIds) && !in_array($share->getId(), $shareIds, true))) { + $shareIds = is_array($shareIds) ? $shareIds : [$shareIds]; + + if (!in_array($share->getId(), $shareIds, true)) { throw new InvalidSessionException(); } } diff --git a/tests/unit/Middleware/SessionMiddlewareTest.php b/tests/unit/Middleware/SessionMiddlewareTest.php new file mode 100644 index 00000000000..647a5c6843f --- /dev/null +++ b/tests/unit/Middleware/SessionMiddlewareTest.php @@ -0,0 +1,117 @@ +request = $this->createMock(IRequest::class); + $this->session = $this->createMock(ISession::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->shareManager = $this->createMock(IManager::class); + + $this->middleware = new SessionMiddleware( + $this->request, + $this->createMock(SessionService::class), + $this->createMock(DocumentService::class), + $this->session, + $this->userSession, + $this->rootFolder, + $this->shareManager, + $this->createMock(IL10N::class), + ); + } + + public function testUnauthenticatedAccessBlocked(): void { + $this->expectException(InvalidSessionException::class); + + $share = $this->createPasswordProtectedShare('42'); + $this->session->method('get')->with('public_link_authenticated')->willReturn(null); + + $this->invokeMiddleware($share); + } + + public function testAuthenticatedSingleIdAllowed(): void { + $share = $this->createPasswordProtectedShare('42'); + $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); + + $this->invokeMiddleware($share); + $this->assertTrue(true); + } + + public function testAuthenticatedArrayAllowed(): void { + $share = $this->createPasswordProtectedShare('42'); + $this->session->method('get')->with('public_link_authenticated')->willReturn(['40', '42', '44']); + + $this->invokeMiddleware($share); + $this->assertTrue(true); + } + + public function testWrongSingleIdBlocked(): void { + $this->expectException(InvalidSessionException::class); + + $share = $this->createPasswordProtectedShare('42'); + $this->session->method('get')->with('public_link_authenticated')->willReturn('99'); + + $this->invokeMiddleware($share); + } + + public function testWrongArrayBlocked(): void { + $this->expectException(InvalidSessionException::class); + + $share = $this->createPasswordProtectedShare('42'); + $this->session->method('get')->with('public_link_authenticated')->willReturn(['10', '20', '30']); + + $this->invokeMiddleware($share); + } + + private function createPasswordProtectedShare(string $id): IShare { + $share = $this->createMock(IShare::class); + $share->method('getId')->willReturn($id); + $share->method('getPassword')->willReturn('password'); + $share->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ); + $share->method('getShareOwner')->willReturn('owner'); + $share->method('getAttributes')->willReturn(null); + return $share; + } + + private function invokeMiddleware(IShare $share): void { + $this->request->method('getParam')->willReturnMap([ + ['documentId', null, 999], + ['shareToken', null, 'token'], + ]); + $this->userSession->method('getUser')->willReturn(null); + $this->shareManager->method('getShareByToken')->willReturn($share); + + $folder = $this->createMock(Folder::class); + $folder->method('getFirstNodeById')->willReturn($this->createMock(\OCP\Files\File::class)); + $this->rootFolder->method('getUserFolder')->willReturn($folder); + + $controller = $this->createMock(ISessionAwareController::class); + self::invokePrivate($this->middleware, 'assertUserOrShareToken', [$controller]); + } +}