From 6c1c20de9e9cf4e0052c6ec8c5392139a07d1411 Mon Sep 17 00:00:00 2001 From: Jonas Rittershofer Date: Sun, 20 Feb 2022 16:56:27 +0100 Subject: [PATCH] Fix tests Signed-off-by: Jonas Rittershofer --- .../Controller/ShareApiControllerTest.php | 390 ++++++++++ tests/Unit/Service/FormsServiceTest.php | 721 +++++++++++++----- 2 files changed, 913 insertions(+), 198 deletions(-) create mode 100644 tests/Unit/Controller/ShareApiControllerTest.php diff --git a/tests/Unit/Controller/ShareApiControllerTest.php b/tests/Unit/Controller/ShareApiControllerTest.php new file mode 100644 index 000000000..6ccd2ce8d --- /dev/null +++ b/tests/Unit/Controller/ShareApiControllerTest.php @@ -0,0 +1,390 @@ + + * + * @author Jonas Rittershofer + * + * @license AGPL-3.0-or-later + * + * 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 OCA\Forms\Tests\Unit\Controller; + +use OCA\Forms\Controller\ShareApiController; + +use OCA\Forms\Db\Form; +use OCA\Forms\Db\FormMapper; +use OCA\Forms\Db\Share; +use OCA\Forms\Db\ShareMapper; +use OCA\Forms\Service\FormsService; + +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSBadRequestException; +use OCP\AppFramework\OCS\OCSException; +use OCP\AppFramework\OCS\OCSForbiddenException; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\ILogger; +use OCP\IRequest; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Security\ISecureRandom; +use OCP\Share\IShare; + +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class ShareApiControllerTest extends TestCase { + + /** @var ShareApiController */ + private $shareApiController; + + /** @var FormMapper|MockObject */ + private $formMapper; + + /** @var ShareMapper|MockObject */ + private $shareMapper; + + /** @var FormsService|MockObject */ + private $formsService; + + /** @var IGroupManager|MockObject */ + private $groupManager; + + /** @var ILogger|MockObject */ + private $logger; + + /** @var IRequest|MockObject */ + private $request; + + /** @var IUserManager|MockObject */ + private $userManager; + + /** @var ISecureRandom|MockObject */ + private $secureRandom; + + public function setUp(): void { + $this->formMapper = $this->createMock(FormMapper::class); + $this->shareMapper = $this->createMock(ShareMapper::class); + $this->formsService = $this->createMock(FormsService::class); + $this->groupManager = $this->createMock(IGroupManager::class); + $this->logger = $this->createMock(ILogger::class); + $this->request = $this->createMock(IRequest::class); + $this->userManager = $this->createMock(IUserManager::class); + $userSession = $this->createMock(IUserSession::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getUID') + ->willReturn('currentUser'); + $userSession->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + $this->shareApiController = new ShareApiController( + 'forms', + $this->formMapper, + $this->shareMapper, + $this->formsService, + $this->groupManager, + $this->logger, + $this->request, + $this->userManager, + $userSession, + $this->secureRandom + ); + } + + public function dataValidNewShare() { + return [ + 'newUserShare' => [ + 'shareType' => IShare::TYPE_USER, + 'shareWith' => 'user1', + 'expected' => [ + 'id' => 13, + 'formId' => 5, + 'shareType' => 0, + 'shareWith' => 'user1', + 'displayName' => 'user1 DisplayName' + ] + ], + 'newGroupShare' => [ + 'shareType' => IShare::TYPE_GROUP, + 'shareWith' => 'group1', + 'expected' => [ + 'id' => 13, + 'formId' => 5, + 'shareType' => 1, + 'shareWith' => 'group1', + 'displayName' => 'group1 DisplayName' + ] + ], + ]; + } + /** + * Test valid shares + * @dataProvider dataValidNewShare + * + * @param int $shareType + * @param string $shareWith + * @param array $expected + */ + public function testValidNewShare(int $shareType, string $shareWith, array $expected) { + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('currentUser'); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->userManager->expects($this->any()) + ->method('get') + ->with($shareWith) + ->willReturn($this->createMock(IUser::class)); + + $this->groupManager->expects($this->any()) + ->method('get') + ->with($shareWith) + ->willReturn($this->createMock(IGroup::class)); + + $share = new Share(); + $share->setformId('5'); + $share->setShareType($shareType); + $share->setShareWith($shareWith); + $shareWithId = clone $share; + $shareWithId->setId(13); + $this->shareMapper->expects($this->once()) + ->method('insert') + ->with($share) + ->willReturn($shareWithId); + + $this->formsService->expects($this->once()) + ->method('getShareDisplayName') + ->with($shareWithId->read()) + ->willReturn($shareWith . ' DisplayName'); + + // Share Form '5' to 'user1' of share-type 'user=0' + $expectedResponse = new DataResponse($expected); + $this->assertEquals($expectedResponse, $this->shareApiController->newShare(5, $shareType, $shareWith)); + } + + public function dataNewLinkShare() { + return [ + 'newLinkShare' => [ + 'shareType' => IShare::TYPE_LINK, + 'shareWith' => '', + 'expected' => [ + 'id' => 13, + 'formId' => 5, + 'shareType' => 3, + 'shareWith' => 'abcdefgh', + 'displayName' => '' + ]], + ]; + } + /** + * Test valid Link shares + * @dataProvider dataNewLinkShare + * + * @param int $shareType + * @param string $shareWith + * @param array $expected + */ + public function testNewLinkShare(int $shareType, string $shareWith, array $expected) { + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('currentUser'); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->secureRandom->expects($this->any()) + ->method('generate') + ->willReturn('abcdefgh'); + + $share = new Share(); + $share->setformId('5'); + $share->setShareType($shareType); + if ($shareWith === '') { + $share->setShareWith('abcdefgh'); + } else { + $share->setShareWith($shareWith); + } + $shareWithId = clone $share; + $shareWithId->setId(13); + $this->shareMapper->expects($this->once()) + ->method('insert') + ->with($share) + ->willReturn($shareWithId); + + $this->formsService->expects($this->once()) + ->method('getShareDisplayName') + ->with($shareWithId->read()) + ->willReturn(''); + + $this->shareMapper->expects($this->once()) + ->method('findPublicShareByHash') + ->will($this->throwException(new DoesNotExistException('Not found.'))); + + // Share the form. + $expectedResponse = new DataResponse($expected); + $this->assertEquals($expectedResponse, $this->shareApiController->newShare(5, $shareType, $shareWith)); + } + + /** + * Test a random link hash, that is already existing. + */ + public function testExistingLinkHash() { + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('currentUser'); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->secureRandom->expects($this->any()) + ->method('generate') + ->willReturn('abcdefgh'); + + $this->shareMapper->expects($this->once()) + ->method('findPublicShareByHash') + ->with('abcdefgh') + ->willReturn(new Share()); + + $this->shareMapper->expects($this->never()) + ->method('insert'); + + $this->expectException(OCSException::class); + $this->shareApiController->newShare(5, IShare::TYPE_LINK, ''); + } + + /** + * Test an unused (but existing) Share-Type + */ + public function testBadShareType() { + $this->expectException(OCSBadRequestException::class); + + // Share Form '5' to 'user1' of share-type 'deck_user=13' + $this->shareApiController->newShare(5, 13, 'user1'); + } + + /** + * Sharing a non-existing form. + */ + public function testShareUnknownForm() { + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->will($this->throwException(new DoesNotExistException('Form not found'))); + ; + + $this->expectException(OCSBadRequestException::class); + $this->shareApiController->newShare(5, 0, 'user1'); + } + + /** + * Share form of other owner + */ + public function testShareForeignForm() { + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('someOtherUser'); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->expectException(OCSForbiddenException::class); + $this->shareApiController->newShare(5, 0, 'user1'); + } + + /** + * Delete a share. + */ + public function testDeleteShare() { + $share = new Share(); + $share->setId(8); + $share->setFormId(5); + $this->shareMapper->expects($this->once()) + ->method('findById') + ->with('8') + ->willReturn($share); + + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('currentUser'); + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->shareMapper->expects($this->once()) + ->method('deleteById') + ->with('8'); + + $response = new DataResponse(8); + $this->assertEquals($response, $this->shareApiController->deleteShare(8)); + } + + /** + * Delete Non-existing share. + */ + public function testDeleteUnknownShare() { + $this->shareMapper->expects($this->once()) + ->method('findById') + ->with('8') + ->will($this->throwException(new DoesNotExistException('Share not found'))); + ; + + $this->expectException(OCSBadRequestException::class); + $this->shareApiController->deleteShare(8); + } + + /** + * Delete share from form of other owner. + */ + public function testDeleteForeignShare() { + $share = new Share(); + $share->setId(8); + $share->setFormId(5); + $this->shareMapper->expects($this->once()) + ->method('findById') + ->with('8') + ->willReturn($share); + + $form = new Form(); + $form->setId('5'); + $form->setOwnerId('someOtherUser'); + $this->formMapper->expects($this->once()) + ->method('findById') + ->with('5') + ->willReturn($form); + + $this->expectException(OCSForbiddenException::class); + $this->shareApiController->deleteShare(8); + } +} diff --git a/tests/Unit/Service/FormsServiceTest.php b/tests/Unit/Service/FormsServiceTest.php index e4702c1d2..80585a83f 100644 --- a/tests/Unit/Service/FormsServiceTest.php +++ b/tests/Unit/Service/FormsServiceTest.php @@ -33,6 +33,8 @@ use OCA\Forms\Db\OptionMapper; use OCA\Forms\Db\Question; use OCA\Forms\Db\QuestionMapper; +use OCA\Forms\Db\Share; +use OCA\Forms\Db\ShareMapper; use OCA\Forms\Db\SubmissionMapper; use OCP\IGroup; @@ -41,6 +43,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; +use OCP\Share\IShare; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -62,6 +65,9 @@ class FormsServiceTest extends TestCase { /** @var QuestionMapper|MockObject */ private $questionMapper; + /** @var ShareMapper|MockObject */ + private $shareMapper; + /** @var SubmissionMapper|MockObject */ private $submissionMapper; @@ -80,6 +86,7 @@ public function setUp(): void { $this->formMapper = $this->createMock(FormMapper::class); $this->optionMapper = $this->createMock(OptionMapper::class); $this->questionMapper = $this->createMock(QuestionMapper::class); + $this->shareMapper = $this->createMock(ShareMapper::class); $this->submissionMapper = $this->createMock(SubmissionMapper::class); $this->groupManager = $this->createMock(IGroupManager::class); @@ -100,6 +107,7 @@ public function setUp(): void { $this->formMapper, $this->optionMapper, $this->questionMapper, + $this->shareMapper, $this->submissionMapper, $this->groupManager, $this->logger, @@ -119,21 +127,8 @@ public function dataGetForm() { 'ownerId' => 'someUser', 'created' => 123456789, 'access' => [ - 'users' => [ - [ - 'shareWith' => 'user1', - 'displayName' => 'First User', - 'shareType' => 0 // IShare::TYPE_USER - ] - ], - 'groups' => [ - [ - 'shareWith' => 'group1', - 'displayName' => 'First Group', - 'shareType' => 1 // IShare::TYPE_GROUP - ] - ], - 'type' => 'selected' + 'permitAllUsers' => false, + 'showToAllUsers' => false, ], 'expires' => 0, 'isAnonymous' => false, @@ -171,6 +166,18 @@ public function dataGetForm() { 'description' => '', 'options' => [] ] + ], + 'shares' => [ + [ + 'id' => 1, + 'formId' => 42, + 'shareType' => 0, + 'shareWith' => 'currentUser', + 'displayName' => 'Current User' + ] + ], + 'permissions' => [ + 'submit' ] ]] ]; @@ -191,9 +198,8 @@ public function testGetForm(array $expected) { $form->setOwnerId('someUser'); $form->setCreated(123456789); $form->setAccess([ - 'users' => ['user1'], - 'groups' => ['group1'], - 'type' => 'selected' + 'permitAllUsers' => false, + 'showToAllUsers' => false, ]); $form->setExpires(0); $form->setIsAnonymous(false); @@ -208,19 +214,11 @@ public function testGetForm(array $expected) { $user = $this->createMock(IUser::class); $user->expects($this->once()) ->method('getDisplayName') - ->willReturn('First User'); - $group = $this->createMock(IGroup::class); - $group->expects($this->once()) - ->method('getDisplayName') - ->willReturn('First Group'); + ->willReturn('Current User'); $this->userManager->expects($this->once()) ->method('get') - ->with('user1') + ->with('currentUser') ->willReturn($user); - $this->groupManager->expects($this->once()) - ->method('get') - ->with('group1') - ->willReturn($group); // Questions $question1 = new Question(); @@ -258,10 +256,55 @@ public function testGetForm(array $expected) { ->with(1) ->willReturn([$option1, $option2]); + $share = new Share(); + $share->setId(1); + $share->setFormId(42); + $share->setShareType(0); + $share->setShareWith('currentUser'); + + $this->shareMapper->expects($this->exactly(3)) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + // Run the test $this->assertEquals($expected, $this->formsService->getForm(42)); } + public function dataGetPartialForm() { + return [ + 'onePartialOwnedForm' => [[ + 'id' => 42, + 'hash' => 'abcdefg', + 'title' => 'Form 1', + 'expires' => 0, + 'permissions' => ['edit', 'results', 'submit'], + 'partial' => true + ]] + ]; + } + /** + * @dataProvider dataGetPartialForm + * + * @param array $expected + */ + public function testGetPartialForm(array $expected) { + $form = new Form(); + $form->setId(42); + $form->setHash('abcdefg'); + $form->setTitle('Form 1'); + $form->setOwnerId('currentUser'); + $form->setExpires(0); + + $this->formMapper->expects($this->exactly(2)) + ->method('findById') + ->with(42) + ->willReturn($form); + + // Run the test + $this->assertEquals($expected, $this->formsService->getPartialFormArray(42)); + } + public function dataGetPublicForm() { return [ // Bare form without questions, checking removed access & ownerId @@ -275,7 +318,10 @@ public function dataGetPublicForm() { 'isAnonymous' => false, 'submitOnce' => false, 'canSubmit' => true, - 'questions' => [] + 'questions' => [], + 'permissions' => [ + 'submit' + ] ]] ]; } @@ -294,9 +340,8 @@ public function testGetPublicForm(array $expected) { $form->setOwnerId('someUser'); $form->setCreated(123456789); $form->setAccess([ - 'users' => ['user1'], - 'groups' => ['group1'], - 'type' => 'selected' + 'permitAllUsers' => false, + 'showToAllUsers' => false, ]); $form->setExpires(0); $form->setIsAnonymous(false); @@ -311,19 +356,11 @@ public function testGetPublicForm(array $expected) { $user = $this->createMock(IUser::class); $user->expects($this->once()) ->method('getDisplayName') - ->willReturn('First User'); - $group = $this->createMock(IGroup::class); - $group->expects($this->once()) - ->method('getDisplayName') - ->willReturn('First Group'); + ->willReturn('Current User'); $this->userManager->expects($this->once()) ->method('get') - ->with('user1') + ->with('currentUser') ->willReturn($user); - $this->groupManager->expects($this->once()) - ->method('get') - ->with('group1') - ->willReturn($group); // No Questions here $this->questionMapper->expects($this->once()) @@ -331,66 +368,123 @@ public function testGetPublicForm(array $expected) { ->with(42) ->willReturn([]); + // Share exists, but should not be shown in the end. + $share = new Share(); + $share->setId(1); + $share->setFormId(42); + $share->setShareType(0); + $share->setShareWith('currentUser'); + + $this->shareMapper->expects($this->exactly(3)) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + // Run the test $this->assertEquals($expected, $this->formsService->getPublicForm(42)); } - public function dataCanSubmit() { + public function dataGetPermissions() { return [ - 'publicForm' => [ - ['type' => 'public'], - 'someUser', - true, - ['currentUser'], - true + 'ownerHasAllPermissions' => [ + 'ownerId' => 'currentUser', + 'access' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ], + 'expected' => ['edit', 'results', 'submit'], + ], + 'allUsersCanSubmit' => [ + 'ownerId' => 'someOtherUser', + 'access' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => false, + ], + 'expected' => ['submit'], ], + 'noPermission' => [ + 'ownerId' => 'someOtherUser', + 'access' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ], + 'expected' => [], + ] + ]; + } + /** + * @dataProvider dataGetPermissions + * + * @param string $ownerId + * @param array $access + * @param array $expected + */ + public function testGetPermissions(string $ownerId, array $access, array $expected) { + $form = new Form(); + $form->setId(42); + $form->setOwnerId($ownerId); + $form->setAccess($access); + + $this->formMapper->expects($this->any()) + ->method('findById') + ->with(42) + ->willReturn($form); + + $this->shareMapper->expects($this->any()) + ->method('findByForm') + ->with(42) + ->willReturn([]); + + $this->assertEquals($expected, $this->formsService->getPermissions(42)); + } + + public function dataCanSubmit() { + return [ 'allowFormOwner' => [ - ['type' => 'registered'], - 'currentUser', - true, - ['currentUser'], - true + 'ownerId' => 'currentUser', + 'submitOnce' => true, + 'participantsArray' => ['currentUser'], + 'expected' => true ], 'submitOnceGood' => [ - ['type' => 'registered'], - 'someUser', - true, - ['notCurrentUser'], - true + 'ownerId' => 'someUser', + 'submitOnce' => true, + 'participantsArray' => ['notCurrentUser'], + 'expected' => true ], 'submitOnceNotGood' => [ - ['type' => 'registered'], - 'someUser', - true, - ['currentUser'], - false + 'ownerId' => 'someUser', + 'submitOnce' => true, + 'participantsArray' => ['notCurrentUser', 'currentUser'], + 'expected' => false ], - 'simpleAllowed' => [ - ['type' => 'registered'], - 'someUser', - false, - ['currentUser'], - true + 'submitMultiple' => [ + 'ownerId' => 'someUser', + 'submitOnce' => false, + 'participantsArray' => ['currentUser'], + 'expected' => true ] ]; } /** * @dataProvider dataCanSubmit * - * @param array $accessArray * @param string $ownerId * @param bool $submitOnce * @param array $participantsArray * @param bool $expected */ - public function testCanSubmit(array $accessArray, string $ownerId, bool $submitOnce, array $participantsArray, bool $expected) { + public function testCanSubmit(string $ownerId, bool $submitOnce, array $participantsArray, bool $expected) { $form = new Form(); $form->setId(42); - $form->setAccess($accessArray); + $form->setAccess([ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ]); $form->setOwnerId($ownerId); $form->setSubmitOnce($submitOnce); - $this->formMapper->expects($this->once()) + $this->formMapper->expects($this->any()) ->method('findById') ->with(42) ->willReturn($form); @@ -403,63 +497,136 @@ public function testCanSubmit(array $accessArray, string $ownerId, bool $submitO $this->assertEquals($expected, $this->formsService->canSubmit(42)); } - public function dataHasUserAccess() { + /** + * Test result, if hasPublicLink returns true due to public link share. + */ + public function testPublicCanSubmit() { + $form = new Form(); + $form->setId(42); + $form->setAccess([ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ]); + + $this->formMapper->expects($this->any()) + ->method('findById') + ->with(42) + ->willReturn($form); + + $share = new Share; + $share->setShareType(IShare::TYPE_LINK); + $this->shareMapper->expects($this->once()) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + + // Make sure, we don't pass the PublicLinkCheck (which would then reach 'getUID') + $user = $this->createMock(IUser::class); + $user->expects($this->never()) + ->method('getUID'); + $userSession = $this->createMock(IUserSession::class); + $userSession->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + $formsService = new FormsService( + $this->activityManager, + $this->formMapper, + $this->optionMapper, + $this->questionMapper, + $this->shareMapper, + $this->submissionMapper, + $this->groupManager, + $this->logger, + $this->userManager, + $userSession + ); + + $this->assertEquals(true, $formsService->canSubmit(42)); + } + + public function dataHasPublicLink() { return [ - 'noAccess' => [ - [ - 'type' => 'selected', - 'users' => [], - 'groups' => [] + 'legacyLink' => [ + 'access' => [ + 'legacyLink' => true, + 'permitAllUsers' => false, + 'showToAllUsers' => false, ], - 'someOtherUser', - false + 'shareType' => IShare::TYPE_USER, + 'expected' => true, ], - 'publicForm' => [ - [ - 'type' => 'public', - 'users' => [], - 'groups' => [] + 'noPublicLink' => [ + 'access' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, ], - 'someOtherUser', - true + 'shareType' => IShare::TYPE_USER, + 'expected' => false, ], + 'hasPublicLink' => [ + 'access' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ], + 'shareType' => IShare::TYPE_LINK, + 'expected' => true, + ] + ]; + } + /** + * @dataProvider dataHasPublicLink + * + * @param array $access + * @param int $shareType The ShareType used for this test. + * @param bool $expected + */ + public function testHasPublicLink(array $access, int $shareType, bool $expected) { + $form = new Form; + $form->setId(42); + $form->setAccess($access); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with(42) + ->willReturn($form); + + $share = new Share(); + $share->setShareType($shareType); + $this->shareMapper->expects($this->any()) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + + $this->assertEquals($expected, $this->formsService->hasPublicLink(42)); + } + + public function dataHasUserAccess() { + return [ 'ownerhasAccess' => [ - [ - 'type' => 'selected', - 'users' => [], - 'groups' => [] + 'accessArray' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, ], - 'currentUser', - true + 'ownerId' => 'currentUser', + 'expected' => true ], - 'registeredHasAccess' => [ - [ - 'type' => 'registered', - 'users' => [], - 'groups' => [] + 'allUsersPermitted' => [ + 'accessArray' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => false, ], - 'someOtherUser', - true + 'ownerId' => 'someOtherUser', + 'expected' => true ], - 'selectedUser' => [ - [ - 'type' => 'selected', - 'users' => ['user1', 'currentUser', 'user2'], - 'groups' => [] + 'noAccess' => [ + 'accessArray' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, ], - 'someOtherUser', - true + 'ownerId' => 'someOtherUser', + 'expected' => false ], - 'userInSelectedGroup' => [ - [ - 'type' => 'selected', - 'users' => [], - 'groups' => ['currentUserGroup'] - ], - 'someOtherUser', - true - ] - ]; } /** @@ -479,14 +646,33 @@ public function testHasUserAccess(array $accessArray, string $ownerId, bool $exp ->with(42) ->willReturn($form); - $this->groupManager->expects($this->any()) - ->method('isInGroup') - ->with('currentUser', 'currentUserGroup') - ->willReturn(true); - $this->assertEquals($expected, $this->formsService->hasUserAccess(42)); } + public function testHasUserAccess_DirectShare() { + $form = new Form(); + $form->setAccess([ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ]); + $form->setOwnerId('notCurrentUser'); + + $this->formMapper->expects($this->once()) + ->method('findById') + ->with(42) + ->willReturn($form); + + $share = new Share(); + $share->setShareType(IShare::TYPE_USER); + $share->setShareWith('currentUser'); + $this->shareMapper->expects($this->any()) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + + $this->assertEquals(true, $this->formsService->hasUserAccess(42)); + } + public function testHasUserAccess_NotLoggedIn() { $userSession = $this->createMock(IUserSession::class); $userSession->expects($this->once()) @@ -498,6 +684,7 @@ public function testHasUserAccess_NotLoggedIn() { $this->formMapper, $this->optionMapper, $this->questionMapper, + $this->shareMapper, $this->submissionMapper, $this->groupManager, $this->logger, @@ -507,9 +694,8 @@ public function testHasUserAccess_NotLoggedIn() { $form = new Form(); $form->setAccess([ - 'type' => 'registered', - 'users' => [], - 'groups' => [] + 'permitAllUsers' => false, + 'showToAllUsers' => false, ]); $form->setOwnerId('someOtherUser'); @@ -521,6 +707,147 @@ public function testHasUserAccess_NotLoggedIn() { $this->assertEquals(false, $formsService->hasUserAccess(42)); } + public function dataIsSharedFormShown() { + return [ + 'dontShowToOwner' => [ + 'ownerId' => 'currentUser', + 'expires' => 0, + 'access' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => true, + ], + 'shareType' => IShare::TYPE_LINK, + 'expected' => false, + ], + 'expiredForm' => [ + 'ownerId' => 'notCurrentUser', + 'expires' => 1, + 'access' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => true, + ], + 'shareType' => IShare::TYPE_LINK, + 'expected' => false, + ], + 'shownToAll' => [ + 'ownerId' => 'notCurrentUser', + 'expires' => 0, + 'access' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => true, + ], + 'shareType' => IShare::TYPE_LINK, + 'expected' => true, + ], + 'sharedToUser' => [ + 'ownerId' => 'notCurrentUser', + 'expires' => 0, + 'access' => [ + 'permitAllUsers' => false, + 'showToAllUsers' => false, + ], + 'shareType' => IShare::TYPE_USER, + 'expected' => true, + ], + 'notShown' => [ + 'ownerId' => 'notCurrentUser', + 'expires' => 0, + 'access' => [ + 'permitAllUsers' => true, + 'showToAllUsers' => false, + ], + 'shareType' => IShare::TYPE_LINK, + 'expected' => false, + ] + ]; + } + /** + * @dataProvider dataIsSharedFormShown + * + * @param string $ownerId + * @param int $expires + * @param array $access + * @param int $shareType ShareType used for dummy-share here. + * @param bool $expected + */ + public function testIsSharedFormShown(string $ownerId, int $expires, array $access, int $shareType, bool $expected) { + $form = new Form(); + $form->setId(42); + $form->setOwnerId($ownerId); + $form->setExpires($expires); + $form->setAccess($access); + + $this->formMapper->expects($this->any()) + ->method('findById') + ->with(42) + ->willReturn($form); + + $share = new Share(); + $share->setShareType($shareType); + $share->setShareWith('currentUser'); // Only relevant, if $shareType is TYPE_USER, otherwise it's just some 'hash' + $this->shareMapper->expects($this->any()) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + + $this->assertEquals($expected, $this->formsService->isSharedFormShown(42)); + } + + public function dataIsSharedToUser() { + return [ + 'sharedToUser' => [ + 'shareType' => IShare::TYPE_USER, + 'shareWith' => 'currentUser', + 'expected' => true, + ], + 'sharedToOtherUser' => [ + 'shareType' => IShare::TYPE_USER, + 'shareWith' => 'NotcurrentUser', + 'expected' => false, + ], + 'sharedToGroup' => [ + 'shareType' => IShare::TYPE_GROUP, + 'shareWith' => 'goodGroup', + 'expected' => true, + ], + 'sharedToOtherGroup' => [ + 'shareType' => IShare::TYPE_GROUP, + 'shareWith' => 'wrongGroup', + 'expected' => false, + ], + 'NotSharedToUser' => [ + 'shareType' => IShare::TYPE_LINK, + 'shareWith' => 'abcdefg', + 'expected' => false, + ], + ]; + } + /** + * @dataProvider dataIsSharedToUser + * + * @param int $shareType + * @param string $shareWith + * @param bool $expected + */ + public function testIsSharedToUser(int $shareType, string $shareWith, bool $expected) { + $share = new Share(); + $share->setShareType($shareType); + $share->setShareWith($shareWith); + $this->shareMapper->expects($this->once()) + ->method('findByForm') + ->with(42) + ->willReturn([$share]); + + $this->groupManager->expects($this->any()) + ->method('isInGroup') + ->will($this->returnValueMap([ + ['currentUser', 'goodGroup', true], + ['currentUser', 'wrongGroup', false], + ])); + + $this->assertEquals($expected, $this->formsService->isSharedToUser(42)); + } + public function dataHasFormExpired() { return [ 'hasExpired' => [time() - 3600, true], @@ -546,92 +873,90 @@ public function testHasFormExpired(int $expires, bool $expected) { $this->assertEquals($expected, $this->formsService->hasFormExpired(42)); } - public function dataNotifyNewShares() { + public function dataGetShareDisplayName() { return [ - 'newUsersGroups' => [ - [ - 'users' => ['user1'], - 'groups' => ['group1', 'group2'] + 'userShare' => [ + 'share' => [ + 'shareType' => IShare::TYPE_USER, + 'shareWith' => 'user1', ], - [ - 'users' => ['user1', 'user2', 'user3'], - 'groups' => ['group1', 'group2', 'group3'] - ], - ['user2', 'user3'], - ['group3'] + 'expected' => 'user1 UserDisplayname', ], - 'noNewShares' => [ - [ - 'users' => ['user1'], - 'groups' => ['group1', 'group2'] - ], - [ - 'users' => ['user1'], - 'groups' => ['group1', 'group2'] + 'groupShare' => [ + 'share' => [ + 'shareType' => IShare::TYPE_GROUP, + 'shareWith' => 'group1', ], - [], - [] + 'expected' => 'group1 GroupDisplayname', ], - 'removeShares' => [ - [ - 'users' => ['user1', 'user2', 'user3'], - 'groups' => ['group1', 'group2', 'group3'] + 'otherShare' => [ + 'share' => [ + 'shareType' => IShare::TYPE_LINK, + 'shareWith' => 'abcdefg', ], - [ - 'users' => ['user1'], - 'groups' => ['group1', 'group2'] - ], - [], - [] + 'expected' => '', ], - 'noSharesAtAll' => [ - [ - 'users' => [], - 'groups' => [] - ], - [ - 'users' => [], - 'groups' => [] - ], - [], - [] + ]; + } + /** + * @dataProvider dataGetShareDisplayName + * + * @param array $share + * @param string $expected + */ + public function testGetShareDisplayName(array $share, string $expected) { + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getDisplayName') + ->willReturn($share['shareWith'] . ' UserDisplayname'); + $this->userManager->expects($this->any()) + ->method('get') + ->with($share['shareWith']) + ->willReturn($user); + + $group = $this->createMock(IGroup::class); + $group->expects($this->any()) + ->method('getDisplayName') + ->willReturn($share['shareWith'] . ' GroupDisplayname'); + $this->groupManager->expects($this->any()) + ->method('get') + ->with($share['shareWith']) + ->willReturn($group); + + $this->assertEquals($expected, $this->formsService->getShareDisplayName($share)); + } + + public function dataNotifyNewShares() { + return [ + 'newUserShare' => [ + 'shareType' => IShare::TYPE_USER, + 'shareWith' => 'someUser', + 'expectedMethod' => 'publishNewShare', + ], + 'newGroupShare' => [ + 'shareType' => IShare::TYPE_GROUP, + 'shareWith' => 'someGroup', + 'expectedMethod' => 'publishNewGroupShare', ] ]; } /** * @dataProvider dataNotifyNewShares * - * @param array $oldAccess - * @param array $newAccess - * @param array $diffUsers - * @param array $diffGroups + * @param int $shareType + * @param string $shareWith + * @param string $expectedMethod that will be called on activityManager. */ - public function testNotifyNewShares(array $oldAccess, array $newAccess, array $diffUsers, array $diffGroups) { + public function testNotifyNewShares(int $shareType, string $shareWith, string $expectedMethod) { $form = $this->createMock(Form::class); + $share = new Share(); + $share->setShareType($shareType); + $share->setShareWith($shareWith); + + $this->activityManager->expects($this->once()) + ->method($expectedMethod) + ->with($form, $shareWith); - $passedUserList = []; - $this->activityManager->expects($this->any()) - ->method('publishNewShare') - ->will($this->returnCallback(function ($passedForm, $passedUser) use ($form, &$passedUserList) { - if ($passedForm === $form) { - // Store List of passed users - $passedUserList[] = $passedUser; - } - })); - $passedGroupList = []; - $this->activityManager->expects($this->any()) - ->method('publishNewGroupShare') - ->will($this->returnCallback(function ($passedForm, $passedGroup) use ($form, &$passedGroupList) { - if ($passedForm === $form) { - // Store List of passed groups - $passedGroupList[] = $passedGroup; - } - })); - - $this->formsService->notifyNewShares($form, $oldAccess, $newAccess); - - // Check List of called Users and Groups - $this->assertEquals($diffUsers, $passedUserList); - $this->assertEquals($diffGroups, $passedGroupList); + $this->formsService->notifyNewShares($form, $share); } }