Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix idn emails not working in shares #30600

Merged
merged 3 commits into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions apps/sharebymail/lib/ShareByMailProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@ protected function createMailShare(IShare $share) {
$share->getNote()
);

if (!$this->mailer->validateMailAddress($share->getSharedWith())) {
$this->removeShareFromTable($shareId);
$e = new HintException('Failed to send share by mail. Got an invalid email address: ' . $share->getSharedWith(),
$this->l->t('Failed to send share by email. Got an invalid email address'));
$this->logger->error('Failed to send share by mail. Got an invalid email address ' . $share->getSharedWith(), [
'app' => 'sharebymail',
'exception' => $e,
]);
}

try {
$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
['token' => $share->getToken()]);
Expand Down Expand Up @@ -679,7 +689,7 @@ public function getChildren(IShare $parent) {
* @param \DateTime|null $expirationTime
* @return int
*/
protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload, $label, $expirationTime, $note = '') {
protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload, $label, $expirationTime, $note = ''): int {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert('share')
->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
Expand Down Expand Up @@ -774,7 +784,7 @@ public function delete(IShare $share) {
} catch (\Exception $e) {
}

$this->removeShareFromTable($share->getId());
$this->removeShareFromTable((int)$share->getId());
}

/**
Expand Down Expand Up @@ -970,9 +980,9 @@ public function getShareByToken($token) {
/**
* remove share from table
*
* @param string $shareId
* @param int $shareId
*/
protected function removeShareFromTable($shareId) {
protected function removeShareFromTable(int $shareId): void {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
Expand Down
6 changes: 5 additions & 1 deletion apps/sharebymail/tests/ShareByMailProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public function testCreate() {

public function testCreateSendPasswordByMailWithoutEnforcedPasswordProtection() {
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$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');

Expand Down Expand Up @@ -459,6 +459,7 @@ public function testCreateFailed() {
public function testCreateMailShare() {
$this->share->expects($this->any())->method('getToken')->willReturn('token');
$this->share->expects($this->once())->method('setToken')->with('token');
$this->share->expects($this->any())->method('getSharedWith')->willReturn('valid@valid.com');
$node = $this->getMockBuilder('OCP\Files\Node')->getMock();
$node->expects($this->any())->method('getName')->willReturn('fileName');
$this->share->expects($this->any())->method('getNode')->willReturn($node);
Expand All @@ -483,6 +484,7 @@ public function testCreateMailShareFailed() {

$this->share->expects($this->any())->method('getToken')->willReturn('token');
$this->share->expects($this->once())->method('setToken')->with('token');
$this->share->expects($this->any())->method('getSharedWith')->willReturn('valid@valid.com');
$node = $this->getMockBuilder('OCP\Files\Node')->getMock();
$node->expects($this->any())->method('getName')->willReturn('fileName');
$this->share->expects($this->any())->method('getNode')->willReturn($node);
Expand Down Expand Up @@ -987,6 +989,7 @@ public function testGetSharesInFolder() {
->willReturn(new \OC\Share20\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()));
Expand Down Expand Up @@ -1033,6 +1036,7 @@ public function testGetAccessList() {
->willReturn(new \OC\Share20\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()));
Expand Down
10 changes: 7 additions & 3 deletions lib/private/Collaboration/Collaborators/MailPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShare;
use OCP\Mail\IMailer;

class MailPlugin implements ISearchPlugin {
/* @var bool */
Expand All @@ -64,19 +65,23 @@ class MailPlugin implements ISearchPlugin {
private $knownUserService;
/** @var IUserSession */
private $userSession;
/** @var IMailer */
private $mailer;

public function __construct(IManager $contactsManager,
ICloudIdManager $cloudIdManager,
IConfig $config,
IGroupManager $groupManager,
KnownUserService $knownUserService,
IUserSession $userSession) {
IUserSession $userSession,
IMailer $mailer) {
$this->contactsManager = $contactsManager;
$this->cloudIdManager = $cloudIdManager;
$this->config = $config;
$this->groupManager = $groupManager;
$this->knownUserService = $knownUserService;
$this->userSession = $userSession;
$this->mailer = $mailer;

$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
Expand Down Expand Up @@ -247,8 +252,7 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) {
$userResults['wide'] = array_slice($userResults['wide'], $offset, $limit);
}


if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) {
if (!$searchResult->hasExactIdMatch($emailType) && $this->mailer->validateMailAddress($search)) {
$result['exact'][] = [
'label' => $search,
'uuid' => $search,
Expand Down
58 changes: 50 additions & 8 deletions tests/lib/Collaboration/Collaborators/MailPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\IShare;
use OCP\Mail\IMailer;
use Test\TestCase;

class MailPluginTest extends TestCase {
Expand Down Expand Up @@ -64,6 +65,9 @@ class MailPluginTest extends TestCase {
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
protected $userSession;

/** @var IMailer|\PHPUnit\Framework\MockObject\MockObject */
protected $mailer;

protected function setUp(): void {
parent::setUp();

Expand All @@ -72,6 +76,7 @@ protected function setUp(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
$this->knownUserService = $this->createMock(KnownUserService::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->mailer = $this->createMock(IMailer::class);
$this->cloudIdManager = new CloudIdManager($this->contactsManager, $this->createMock(IURLGenerator::class), $this->createMock(IUserManager::class));

$this->searchResult = new SearchResult();
Expand All @@ -84,7 +89,8 @@ public function instantiatePlugin() {
$this->config,
$this->groupManager,
$this->knownUserService,
$this->userSession
$this->userSession,
$this->mailer
);
}

Expand All @@ -97,7 +103,7 @@ public function instantiatePlugin() {
* @param array $expected
* @param bool $reachedEnd
*/
public function testSearch($searchTerm, $contacts, $shareeEnumeration, $expected, $exactIdMatch, $reachedEnd) {
public function testSearch($searchTerm, $contacts, $shareeEnumeration, $expected, $exactIdMatch, $reachedEnd, $validEmail) {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(
Expand All @@ -117,6 +123,9 @@ function ($appName, $key, $default) use ($shareeEnumeration) {
$this->userSession->method('getUser')
->willReturn($currentUser);

$this->mailer->method('validateMailAddress')
->willReturn($validEmail);

$this->contactsManager->expects($this->any())
->method('search')
->willReturnCallback(function ($search, $searchAttributes) use ($searchTerm, $contacts) {
Expand All @@ -137,9 +146,9 @@ function ($appName, $key, $default) use ($shareeEnumeration) {
public function dataGetEmail() {
return [
// data set 0
['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, false],
['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, false, false],
// data set 1
['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, false],
['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, false, false],
// data set 2
[
'test@remote.com',
Expand All @@ -148,6 +157,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 3
[ // no valid email address
Expand All @@ -157,6 +167,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 4
[
Expand All @@ -166,6 +177,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 5
[
Expand Down Expand Up @@ -193,6 +205,7 @@ public function dataGetEmail() {
['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 6
[
Expand Down Expand Up @@ -221,6 +234,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 7
[
Expand Down Expand Up @@ -248,6 +262,7 @@ public function dataGetEmail() {
['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 8
[
Expand Down Expand Up @@ -276,6 +291,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 9
[
Expand Down Expand Up @@ -303,6 +319,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
true,
false,
false,
],
// data set 10
[
Expand Down Expand Up @@ -330,6 +347,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
true,
false,
false,
],
// data set 11
// contact with space
Expand Down Expand Up @@ -358,6 +376,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User Name @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'user name@localhost']]]]],
true,
false,
false,
],
// data set 12
// remote with space, no contact
Expand Down Expand Up @@ -387,6 +406,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 13
// Local user found by email
Expand All @@ -405,6 +425,7 @@ public function dataGetEmail() {
['users' => [], 'exact' => ['users' => [['uuid' => 'uid1', 'name' => 'User', 'label' => 'User (test@example.com)','value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'shareWithDisplayNameUnique' => 'test@example.com']]]],
true,
false,
true,
],
// data set 14
// Current local user found by email => no result
Expand All @@ -423,6 +444,7 @@ public function dataGetEmail() {
['exact' => []],
false,
false,
true,
],
// data set 15
// Pagination and "more results" for user matches byyyyyyy emails
Expand Down Expand Up @@ -465,6 +487,7 @@ public function dataGetEmail() {
], 'emails' => [], 'exact' => ['users' => [], 'emails' => []]],
false,
true,
false,
],
// data set 16
// Pagination and "more results" for normal emails
Expand Down Expand Up @@ -503,6 +526,7 @@ public function dataGetEmail() {
], 'exact' => ['emails' => []]],
false,
true,
false,
],
// data set 17
// multiple email addresses with type
Expand Down Expand Up @@ -536,6 +560,18 @@ public function dataGetEmail() {
]]],
false,
false,
false,
],
// data set 18
// idn email
[
'test@lölölölölölölöl.com',
[],
true,
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@lölölölölölölöl.com', 'label' => 'test@lölölölölölölöl.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@lölölölölölölöl.com']]]]],
false,
false,
true,
],
];
}
Expand All @@ -550,7 +586,7 @@ public function dataGetEmail() {
* @param bool $reachedEnd
* @param array groups
*/
public function testSearchGroupsOnly($searchTerm, $contacts, $expected, $exactIdMatch, $reachedEnd, $userToGroupMapping) {
public function testSearchGroupsOnly($searchTerm, $contacts, $expected, $exactIdMatch, $reachedEnd, $userToGroupMapping, $validEmail) {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(
Expand All @@ -573,6 +609,9 @@ function ($appName, $key, $default) {
->method('getUID')
->willReturn('currentUser');

$this->mailer->method('validateMailAddress')
->willReturn($validEmail);

$this->contactsManager->expects($this->any())
->method('search')
->willReturnCallback(function ($search, $searchAttributes) use ($searchTerm, $contacts) {
Expand Down Expand Up @@ -626,7 +665,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group1"]
]
],
false,
],
// The user `User` cannot share with the current user
[
Expand All @@ -646,7 +686,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group2"]
]
],
false,
],
// The user `User` cannot share with the current user, but there is an exact match on the e-mail address -> share by e-mail
[
Expand All @@ -666,7 +707,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group2"]
]
],
true,
]
];
}
Expand Down