connection = Server::get(IDBConnection::class); $this->l = $this->getMockBuilder(IL10N::class)->getMock(); $this->l->method('t') ->willReturnCallback(function ($text, $parameters = []) { return vsprintf($text, $parameters); }); $this->config = $this->getMockBuilder(IConfig::class)->getMock(); $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')->getMock(); $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock(); $this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock(); $this->mailer = $this->getMockBuilder('\OCP\Mail\IMailer')->getMock(); $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->getMock(); $this->share = $this->getMockBuilder(IShare::class)->getMock(); $this->activityManager = $this->getMockBuilder('OCP\Activity\IManager')->getMock(); $this->settingsManager = $this->getMockBuilder(SettingsManager::class)->disableOriginalConstructor()->getMock(); $this->defaults = $this->createMock(Defaults::class); $this->hasher = $this->getMockBuilder(IHasher::class)->getMock(); $this->eventDispatcher = $this->getMockBuilder(IEventDispatcher::class)->getMock(); $this->shareManager = $this->getMockBuilder(IManager::class)->getMock(); $this->userManager->expects($this->any())->method('userExists')->willReturn(true); $this->config->expects($this->any())->method('getAppValue')->with('core', 'enforce_strict_email_check')->willReturn('yes'); } /** * get instance of Mocked ShareByMailProvider * * @param array $mockedMethods internal methods which should be mocked * @return \PHPUnit\Framework\MockObject\MockObject | ShareByMailProvider */ private function getInstance(array $mockedMethods = []) { if (!empty($mockedMethods)) { return $this->getMockBuilder('OCA\ShareByMail\ShareByMailProvider') ->setConstructorArgs([ $this->config, $this->connection, $this->secureRandom, $this->userManager, $this->rootFolder, $this->l, $this->logger, $this->mailer, $this->urlGenerator, $this->activityManager, $this->settingsManager, $this->defaults, $this->hasher, $this->eventDispatcher, $this->shareManager ]) ->setMethods($mockedMethods) ->getMock(); } return new ShareByMailProvider( $this->config, $this->connection, $this->secureRandom, $this->userManager, $this->rootFolder, $this->l, $this->logger, $this->mailer, $this->urlGenerator, $this->activityManager, $this->settingsManager, $this->defaults, $this->hasher, $this->eventDispatcher, $this->shareManager ); } protected function tearDown(): void { $this->connection ->getQueryBuilder() ->delete('share') ->executeStatement(); parent::tearDown(); } public function testCreate(): void { $expectedShare = $this->createMock(IShare::class); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('user1'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'sendEmail', 'sendPassword']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare); $share->expects($this->any())->method('getNode')->willReturn($node); // As share api link password is not enforced, the password will not be generated. $this->shareManager->expects($this->once())->method('shareApiLinkEnforcePassword')->willReturn(false); $this->settingsManager->expects($this->never())->method('sendPasswordByMail'); // Mail notification is triggered by the share manager. $instance->expects($this->never())->method('sendEmail'); $instance->expects($this->never())->method('sendPassword'); $this->assertSame($expectedShare, $instance->create($share)); } public function testCreateSendPasswordByMailWithoutEnforcedPasswordProtection(): void { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@examplelölöl.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare); $share->expects($this->any())->method('getNode')->willReturn($node); // The autogenerated password should not be mailed. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false); $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true); $instance->expects($this->never())->method('autoGeneratePassword'); // No password is set and no password sent via talk is requested $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@examplelölöl.com']); $instance->expects($this->never())->method('sendPassword'); $instance->expects($this->never())->method('sendPasswordToOwner'); // The manager sends the mail notification. // For the sake of testing simplicity, we will handle it ourselves. $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword(): void { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getPassword')->willReturn('password'); $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed'); $share->expects($this->once())->method('setPassword')->with('passwordHashed'); // The given password (but not the autogenerated password) should not be // mailed to the receiver of the share because permanent passwords are not enforced. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false); $this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false); $instance->expects($this->never())->method('autoGeneratePassword'); // A password is set but no password sent via talk has been requested $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@example.com']); $instance->expects($this->once())->method('sendPassword')->with($share, 'password'); $instance->expects($this->never())->method('sendPasswordToOwner'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithoutPermanentPassword(): void { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance([ 'getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner', ]); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getPassword')->willReturn('password'); $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed'); $share->expects($this->once())->method('setPassword')->with('passwordHashed'); // No password is generated, so no emails need to be sent // aside from the main email notification. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false); $instance->expects($this->never())->method('autoGeneratePassword'); $this->config->expects($this->once())->method('getSystemValue') ->with('sharing.enable_mail_link_password_expiration') ->willReturn(true); // No password has been set and no password sent via talk has been requested, // but password has been enforced for the whole instance and will be generated. $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@example.com']); $instance->expects($this->never())->method('sendPassword'); $instance->expects($this->never())->method('sendPasswordToOwner'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateSendPasswordByMailWithEnforcedPasswordProtectionWithPermanentPassword(): void { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $this->secureRandom->expects($this->once()) ->method('generate') ->with(8, ISecureRandom::CHAR_HUMAN_READABLE) ->willReturn('autogeneratedPassword'); $this->eventDispatcher->expects($this->once()) ->method('dispatchTyped') ->with(new GenerateSecurePasswordEvent(PasswordContext::SHARING)); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'createPasswordSendActivity', 'sendPasswordToOwner']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'autogeneratedPassword']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare); // Initially not set, but will be set by the autoGeneratePassword method. $share->expects($this->exactly(3))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword'); $this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed'); $share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed'); // The autogenerated password should be mailed to the receiver of the share because permanent passwords are enforced. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true); $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false); $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true); $message = $this->createMock(IMessage::class); $message->expects($this->exactly(2))->method('setTo')->with(['receiver@example.com']); $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message); $this->mailer->expects($this->exactly(2))->method('createEMailTemplate') ->withConsecutive([ 'sharebymail.RecipientNotification', [ 'filename' => 'filename', 'link' => 'https://example.com/file.txt', 'initiator' => 'owner', 'expiration' => null, 'shareWith' => 'receiver@example.com', 'note' => '' ] ], [ 'sharebymail.RecipientPasswordNotification', [ 'filename' => 'filename', 'password' => 'autogeneratedPassword', 'initiator' => 'owner', 'initiatorEmail' => null, 'shareWith' => 'receiver@example.com', ] ]); // Main email notification is sent as well as the password // to the recipient because shareApiLinkEnforcePassword is enabled. $this->mailer->expects($this->exactly(2))->method('send'); $instance->expects($this->never())->method('sendPasswordToOwner'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateSendPasswordByMailWithPasswordAndWithEnforcedPasswordProtectionWithPermanentPassword(): void { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendPasswordToOwner']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare); $share->expects($this->exactly(3))->method('getPassword')->willReturn('password'); $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed'); $share->expects($this->once())->method('setPassword')->with('passwordHashed'); // The given password (but not the autogenerated password) should be // mailed to the receiver of the share. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true); $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false); $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true); $instance->expects($this->never())->method('autoGeneratePassword'); $message = $this->createMock(IMessage::class); $message->expects($this->exactly(2))->method('setTo')->with(['receiver@example.com']); $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message); $this->mailer->expects($this->exactly(2))->method('createEMailTemplate') ->withConsecutive([ 'sharebymail.RecipientNotification', [ 'filename' => 'filename', 'link' => 'https://example.com/file.txt', 'initiator' => 'owner', 'expiration' => null, 'shareWith' => 'receiver@example.com', 'note' => '' ] ], [ 'sharebymail.RecipientPasswordNotification', [ 'filename' => 'filename', 'password' => 'password', 'initiator' => 'owner', 'initiatorEmail' => null, 'shareWith' => 'receiver@example.com', ] ]); // Main email notification is sent as well as the password // to the recipient because the password is set. $this->mailer->expects($this->exactly(2))->method('send'); $instance->expects($this->never())->method('sendPasswordToOwner'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateSendPasswordByTalkWithEnforcedPasswordProtectionWithPermanentPassword(): void { $expectedShare = $this->createMock(IShare::class); // The owner of the share. $owner = $this->getMockBuilder(IUser::class)->getMock(); $this->userManager->expects($this->any())->method('get')->with('owner')->willReturn($owner); $owner->expects($this->any())->method('getEMailAddress')->willReturn('owner@example.com'); $owner->expects($this->any())->method('getDisplayName')->willReturn('owner'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(true); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'autogeneratedPassword']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare); $share->expects($this->exactly(4))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword', 'autogeneratedPassword'); $this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed'); $share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed'); // The autogenerated password should be mailed to the owner of the share. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true); $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false); $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true); $instance->expects($this->once())->method('autoGeneratePassword')->with($share)->willReturn('autogeneratedPassword'); $message = $this->createMock(IMessage::class); $message->expects($this->exactly(2))->method('setTo')->withConsecutive([['receiver@example.com']], [['owner@example.com' => 'owner']]); $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message); $this->mailer->expects($this->exactly(2))->method('createEMailTemplate') ->withConsecutive([ 'sharebymail.RecipientNotification', [ 'filename' => 'filename', 'link' => 'https://example.com/file.txt', 'initiator' => 'owner', 'expiration' => null, 'shareWith' => 'receiver@example.com', 'note' => '' ] ], [ 'sharebymail.OwnerPasswordNotification', [ 'filename' => 'filename', 'password' => 'autogeneratedPassword', 'initiator' => 'owner', 'initiatorEmail' => 'owner@example.com', 'shareWith' => 'receiver@example.com', ] ]); // Main email notification is sent as well as the password to owner // because the password is set and SendPasswordByTalk is enabled. $this->mailer->expects($this->exactly(2))->method('send'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } // If attributes is set to multiple emails, use them as BCC public function sendNotificationToMultipleEmails() { $expectedShare = $this->createMock(IShare::class); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('filename'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn(''); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false); $share->expects($this->any())->method('getSharedBy')->willReturn('owner'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); $attributes = $this->getMockBuilder(IAttributes::class)->getMock(); $share->expects($this->any())->method('getAttributes')->willReturn($attributes); $attributes->expects($this->any())->method('getAttribute')->with('shareWith', 'emails')->willReturn([ 'receiver1@example.com', 'receiver2@example.com', 'receiver3@example.com', ]); // Assume the mail address is valid. $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']); $instance->expects($this->once())->method('getSharedWith')->willReturn([]); $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42); $instance->expects($this->once())->method('createShareActivity')->with($share); $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']); $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getPassword')->willReturn('password'); $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed'); $share->expects($this->once())->method('setPassword')->with('passwordHashed'); // The given password (but not the autogenerated password) should not be // mailed to the receiver of the share because permanent passwords are not enforced. $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false); $this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false); $instance->expects($this->never())->method('autoGeneratePassword'); // A password is set but no password sent via talk has been requested $instance->expects($this->once())->method('sendEmail') ->with($share, ['receiver1@example.com', 'receiver2@example.com', 'receiver3@example.com']); $instance->expects($this->once())->method('sendPassword')->with($share, 'password'); $instance->expects($this->never())->method('sendPasswordToOwner'); $message = $this->createMock(IMessage::class); $message->expects($this->never())->method('setTo'); $message->expects($this->exactly(2))->method('setBcc')->with(['receiver1@example.com', 'receiver2@example.com', 'receiver3@example.com']); $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message); // Main email notification is sent as well as the password // to recipients because the password is set. $this->mailer->expects($this->exactly(2))->method('send'); $this->assertSame($expectedShare, $instance->create($share)); $instance->sendMailNotification($share); } public function testCreateFailed(): void { $this->expectException(\Exception::class); $this->share->expects($this->once())->method('getSharedWith')->willReturn('user1'); $node = $this->getMockBuilder('OCP\Files\Node')->getMock(); $node->expects($this->any())->method('getName')->willReturn('fileName'); $this->share->expects($this->any())->method('getNode')->willReturn($node); $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject']); $instance->expects($this->once())->method('getSharedWith')->willReturn(['found']); $instance->expects($this->never())->method('createMailShare'); $instance->expects($this->never())->method('getRawShare'); $instance->expects($this->never())->method('createShareObject'); $this->assertSame('shareObject', $instance->create($this->share) ); } public function testCreateMailShare(): void { $this->share->expects($this->any())->method('getToken')->willReturn('token'); $this->share->expects($this->once())->method('setToken')->with('token'); $this->share->expects($this->any())->method('getSharedBy')->willReturn('validby@valid.com'); $this->share->expects($this->any())->method('getSharedWith')->willReturn('validwith@valid.com'); $this->share->expects($this->any())->method('getNote')->willReturn('Check this!'); $this->share->expects($this->any())->method('getMailSend')->willReturn(true); $node = $this->getMockBuilder('OCP\Files\Node')->getMock(); $node->expects($this->any())->method('getName')->willReturn('fileName'); $this->share->expects($this->any())->method('getNode')->willReturn($node); $instance = $this->getInstance(['generateToken', 'addShareToDB', 'sendMailNotification']); $instance->expects($this->once())->method('generateToken')->willReturn('token'); $instance->expects($this->once())->method('addShareToDB')->willReturn(42); // The manager handle the mail sending $instance->expects($this->never())->method('sendMailNotification'); $this->assertSame(42, $this->invokePrivate($instance, 'createMailShare', [$this->share]) ); } public function testGenerateToken(): void { $instance = $this->getInstance(); $this->secureRandom->expects($this->once())->method('generate')->willReturn('token'); $this->assertSame('token', $this->invokePrivate($instance, 'generateToken') ); } public function testAddShareToDB(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $password = 'password'; $sendPasswordByTalk = true; $hideDownload = true; $label = 'label'; $expiration = new \DateTime(); $passwordExpirationTime = new \DateTime(); $instance = $this->getInstance(); $id = $this->invokePrivate( $instance, 'addShareToDB', [ $itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $passwordExpirationTime, $sendPasswordByTalk, $hideDownload, $label, $expiration ] ); $qb = $this->connection->getQueryBuilder(); $qb->select('*') ->from('share') ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); $qResult = $qb->execute(); $result = $qResult->fetchAll(); $qResult->closeCursor(); $this->assertSame(1, count($result)); $this->assertSame($itemSource, (int)$result[0]['item_source']); $this->assertSame($itemType, $result[0]['item_type']); $this->assertSame($shareWith, $result[0]['share_with']); $this->assertSame($sharedBy, $result[0]['uid_initiator']); $this->assertSame($uidOwner, $result[0]['uid_owner']); $this->assertSame($permissions, (int)$result[0]['permissions']); $this->assertSame($token, $result[0]['token']); $this->assertSame($password, $result[0]['password']); $this->assertSame($passwordExpirationTime->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['password_expiration_time'])->getTimestamp()); $this->assertSame($sendPasswordByTalk, (bool)$result[0]['password_by_talk']); $this->assertSame($hideDownload, (bool)$result[0]['hide_download']); $this->assertSame($label, $result[0]['label']); $this->assertSame($expiration->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['expiration'])->getTimestamp()); } public function testUpdate(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $note = 'personal note'; $instance = $this->getInstance(); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note); $this->share->expects($this->once())->method('getPermissions')->willReturn($permissions + 1); $this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner); $this->share->expects($this->once())->method('getSharedBy')->willReturn($sharedBy); $this->share->expects($this->any())->method('getNote')->willReturn($note); $this->share->expects($this->atLeastOnce())->method('getId')->willReturn($id); $this->share->expects($this->atLeastOnce())->method('getNodeId')->willReturn($itemSource); $this->share->expects($this->once())->method('getSharedWith')->willReturn($shareWith); $this->assertSame($this->share, $instance->update($this->share) ); $qb = $this->connection->getQueryBuilder(); $qb->select('*') ->from('share') ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); $qResult = $qb->execute(); $result = $qResult->fetchAll(); $qResult->closeCursor(); $this->assertSame(1, count($result)); $this->assertSame($itemSource, (int)$result[0]['item_source']); $this->assertSame($itemType, $result[0]['item_type']); $this->assertSame($shareWith, $result[0]['share_with']); $this->assertSame($sharedBy, $result[0]['uid_initiator']); $this->assertSame($uidOwner, $result[0]['uid_owner']); $this->assertSame($permissions + 1, (int)$result[0]['permissions']); $this->assertSame($token, $result[0]['token']); $this->assertSame($note, $result[0]['note']); } public function dataUpdateSendPassword() { return [ ['password', 'hashed', 'hashed new', false, false, true], ['', 'hashed', 'hashed new', false, false, false], [null, 'hashed', 'hashed new', false, false, false], ['password', 'hashed', 'hashed', false, false, false], ['password', 'hashed', 'hashed new', false, true, false], ['password', 'hashed', 'hashed new', true, false, true], ['password', 'hashed', 'hashed', true, false, true], ]; } /** * @dataProvider dataUpdateSendPassword * * @param string|null plainTextPassword * @param string originalPassword * @param string newPassword * @param string originalSendPasswordByTalk * @param string newSendPasswordByTalk * @param bool sendMail */ public function testUpdateSendPassword($plainTextPassword, string $originalPassword, string $newPassword, $originalSendPasswordByTalk, $newSendPasswordByTalk, bool $sendMail): void { $node = $this->createMock(File::class); $node->expects($this->any())->method('getName')->willReturn('filename'); $this->settingsManager->method('sendPasswordByMail')->willReturn(true); $originalShare = $this->getMockBuilder(IShare::class)->getMock(); $originalShare->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $originalShare->expects($this->any())->method('getNode')->willReturn($node); $originalShare->expects($this->any())->method('getId')->willReturn(42); $originalShare->expects($this->any())->method('getPassword')->willReturn($originalPassword); $originalShare->expects($this->any())->method('getSendPasswordByTalk')->willReturn($originalSendPasswordByTalk); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getPassword')->willReturn($newPassword); $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn($newSendPasswordByTalk); if ($sendMail) { $this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.RecipientPasswordNotification', [ 'filename' => 'filename', 'password' => $plainTextPassword, 'initiator' => null, 'initiatorEmail' => null, 'shareWith' => 'receiver@example.com', ]); $this->mailer->expects($this->once())->method('send'); } else { $this->mailer->expects($this->never())->method('send'); } $instance = $this->getInstance(['getShareById', 'createPasswordSendActivity']); $instance->expects($this->once())->method('getShareById')->willReturn($originalShare); $this->assertSame($share, $instance->update($share, $plainTextPassword) ); } public function testDelete(): void { $instance = $this->getInstance(['removeShareFromTable', 'createShareActivity']); $this->share->expects($this->once())->method('getId')->willReturn(42); $instance->expects($this->once())->method('removeShareFromTable')->with(42); $instance->expects($this->once())->method('createShareActivity')->with($this->share, 'unshare'); $instance->delete($this->share); } public function testGetShareById(): void { $instance = $this->getInstance(['createShareObject']); $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $this->createDummyShare($itemType, $itemSource, $shareWith, 'user1wrong', 'user2wrong', $permissions, $token); $id2 = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $instance->expects($this->once())->method('createShareObject') ->willReturnCallback( function ($data) use ($uidOwner, $sharedBy, $id2) { $this->assertSame($uidOwner, $data['uid_owner']); $this->assertSame($sharedBy, $data['uid_initiator']); $this->assertSame($id2, (int)$data['id']); return $this->share; } ); $result = $instance->getShareById($id2); $this->assertInstanceOf('OCP\Share\IShare', $result); } public function testGetShareByIdFailed(): void { $this->expectException(ShareNotFound::class); $instance = $this->getInstance(['createShareObject']); $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $instance->getShareById($id + 1); } public function testGetShareByPath(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $node = $this->createMock(Node::class); $node->expects($this->once())->method('getId')->willReturn($itemSource); $instance = $this->getInstance(['createShareObject']); $this->createDummyShare($itemType, 111, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $instance->expects($this->once())->method('createShareObject') ->willReturnCallback( function ($data) use ($uidOwner, $sharedBy, $id) { $this->assertSame($uidOwner, $data['uid_owner']); $this->assertSame($sharedBy, $data['uid_initiator']); $this->assertSame($id, (int)$data['id']); return $this->share; } ); $result = $instance->getSharesByPath($node); $this->assertTrue(is_array($result)); $this->assertSame(1, count($result)); $this->assertInstanceOf('OCP\Share\IShare', $result[0]); } public function testGetShareByToken(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $instance = $this->getInstance(['createShareObject']); $idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, '', IShare::TYPE_LINK); $this->assertTrue($idMail !== $idPublic); $instance->expects($this->once())->method('createShareObject') ->willReturnCallback( function ($data) use ($idMail) { $this->assertSame($idMail, (int)$data['id']); return $this->share; } ); $result = $instance->getShareByToken('token'); $this->assertInstanceOf('OCP\Share\IShare', $result); } public function testGetShareByTokenFailed(): void { $this->expectException(ShareNotFound::class); $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $instance = $this->getInstance(['createShareObject']); $idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, 'token2', '', IShare::TYPE_LINK); $this->assertTrue($idMail !== $idPublic); $this->assertInstanceOf('OCP\Share\IShare', $instance->getShareByToken('token2') ); } public function testRemoveShareFromTable(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $instance = $this->getInstance(); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $query = $this->connection->getQueryBuilder(); $query->select('*')->from('share') ->where($query->expr()->eq('id', $query->createNamedParameter($id))); $result = $query->execute(); $before = $result->fetchAll(); $result->closeCursor(); $this->assertTrue(is_array($before)); $this->assertSame(1, count($before)); $this->invokePrivate($instance, 'removeShareFromTable', [$id]); $query = $this->connection->getQueryBuilder(); $query->select('*')->from('share') ->where($query->expr()->eq('id', $query->createNamedParameter($id))); $result = $query->execute(); $after = $result->fetchAll(); $result->closeCursor(); $this->assertTrue(is_array($after)); $this->assertEmpty($after); } public function testUserDeleted(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, 'user2Wrong', $permissions, $token); $query = $this->connection->getQueryBuilder(); $query->select('*')->from('share'); $result = $query->execute(); $before = $result->fetchAll(); $result->closeCursor(); $this->assertTrue(is_array($before)); $this->assertSame(2, count($before)); $instance = $this->getInstance(); $instance->userDeleted($uidOwner, IShare::TYPE_EMAIL); $query = $this->connection->getQueryBuilder(); $query->select('*')->from('share'); $result = $query->execute(); $after = $result->fetchAll(); $result->closeCursor(); $this->assertTrue(is_array($after)); $this->assertSame(1, count($after)); $this->assertSame($id, (int)$after[0]['id']); } public function testGetRawShare(): void { $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $instance = $this->getInstance(); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $result = $this->invokePrivate($instance, 'getRawShare', [$id]); $this->assertTrue(is_array($result)); $this->assertSame($itemSource, (int)$result['item_source']); $this->assertSame($itemType, $result['item_type']); $this->assertSame($shareWith, $result['share_with']); $this->assertSame($sharedBy, $result['uid_initiator']); $this->assertSame($uidOwner, $result['uid_owner']); $this->assertSame($permissions, (int)$result['permissions']); $this->assertSame($token, $result['token']); } public function testGetRawShareFailed(): void { $this->expectException(ShareNotFound::class); $itemSource = 11; $itemType = 'file'; $shareWith = 'user@server.com'; $sharedBy = 'user1'; $uidOwner = 'user2'; $permissions = 1; $token = 'token'; $instance = $this->getInstance(); $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token); $this->invokePrivate($instance, 'getRawShare', [$id + 1]); } private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note = '', $shareType = IShare::TYPE_EMAIL) { $qb = $this->connection->getQueryBuilder(); $qb->insert('share') ->setValue('share_type', $qb->createNamedParameter($shareType)) ->setValue('item_type', $qb->createNamedParameter($itemType)) ->setValue('item_source', $qb->createNamedParameter($itemSource)) ->setValue('file_source', $qb->createNamedParameter($itemSource)) ->setValue('share_with', $qb->createNamedParameter($shareWith)) ->setValue('uid_owner', $qb->createNamedParameter($uidOwner)) ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy)) ->setValue('permissions', $qb->createNamedParameter($permissions)) ->setValue('token', $qb->createNamedParameter($token)) ->setValue('note', $qb->createNamedParameter($note)) ->setValue('stime', $qb->createNamedParameter(time())); /* * Added to fix https://github.com/owncloud/core/issues/22215 * Can be removed once we get rid of ajax/share.php */ $qb->setValue('file_target', $qb->createNamedParameter('')); $qb->execute(); $id = $qb->getLastInsertId(); return (int)$id; } public function testGetSharesInFolder(): void { $userManager = \OC::$server->getUserManager(); $rootFolder = \OC::$server->getRootFolder(); $this->shareManager->expects($this->any()) ->method('newShare') ->willReturn(new Share($rootFolder, $userManager)); $provider = $this->getInstance(['sendMailNotification', 'createShareActivity']); $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $u1 = $userManager->createUser('testFed', md5(time())); $u2 = $userManager->createUser('testFed2', md5(time())); $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo'); $file1 = $folder1->newFile('bar1'); $file2 = $folder1->newFile('bar2'); $share1 = $this->shareManager->newShare(); $share1->setSharedWith('user@server.com') ->setSharedBy($u1->getUID()) ->setShareOwner($u1->getUID()) ->setPermissions(Constants::PERMISSION_READ) ->setNode($file1); $provider->create($share1); $share2 = $this->shareManager->newShare(); $share2->setSharedWith('user@server.com') ->setSharedBy($u2->getUID()) ->setShareOwner($u1->getUID()) ->setPermissions(Constants::PERMISSION_READ) ->setNode($file2); $provider->create($share2); $result = $provider->getSharesInFolder($u1->getUID(), $folder1, false); $this->assertCount(1, $result); $this->assertCount(1, $result[$file1->getId()]); $result = $provider->getSharesInFolder($u1->getUID(), $folder1, true); $this->assertCount(2, $result); $this->assertCount(1, $result[$file1->getId()]); $this->assertCount(1, $result[$file2->getId()]); $u1->delete(); $u2->delete(); } public function testGetAccessList(): void { $userManager = \OC::$server->getUserManager(); $rootFolder = \OC::$server->getRootFolder(); $this->shareManager->expects($this->any()) ->method('newShare') ->willReturn(new Share($rootFolder, $userManager)); $provider = $this->getInstance(['sendMailNotification', 'createShareActivity']); $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true); $u1 = $userManager->createUser('testFed', md5(time())); $u2 = $userManager->createUser('testFed2', md5(time())); $folder = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo'); $accessList = $provider->getAccessList([$folder], true); $this->assertArrayHasKey('public', $accessList); $this->assertFalse($accessList['public']); $accessList = $provider->getAccessList([$folder], false); $this->assertArrayHasKey('public', $accessList); $this->assertFalse($accessList['public']); $share1 = $this->shareManager->newShare(); $share1->setSharedWith('user@server.com') ->setSharedBy($u1->getUID()) ->setShareOwner($u1->getUID()) ->setPermissions(Constants::PERMISSION_READ) ->setNode($folder); $share1 = $provider->create($share1); $share2 = $this->shareManager->newShare(); $share2->setSharedWith('user2@server.com') ->setSharedBy($u2->getUID()) ->setShareOwner($u1->getUID()) ->setPermissions(Constants::PERMISSION_READ) ->setNode($folder); $share2 = $provider->create($share2); $accessList = $provider->getAccessList([$folder], true); $this->assertArrayHasKey('public', $accessList); $this->assertTrue($accessList['public']); $accessList = $provider->getAccessList([$folder], false); $this->assertArrayHasKey('public', $accessList); $this->assertTrue($accessList['public']); $provider->delete($share2); $accessList = $provider->getAccessList([$folder], true); $this->assertArrayHasKey('public', $accessList); $this->assertTrue($accessList['public']); $accessList = $provider->getAccessList([$folder], false); $this->assertArrayHasKey('public', $accessList); $this->assertTrue($accessList['public']); $provider->delete($share1); $accessList = $provider->getAccessList([$folder], true); $this->assertArrayHasKey('public', $accessList); $this->assertFalse($accessList['public']); $accessList = $provider->getAccessList([$folder], false); $this->assertArrayHasKey('public', $accessList); $this->assertFalse($accessList['public']); $u1->delete(); $u2->delete(); } public function testSendMailNotificationWithSameUserAndUserEmail(): void { $provider = $this->getInstance(); $user = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true); $this->userManager ->expects($this->once()) ->method('get') ->with('OwnerUser') ->willReturn($user); $user ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mrs. Owner User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mrs. Owner User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud' ]); $user ->expects($this->once()) ->method('getEMailAddress') ->willReturn('owner@example.com'); $message ->expects($this->once()) ->method('setReplyTo') ->with(['owner@example.com' => 'Mrs. Owner User']); $this->defaults ->expects($this->exactly(2)) ->method('getSlogan') ->willReturn('Testing like 1990'); $template ->expects($this->once()) ->method('addFooter') ->with('UnitTestCloud - Testing like 1990'); $template ->expects($this->once()) ->method('setSubject') ->with('Mrs. Owner User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } public function testSendMailNotificationWithSameUserAndUserEmailAndNote(): void { $provider = $this->getInstance(); $user = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true); $this->userManager ->expects($this->once()) ->method('get') ->with('OwnerUser') ->willReturn($user); $user ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mrs. Owner User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mrs. Owner User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $this->urlGenerator->expects($this->once())->method('imagePath') ->with('core', 'caldav/description.png') ->willReturn('core/img/caldav/description.png'); $this->urlGenerator->expects($this->once())->method('getAbsoluteURL') ->with('core/img/caldav/description.png') ->willReturn('https://example.com/core/img/caldav/description.png'); $template ->expects($this->once()) ->method('addBodyListItem') ->with( 'This is a note to the recipient', 'Note:', 'https://example.com/core/img/caldav/description.png', 'This is a note to the recipient' ); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud' ]); $user ->expects($this->once()) ->method('getEMailAddress') ->willReturn('owner@example.com'); $message ->expects($this->once()) ->method('setReplyTo') ->with(['owner@example.com' => 'Mrs. Owner User']); $this->defaults ->expects($this->exactly(2)) ->method('getSlogan') ->willReturn('Testing like 1990'); $template ->expects($this->once()) ->method('addFooter') ->with('UnitTestCloud - Testing like 1990'); $template ->expects($this->once()) ->method('setSubject') ->with('Mrs. Owner User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn('This is a note to the recipient'); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } public function testSendMailNotificationWithSameUserAndUserEmailAndExpiration(): void { $provider = $this->getInstance(); $user = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true); $this->userManager ->expects($this->once()) ->method('get') ->with('OwnerUser') ->willReturn($user); $user ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mrs. Owner User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mrs. Owner User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $expiration = new DateTime('2001-01-01'); $this->l->expects($this->once()) ->method('l') ->with('date', $expiration, ['width' => 'medium']) ->willReturn('2001-01-01'); $this->urlGenerator->expects($this->once())->method('imagePath') ->with('core', 'caldav/time.png') ->willReturn('core/img/caldav/time.png'); $this->urlGenerator->expects($this->once())->method('getAbsoluteURL') ->with('core/img/caldav/time.png') ->willReturn('https://example.com/core/img/caldav/time.png'); $template ->expects($this->once()) ->method('addBodyListItem') ->with( 'This share is valid until 2001-01-01 at midnight', 'Expiration:', 'https://example.com/core/img/caldav/time.png', ); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud' ]); $user ->expects($this->once()) ->method('getEMailAddress') ->willReturn('owner@example.com'); $message ->expects($this->once()) ->method('setReplyTo') ->with(['owner@example.com' => 'Mrs. Owner User']); $this->defaults ->expects($this->exactly(2)) ->method('getSlogan') ->willReturn('Testing like 1990'); $template ->expects($this->once()) ->method('addFooter') ->with('UnitTestCloud - Testing like 1990'); $template ->expects($this->once()) ->method('setSubject') ->with('Mrs. Owner User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getExpirationDate')->willReturn($expiration); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } public function testSendMailNotificationWithDifferentUserAndNoUserEmail(): void { $provider = $this->getInstance(); $initiatorUser = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true); $this->userManager ->expects($this->once()) ->method('get') ->with('InitiatorUser') ->willReturn($initiatorUser); $initiatorUser ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mr. Initiator User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mr. Initiator User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'Mr. Initiator User via UnitTestCloud' ]); $message ->expects($this->never()) ->method('setReplyTo'); $template ->expects($this->once()) ->method('addFooter') ->with(''); $template ->expects($this->once()) ->method('setSubject') ->with('Mr. Initiator User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } public function testSendMailNotificationWithSameUserAndUserEmailAndReplyToDesactivate(): void { $provider = $this->getInstance(); $user = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false); $this->userManager ->expects($this->once()) ->method('get') ->with('OwnerUser') ->willReturn($user); $user ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mrs. Owner User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mrs. Owner User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud' ]); // Since replyToInitiator is false, we never get the initiator email address $user ->expects($this->never()) ->method('getEMailAddress'); $message ->expects($this->never()) ->method('setReplyTo'); $template ->expects($this->once()) ->method('addFooter') ->with(''); $template ->expects($this->once()) ->method('setSubject') ->with('Mrs. Owner User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } public function testSendMailNotificationWithDifferentUserAndNoUserEmailAndReplyToDesactivate(): void { $provider = $this->getInstance(); $initiatorUser = $this->createMock(IUser::class); $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false); $this->userManager ->expects($this->once()) ->method('get') ->with('InitiatorUser') ->willReturn($initiatorUser); $initiatorUser ->expects($this->once()) ->method('getDisplayName') ->willReturn('Mr. Initiator User'); $message = $this->createMock(Message::class); $this->mailer ->expects($this->once()) ->method('createMessage') ->willReturn($message); $template = $this->createMock(IEMailTemplate::class); $this->mailer ->expects($this->once()) ->method('createEMailTemplate') ->willReturn($template); $template ->expects($this->once()) ->method('addHeader'); $template ->expects($this->once()) ->method('addHeading') ->with('Mr. Initiator User shared file.txt with you'); $template ->expects($this->once()) ->method('addBodyText') ->with('Click the button below to open it.'); $template ->expects($this->once()) ->method('addBodyButton') ->with( 'Open file.txt', 'https://example.com/file.txt' ); $message ->expects($this->once()) ->method('setTo') ->with(['john@doe.com']); $this->defaults ->expects($this->once()) ->method('getName') ->willReturn('UnitTestCloud'); $message ->expects($this->once()) ->method('setFrom') ->with([ Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud' ]); $message ->expects($this->never()) ->method('setReplyTo'); $template ->expects($this->once()) ->method('addFooter') ->with(''); $template ->expects($this->once()) ->method('setSubject') ->with('Mr. Initiator User shared file.txt with you'); $message ->expects($this->once()) ->method('useTemplate') ->with($template); $this->mailer->expects($this->once()) ->method('validateMailAddress') ->willReturn(true); $this->mailer ->expects($this->once()) ->method('send') ->with($message); $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute') ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) ->willReturn('https://example.com/file.txt'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->any())->method('getName')->willReturn('file.txt'); $share = $this->getMockBuilder(IShare::class)->getMock(); $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser'); $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com'); $share->expects($this->any())->method('getNode')->willReturn($node); $share->expects($this->any())->method('getId')->willReturn(42); $share->expects($this->any())->method('getNote')->willReturn(''); $share->expects($this->any())->method('getToken')->willReturn('token'); self::invokePrivate( $provider, 'sendMailNotification', [$share] ); } }