Merge pull request #657 from nextcloud/share-by-mail

New share provider: Share by mail
This commit is contained in:
Joas Schilling 2016-11-02 11:04:33 +01:00 committed by GitHub
commit 7da3ba3f91
25 changed files with 2124 additions and 294 deletions

1
.gitignore vendored
View File

@ -16,6 +16,7 @@
!/apps/files !/apps/files
!/apps/federation !/apps/federation
!/apps/federatedfilesharing !/apps/federatedfilesharing
!/apps/sharebymail
!/apps/encryption !/apps/encryption
!/apps/files_external !/apps/files_external
!/apps/files_sharing !/apps/files_sharing

View File

@ -200,7 +200,8 @@ class ApiController extends Controller {
\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_USER,
\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_GROUP,
\OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_LINK,
\OCP\Share::SHARE_TYPE_REMOTE \OCP\Share::SHARE_TYPE_REMOTE,
\OCP\Share::SHARE_TYPE_EMAIL
]; ];
foreach ($requestedShareTypes as $requestedShareType) { foreach ($requestedShareTypes as $requestedShareType) {
// one of each type is enough to find out about the types // one of each type is enough to find out about the types

View File

@ -36,7 +36,6 @@ use OCP\IL10N;
use OCP\IUserManager; use OCP\IUserManager;
use OCP\IRequest; use OCP\IRequest;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\Lock\LockedException; use OCP\Lock\LockedException;
use OCP\Share\IManager; use OCP\Share\IManager;
@ -186,7 +185,11 @@ class ShareAPIController extends OCSController {
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
$result['share_with'] = $share->getSharedWith(); $result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $share->getSharedWith(); $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
$result['token'] = $share->getToken();
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
$result['token'] = $share->getToken(); $result['token'] = $share->getToken();
} }
@ -195,6 +198,28 @@ class ShareAPIController extends OCSController {
return $result; return $result;
} }
/**
* Check if one of the users address books knows the exact property, if
* yes we return the full name.
*
* @param string $query
* @param string $property
* @return string
*/
private function getDisplayNameFromAddressBook($query, $property) {
// FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
$result = \OC::$server->getContactsManager()->search($query, [$property]);
foreach ($result as $r) {
foreach($r[$property] as $value) {
if ($value === $query) {
return $r['FN'];
}
}
}
return $query;
}
/** /**
* Get a specific share by id * Get a specific share by id
* *
@ -400,6 +425,17 @@ class ShareAPIController extends OCSController {
$share->setSharedWith($shareWith); $share->setSharedWith($shareWith);
$share->setPermissions($permissions); $share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
if ($share->getNodeType() === 'file') {
$share->setPermissions(\OCP\Constants::PERMISSION_READ);
} else {
$share->setPermissions(
\OCP\Constants::PERMISSION_READ |
\OCP\Constants::PERMISSION_CREATE |
\OCP\Constants::PERMISSION_UPDATE |
\OCP\Constants::PERMISSION_DELETE);
}
$share->setSharedWith($shareWith);
} else { } else {
throw new OCSBadRequestException($this->l->t('Unknown share type')); throw new OCSBadRequestException($this->l->t('Unknown share type'));
} }
@ -466,6 +502,9 @@ class ShareAPIController extends OCSController {
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0)); $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0)); $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
if($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
}
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
} }
@ -541,7 +580,12 @@ class ShareAPIController extends OCSController {
$userShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); $userShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
$groupShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); $groupShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
$linkShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); $linkShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
$shares = array_merge($userShares, $groupShares, $linkShares); if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
$mailShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
} else {
$mailShares = [];
}
$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares);
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
$federatedShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); $federatedShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
@ -774,14 +818,25 @@ class ShareAPIController extends OCSController {
// First check if it is an internal share. // First check if it is an internal share.
try { try {
$share = $this->shareManager->getShareById('ocinternal:' . $id); $share = $this->shareManager->getShareById('ocinternal:' . $id);
return $share;
} catch (ShareNotFound $e) { } catch (ShareNotFound $e) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { // Do nothing, just try the other share type
throw new ShareNotFound();
}
$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id);
} }
try {
if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
$share = $this->shareManager->getShareById('ocMailShare:' . $id);
return $share;
}
} catch (ShareNotFound $e) {
// Do nothing, just try the other share type
}
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
throw new ShareNotFound();
}
$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id);
return $share; return $share;
} }

View File

@ -273,15 +273,15 @@ class ShareesAPIController extends OCSController {
/** /**
* @param string $search * @param string $search
* @return array possible sharees * @return array
*/ */
protected function getRemote($search) { protected function getRemote($search) {
$this->result['remotes'] = []; $result = ['results' => [], 'exact' => []];
// Search in contacts // Search in contacts
//@todo Pagination missing //@todo Pagination missing
$addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']); $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
$foundRemoteById = false; $result['exactIdMatch'] = false;
foreach ($addressBookContacts as $contact) { foreach ($addressBookContacts as $contact) {
if (isset($contact['isLocalSystemBook'])) { if (isset($contact['isLocalSystemBook'])) {
continue; continue;
@ -295,10 +295,10 @@ class ShareesAPIController extends OCSController {
list(, $serverUrl) = $this->splitUserRemote($cloudId); list(, $serverUrl) = $this->splitUserRemote($cloudId);
if (strtolower($contact['FN']) === strtolower($search) || strtolower($cloudId) === strtolower($search)) { if (strtolower($contact['FN']) === strtolower($search) || strtolower($cloudId) === strtolower($search)) {
if (strtolower($cloudId) === strtolower($search)) { if (strtolower($cloudId) === strtolower($search)) {
$foundRemoteById = true; $result['exactIdMatch'] = true;
} }
$this->result['exact']['remotes'][] = [ $result['exact'][] = [
'label' => $contact['FN'], 'label' => $contact['FN'] . " ($cloudId)",
'value' => [ 'value' => [
'shareType' => Share::SHARE_TYPE_REMOTE, 'shareType' => Share::SHARE_TYPE_REMOTE,
'shareWith' => $cloudId, 'shareWith' => $cloudId,
@ -306,8 +306,8 @@ class ShareesAPIController extends OCSController {
], ],
]; ];
} else { } else {
$this->result['remotes'][] = [ $result['results'][] = [
'label' => $contact['FN'], 'label' => $contact['FN'] . " ($cloudId)",
'value' => [ 'value' => [
'shareType' => Share::SHARE_TYPE_REMOTE, 'shareType' => Share::SHARE_TYPE_REMOTE,
'shareWith' => $cloudId, 'shareWith' => $cloudId,
@ -320,11 +320,11 @@ class ShareesAPIController extends OCSController {
} }
if (!$this->shareeEnumeration) { if (!$this->shareeEnumeration) {
$this->result['remotes'] = []; $result['results'] = [];
} }
if (!$foundRemoteById && substr_count($search, '@') >= 1 && $this->offset === 0) { if (!$result['exactIdMatch'] && substr_count($search, '@') >= 1 && $this->offset === 0) {
$this->result['exact']['remotes'][] = [ $result['exact'][] = [
'label' => $search, 'label' => $search,
'value' => [ 'value' => [
'shareType' => Share::SHARE_TYPE_REMOTE, 'shareType' => Share::SHARE_TYPE_REMOTE,
@ -334,6 +334,8 @@ class ShareesAPIController extends OCSController {
} }
$this->reachedEndFor[] = 'remotes'; $this->reachedEndFor[] = 'remotes';
return $result;
} }
/** /**
@ -404,68 +406,6 @@ class ShareesAPIController extends OCSController {
return $remote; return $remote;
} }
/**
* @param string $search
*/
protected function getEmails($search) {
$this->result['emails'] = [];
$this->result['exact']['emails'] = [];
$foundEmail = false;
// Search in contacts
//@todo Pagination missing
$addressBookContacts = $this->contactsManager->search($search, ['FN', 'EMAIL']);
foreach ($addressBookContacts as $contact) {
if (!isset($contact['EMAIL'])) {
continue;
}
$emails = $contact['EMAIL'];
if (!is_array($emails)) {
$emails = [$emails];
}
foreach ($emails as $email) {
if (strtolower($search) === strtolower($contact['FN']) ||
strtolower($search) === strtolower($email)
) {
if (strtolower($search) === strtolower($email)) {
$foundEmail = true;
}
$this->result['exact']['emails'][] = [
'label' => $contact['FN'],
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $email,
],
];
} else if ($this->shareeEnumeration) {
$this->result['emails'][] = [
'label' => $contact['FN'],
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $email,
],
];
}
}
}
if (!$foundEmail && substr_count($search, '@') >= 1 && $this->offset === 0) {
$this->result['exact']['emails'][] = [
'label' => $search,
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $search,
],
];
}
$this->reachedEndFor[] = 'emails';
}
/** /**
* @NoAdminRequired * @NoAdminRequired
* *
@ -487,17 +427,16 @@ class ShareesAPIController extends OCSController {
$shareTypes = [ $shareTypes = [
Share::SHARE_TYPE_USER, Share::SHARE_TYPE_USER,
Share::SHARE_TYPE_REMOTE,
Share::SHARE_TYPE_EMAIL
]; ];
if ($this->shareManager->allowGroupSharing()) { if ($this->shareManager->allowGroupSharing()) {
$shareTypes[] = Share::SHARE_TYPE_GROUP; $shareTypes[] = Share::SHARE_TYPE_GROUP;
} }
$shareTypes[] = Share::SHARE_TYPE_EMAIL; if (isset($_GET['shareType']) && is_array($_GET['shareType'])) {
$shareTypes[] = Share::SHARE_TYPE_REMOTE; $shareTypes = array_intersect($shareTypes, $_GET['shareType']);
if (is_array($shareType)) {
$shareTypes = array_intersect($shareTypes, $shareType);
sort($shareTypes); sort($shareTypes);
} else if (is_numeric($shareType)) { } else if (is_numeric($shareType)) {
$shareTypes = array_intersect($shareTypes, [(int) $shareType]); $shareTypes = array_intersect($shareTypes, [(int) $shareType]);
@ -509,6 +448,11 @@ class ShareesAPIController extends OCSController {
$shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_REMOTE]); $shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_REMOTE]);
} }
if (!$this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
// Remove mail shares from type array, because the share provider is not loaded
$shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_EMAIL]);
}
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->limit = (int) $perPage; $this->limit = (int) $perPage;
@ -560,13 +504,30 @@ class ShareesAPIController extends OCSController {
} }
// Get remote // Get remote
$remoteResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) { if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) {
$this->getRemote($search); $remoteResults = $this->getRemote($search);
} }
// Get email $mailResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
if (in_array(Share::SHARE_TYPE_EMAIL, $shareTypes)) { if (in_array(Share::SHARE_TYPE_EMAIL, $shareTypes)) {
$this->getEmails($search); $mailResults = $this->getEmail($search);
}
// if we have a exact match, either for the federated cloud id or for the
// email address we only return the exact match. It is highly unlikely
// that the exact same email address and federated cloud id exists
if ($mailResults['exactIdMatch'] && !$remoteResults['exactIdMatch']) {
$this->result['emails'] = $mailResults['results'];
$this->result['exact']['emails'] = $mailResults['exact'];
} else if (!$mailResults['exactIdMatch'] && $remoteResults['exactIdMatch']) {
$this->result['remotes'] = $remoteResults['results'];
$this->result['exact']['remotes'] = $remoteResults['exact'];
} else {
$this->result['remotes'] = $remoteResults['results'];
$this->result['exact']['remotes'] = $remoteResults['exact'];
$this->result['emails'] = $mailResults['results'];
$this->result['exact']['emails'] = $mailResults['exact'];
} }
$response = new Http\DataResponse($this->result); $response = new Http\DataResponse($this->result);
@ -583,6 +544,70 @@ class ShareesAPIController extends OCSController {
return $response; return $response;
} }
/**
* @param string $search
* @return array
*/
protected function getEmail($search) {
$result = ['results' => [], 'exact' => []];
// Search in contacts
//@todo Pagination missing
$addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN']);
$result['exactIdMatch'] = false;
foreach ($addressBookContacts as $contact) {
if (isset($contact['isLocalSystemBook'])) {
continue;
}
if (isset($contact['EMAIL'])) {
$emailAddresses = $contact['EMAIL'];
if (!is_array($emailAddresses)) {
$emailAddresses = [$emailAddresses];
}
foreach ($emailAddresses as $emailAddress) {
if (strtolower($contact['FN']) === strtolower($search) || strtolower($emailAddress) === strtolower($search)) {
if (strtolower($emailAddress) === strtolower($search)) {
$result['exactIdMatch'] = true;
}
$result['exact'][] = [
'label' => $contact['FN'] . " ($emailAddress)",
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $emailAddress,
],
];
} else {
$result['results'][] = [
'label' => $contact['FN'] . " ($emailAddress)",
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $emailAddress,
],
];
}
}
}
}
if (!$this->shareeEnumeration) {
$result['results'] = [];
}
if (!$result['exactIdMatch'] && filter_var($search, FILTER_VALIDATE_EMAIL)) {
$result['exact'][] = [
'label' => $search,
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $search,
],
];
}
$this->reachedEndFor[] = 'emails';
return $result;
}
/** /**
* Generates a bunch of pagination links for the current page * Generates a bunch of pagination links for the current page
* *

View File

@ -234,6 +234,7 @@ class ApiTest extends TestCase {
function testEnfoceLinkPassword() { function testEnfoceLinkPassword() {
$password = md5(time());
$appConfig = \OC::$server->getAppConfig(); $appConfig = \OC::$server->getAppConfig();
$appConfig->setValue('core', 'shareapi_enforce_links_password', 'yes'); $appConfig->setValue('core', 'shareapi_enforce_links_password', 'yes');
@ -257,14 +258,14 @@ class ApiTest extends TestCase {
// share with password should succeed // share with password should succeed
$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1); $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
$result = $ocs->createShare($this->folder, \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', 'bar'); $result = $ocs->createShare($this->folder, \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', $password);
$ocs->cleanup(); $ocs->cleanup();
$data = $result->getData(); $data = $result->getData();
// setting new password should succeed // setting new password should succeed
$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1); $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
$ocs->updateShare($data['id'], null, 'bar'); $ocs->updateShare($data['id'], null, $password);
$ocs->cleanup(); $ocs->cleanup();
// removing password should fail // removing password should fail
@ -887,6 +888,9 @@ class ApiTest extends TestCase {
* @depends testCreateShareLink * @depends testCreateShareLink
*/ */
function testUpdateShare() { function testUpdateShare() {
$password = md5(time());
$node1 = $this->userFolder->get($this->filename); $node1 = $this->userFolder->get($this->filename);
$share1 = $this->shareManager->newShare(); $share1 = $this->shareManager->newShare();
$share1->setNode($node1) $share1->setNode($node1)
@ -915,7 +919,7 @@ class ApiTest extends TestCase {
$this->assertNull($share2->getPassword()); $this->assertNull($share2->getPassword());
$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1); $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
$ocs->updateShare($share2->getId(), null, 'foo'); $ocs->updateShare($share2->getId(), null, $password);
$ocs->cleanup(); $ocs->cleanup();
$share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId()); $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId());

View File

@ -23,8 +23,10 @@
*/ */
namespace OCA\Files_Sharing\Tests\Controller; namespace OCA\Files_Sharing\Tests\Controller;
use OC\ContactsManager;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\Contacts;
use OCP\Files\Folder; use OCP\Files\Folder;
use OCP\IL10N; use OCP\IL10N;
use OCA\Files_Sharing\Controller\ShareAPIController; use OCA\Files_Sharing\Controller\ShareAPIController;

View File

@ -771,28 +771,44 @@ class ShareesAPIControllerTest extends TestCase {
$this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor')); $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
} }
/**
* @dataProvider dataGetRemote
*
* @param string $searchTerm
* @param array $contacts
* @param bool $shareeEnumeration
* @param array $expected
* @param bool $reachedEnd
*/
public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $expected, $reachedEnd) {
$this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$this->contactsManager->expects($this->any())
->method('search')
->with($searchTerm, ['CLOUD', 'FN'])
->willReturn($contacts);
$result = $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]);
$this->assertEquals($expected, $result);
$this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
}
public function dataGetRemote() { public function dataGetRemote() {
return [ return [
['test', [], true, [], [], true], ['test', [], true, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
['test', [], false, [], [], true], ['test', [], false, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
[ [
'test@remote', 'test@remote',
[], [],
true, true,
[ ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
[],
true, true,
], ],
[ [
'test@remote', 'test@remote',
[], [],
false, false,
[ ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
[],
true, true,
], ],
[ [
@ -814,10 +830,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
true, true,
[], ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => [], 'exactIdMatch' => false],
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']],
],
true, true,
], ],
[ [
@ -839,8 +852,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
false, false,
[], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
[],
true, true,
], ],
[ [
@ -862,12 +874,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
true, true,
[ ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']],
],
true, true,
], ],
[ [
@ -889,10 +896,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
[],
true, true,
], ],
[ [
@ -914,10 +918,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
true, true,
[ ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']],
],
[],
true, true,
], ],
[ [
@ -939,10 +940,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']],
],
[],
true, true,
], ],
// contact with space // contact with space
@ -965,10 +963,7 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
['label' => 'User Name @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']],
],
[],
true, true,
], ],
// remote with space, no contact // remote with space, no contact
@ -991,62 +986,57 @@ class ShareesAPIControllerTest extends TestCase {
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'user space@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user space@remote']]], 'exactIdMatch' => false],
['label' => 'user space@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user space@remote']],
],
[],
true, true,
], ],
]; ];
} }
/** /**
* @dataProvider dataGetRemote * @dataProvider dataGetEmail
* *
* @param string $searchTerm * @param string $searchTerm
* @param array $contacts * @param array $contacts
* @param bool $shareeEnumeration * @param bool $shareeEnumeration
* @param array $exactExpected
* @param array $expected * @param array $expected
* @param bool $reachedEnd * @param bool $reachedEnd
*/ */
public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) { public function testGetEmail($searchTerm, $contacts, $shareeEnumeration, $expected, $reachedEnd) {
$this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$this->contactsManager->expects($this->any()) $this->contactsManager->expects($this->any())
->method('search') ->method('search')
->with($searchTerm, ['CLOUD', 'FN']) ->with($searchTerm, ['EMAIL', 'FN'])
->willReturn($contacts); ->willReturn($contacts);
$this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]); $result = $this->invokePrivate($this->sharees, 'getEmail', [$searchTerm]);
$result = $this->invokePrivate($this->sharees, 'result');
$this->assertEquals($exactExpected, $result['exact']['remotes']); $this->assertEquals($expected, $result);
$this->assertEquals($expected, $result['remotes']);
$this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor')); $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
} }
public function dataGetEmails() { public function dataGetEmail() {
return [ return [
['test', [], true, [], [], true], ['test', [], true, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
['test', [], false, [], [], true], ['test', [], false, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
[ [
'test@remote.com', 'test@remote.com',
[], [],
true, true,
[ ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']], true,
], ],
[ // no valid email address
'test@remote',
[], [],
true, true,
['results' => [], 'exact' => [], 'exactIdMatch' => false],
true,
], ],
[ [
'test@remote.com', 'test@remote.com',
[], [],
false, false,
[ ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']],
],
[],
true, true,
], ],
[ [
@ -1063,15 +1053,12 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
true, true,
[], ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => [], 'exactIdMatch' => false],
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost.com']],
],
true, true,
], ],
[ [
@ -1088,13 +1075,12 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
false, false,
[], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
[],
true, true,
], ],
[ [
@ -1111,17 +1097,12 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
true, true,
[ ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']],
],
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost.com']],
],
true, true,
], ],
[ [
@ -1138,19 +1119,16 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']],
],
[],
true, true,
], ],
[ [
'username@localhost.com', 'username@localhost',
[ [
[ [
'FN' => 'User3 @ Localhost', 'FN' => 'User3 @ Localhost',
@ -1163,19 +1141,16 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
true, true,
[ ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exactIdMatch' => true],
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost.com']],
],
[],
true, true,
], ],
[ [
'username@localhost.com', 'username@localhost',
[ [
[ [
'FN' => 'User3 @ Localhost', 'FN' => 'User3 @ Localhost',
@ -1188,20 +1163,40 @@ class ShareesAPIControllerTest extends TestCase {
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => [ 'EMAIL' => [
'username@localhost.com', 'username@localhost',
], ],
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exactIdMatch' => true],
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost.com']],
],
[],
true, true,
], ],
// Test single email // contact with space
[ [
'username@localhost.com', 'user name@localhost',
[
[
'FN' => 'User3 @ Localhost',
],
[
'FN' => 'User2 @ Localhost',
'EMAIL' => [
],
],
[
'FN' => 'User Name @ Localhost',
'EMAIL' => [
'user name@localhost',
],
],
],
false,
['results' => [], 'exact' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'user name@localhost']]], 'exactIdMatch' => true],
true,
],
// remote with space, no contact
[
'user space@remote.com',
[ [
[ [
'FN' => 'User3 @ Localhost', 'FN' => 'User3 @ Localhost',
@ -1213,137 +1208,106 @@ class ShareesAPIControllerTest extends TestCase {
], ],
[ [
'FN' => 'User @ Localhost', 'FN' => 'User @ Localhost',
'EMAIL' => 'username@localhost.com', 'EMAIL' => [
'username@localhost',
],
], ],
], ],
false, false,
[ ['results' => [], 'exact' => [], 'exactIdMatch' => false],
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost.com']],
],
[],
true, true,
], ],
]; ];
} }
/**
* @dataProvider dataGetEmails
*
* @param string $searchTerm
* @param array $contacts
* @param bool $shareeEnumeration
* @param array $exactExpected
* @param array $expected
* @param bool $reachedEnd
*/
public function testGetEmails($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) {
$this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$this->contactsManager->expects($this->any())
->method('search')
->with($searchTerm, ['FN', 'EMAIL'])
->willReturn($contacts);
$this->invokePrivate($this->sharees, 'getEmails', [$searchTerm]);
$result = $this->invokePrivate($this->sharees, 'result');
$this->assertEquals($exactExpected, $result['exact']['emails']);
$this->assertEquals($expected, $result['emails']);
$this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
}
public function dataSearch() { public function dataSearch() {
$allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_EMAIL, Share::SHARE_TYPE_REMOTE]; $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE, Share::SHARE_TYPE_EMAIL];
return [ return [
[[], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], [[], '', 'yes', true, true, $allTypes, false, true, true],
// Test itemType // Test itemType
[[ [[
'search' => '', 'search' => '',
], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'search' => 'foobar', 'search' => 'foobar',
], '', 'yes', true, 'foobar', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'search' => 0, 'search' => 0,
], '', 'yes', true, '0', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
// Test itemType // Test itemType
[[ [[
'itemType' => '', 'itemType' => '',
], '', 'yes', true, '', '', $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'itemType' => 'folder', 'itemType' => 'folder',
], '', 'yes', true, '', 'folder', $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'itemType' => 0, 'itemType' => 0,
], '', 'yes', true, '', '0', $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
// Test shareType // Test shareType
[[ [[
], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'shareType' => 0, 'shareType' => 0,
], '', 'yes', true, '', null, [0], 1, 200, false, true, true], ], '', 'yes', true, false, [0], false, true, true],
[[ [[
'shareType' => '0', 'shareType' => '0',
], '', 'yes', true, '', null, [0], 1, 200, false, true, true], ], '', 'yes', true, false, [0], false, true, true],
[[ [[
'shareType' => 1, 'shareType' => 1,
], '', 'yes', true, '', null, [1], 1, 200, false, true, true], ], '', 'yes', true, false, [1], false, true, true],
[[ [[
'shareType' => 12, 'shareType' => 12,
], '', 'yes', true, '', null, [], 1, 200, false, true, true], ], '', 'yes', true, false, [], false, true, true],
[[ [[
'shareType' => 'foobar', 'shareType' => 'foobar',
], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'shareType' => [0, 1, 2], 'shareType' => [0, 1, 2],
], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], ], '', 'yes', false, false, [0, 1], false, true, true],
[[ [[
'shareType' => [0, 1], 'shareType' => [0, 1],
], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], ], '', 'yes', false, false, [0, 1], false, true, true],
[[ [[
'shareType' => $allTypes, 'shareType' => $allTypes,
], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'shareType' => $allTypes, 'shareType' => $allTypes,
], '', 'yes', false, '', null, [0, 1, 4], 1, 200, false, true, true], ], '', 'yes', false, false, [0, 1], false, true, true],
[[ [[
'shareType' => $allTypes, 'shareType' => $allTypes,
], '', 'yes', true, '', null, [0, 4, 6], 1, 200, false, true, false], ], '', 'yes', true, false, [0, 6], false, true, false],
[[ [[
'shareType' => $allTypes, 'shareType' => $allTypes,
], '', 'yes', false, '', null, [0, 4], 1, 200, false, true, false], ], '', 'yes', false, true, [0, 4], false, true, false],
// Test pagination // Test pagination
[[ [[
'page' => 1, 'page' => 1,
], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'page' => 10, 'page' => 10,
], '', 'yes', true, '', null, $allTypes, 10, 200, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
// Test perPage // Test perPage
[[ [[
'perPage' => 1, 'perPage' => 1,
], '', 'yes', true, '', null, $allTypes, 1, 1, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
[[ [[
'perPage' => 10, 'perPage' => 10,
], '', 'yes', true, '', null, $allTypes, 1, 10, false, true, true], ], '', 'yes', true, true, $allTypes, false, true, true],
// Test $shareWithGroupOnly setting // Test $shareWithGroupOnly setting
[[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], [[], 'no', 'yes', true, true, $allTypes, false, true, true],
[[], 'yes', 'yes', true, '', null, $allTypes, 1, 200, true, true, true], [[], 'yes', 'yes', true, true, $allTypes, true, true, true],
// Test $shareeEnumeration setting // Test $shareeEnumeration setting
[[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], [[], 'no', 'yes', true, true, $allTypes, false, true, true],
[[], 'no', 'no', true, '', null, $allTypes, 1, 200, false, false, true], [[], 'no', 'no', true, true, $allTypes, false, false, true],
// Test keep case for search
[[
'search' => 'foo@example.com/ownCloud',
], '', 'yes', true, 'foo@example.com/ownCloud', null, $allTypes, 1, 200, false, true, true],
]; ];
} }
@ -1354,16 +1318,12 @@ class ShareesAPIControllerTest extends TestCase {
* @param string $apiSetting * @param string $apiSetting
* @param string $enumSetting * @param string $enumSetting
* @param bool $remoteSharingEnabled * @param bool $remoteSharingEnabled
* @param string $search
* @param string $itemType
* @param array $shareTypes * @param array $shareTypes
* @param int $page
* @param int $perPage
* @param bool $shareWithGroupOnly * @param bool $shareWithGroupOnly
* @param bool $shareeEnumeration * @param bool $shareeEnumeration
* @param bool $allowGroupSharing * @param bool $allowGroupSharing
*/ */
public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) { public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $emailSharingEnabled, $shareTypes, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) {
$search = isset($getData['search']) ? $getData['search'] : ''; $search = isset($getData['search']) ? $getData['search'] : '';
$itemType = isset($getData['itemType']) ? $getData['itemType'] : null; $itemType = isset($getData['itemType']) ? $getData['itemType'] : null;
$page = isset($getData['page']) ? $getData['page'] : 1; $page = isset($getData['page']) ? $getData['page'] : 1;
@ -1399,11 +1359,10 @@ class ShareesAPIControllerTest extends TestCase {
$this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
$this->shareManager $this->shareManager
]) ])
->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) ->setMethods(array('searchSharees', 'isRemoteSharingAllowed', 'shareProviderExists'))
->getMock(); ->getMock();
$sharees->expects($this->once()) $sharees->expects($this->once())
->method('searchSharees') ->method('searchSharees')
->with($search, $itemType, $shareTypes, $page, $perPage)
->willReturnCallback(function ->willReturnCallback(function
($isearch, $iitemType, $ishareTypes, $ipage, $iperPage) ($isearch, $iitemType, $ishareTypes, $ipage, $iperPage)
use ($search, $itemType, $shareTypes, $page, $perPage) { use ($search, $itemType, $shareTypes, $page, $perPage) {
@ -1411,7 +1370,10 @@ class ShareesAPIControllerTest extends TestCase {
// We are doing strict comparisons here, so we can differ 0/'' and null on shareType/itemType // We are doing strict comparisons here, so we can differ 0/'' and null on shareType/itemType
$this->assertSame($search, $isearch); $this->assertSame($search, $isearch);
$this->assertSame($itemType, $iitemType); $this->assertSame($itemType, $iitemType);
$this->assertSame($shareTypes, $ishareTypes); $this->assertSame(count($shareTypes), count($ishareTypes));
foreach($shareTypes as $expected) {
$this->assertTrue(in_array($expected, $ishareTypes));
}
$this->assertSame($page, $ipage); $this->assertSame($page, $ipage);
$this->assertSame($perPage, $iperPage); $this->assertSame($perPage, $iperPage);
return new Http\DataResponse(); return new Http\DataResponse();
@ -1421,6 +1383,11 @@ class ShareesAPIControllerTest extends TestCase {
->with($itemType) ->with($itemType)
->willReturn($remoteSharingEnabled); ->willReturn($remoteSharingEnabled);
$this->shareManager->expects($this->any())
->method('shareProviderExists')
->with(\OCP\Share::SHARE_TYPE_EMAIL)
->willReturn($emailSharingEnabled);
$this->assertInstanceOf(Http\DataResponse::class, $sharees->search($search, $itemType, $page, $perPage, $shareType)); $this->assertInstanceOf(Http\DataResponse::class, $sharees->search($search, $itemType, $page, $perPage, $shareType));
$this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly')); $this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly'));
@ -1519,7 +1486,7 @@ class ShareesAPIControllerTest extends TestCase {
public function dataSearchSharees() { public function dataSearchSharees() {
return [ return [
['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [], ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
[ [
'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []], 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []],
'users' => [], 'users' => [],
@ -1527,7 +1494,7 @@ class ShareesAPIControllerTest extends TestCase {
'remotes' => [], 'remotes' => [],
'emails' => [], 'emails' => [],
], false], ], false],
['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [], ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
[ [
'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []], 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []],
'users' => [], 'users' => [],
@ -1541,7 +1508,7 @@ class ShareesAPIControllerTest extends TestCase {
], [ ], [
['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']], ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
], [ ], [
['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false,
], ],
[ [
'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []], 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []],
@ -1562,7 +1529,7 @@ class ShareesAPIControllerTest extends TestCase {
'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [ 'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [
['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
], null, [ ], null, [
['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false
], ],
[ [
'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []], 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'emails' => []],
@ -1660,14 +1627,11 @@ class ShareesAPIControllerTest extends TestCase {
$result['groups'] = $mockedGroupsResult; $result['groups'] = $mockedGroupsResult;
$this->invokePrivate($sharees, 'result', [$result]); $this->invokePrivate($sharees, 'result', [$result]);
}); });
$sharees->expects(($mockedRemotesResult === null) ? $this->never() : $this->once()) $sharees->expects(($mockedRemotesResult === null) ? $this->never() : $this->once())
->method('getRemote') ->method('getRemote')
->with($searchTerm) ->with($searchTerm)
->willReturnCallback(function() use ($sharees, $mockedRemotesResult) { ->willReturn($mockedRemotesResult);
$result = $this->invokePrivate($sharees, 'result');
$result['remotes'] = $mockedRemotesResult;
$this->invokePrivate($sharees, 'result', [$result]);
});
$ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]); $ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]);
$this->assertInstanceOf('\OCP\AppFramework\Http\DataResponse', $ocs); $this->assertInstanceOf('\OCP\AppFramework\Http\DataResponse', $ocs);

View File

@ -0,0 +1,24 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
$settings = new \OCA\ShareByMail\Settings();
\OCP\Util::connectHook('\OCP\Config', 'js', $settings, 'announceShareProvider');

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<info>
<id>sharebymail</id>
<name>Share by mail</name>
<description>Share provider which allows you to share files by mail</description>
<licence>AGPL</licence>
<author>Bjoern Schiessle</author>
<version>1.0.0</version>
<namespace>ShareByMail</namespace>
<category>other</category>
<dependencies>
<owncloud min-version="9.2" max-version="9.2" />
</dependencies>
<default_enable/>
</info>

View File

@ -0,0 +1,38 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ShareByMail;
class Settings {
/**
* announce that the share-by-mail share provider is enabled
*
* @param array $settings
*/
public function announceShareProvider(array $settings) {
$array = json_decode($settings['array']['oc_appconfig'], true);
$array['shareByMailEnabled'] = true;
$settings['array']['oc_appconfig'] = json_encode($array);
}
}

View File

@ -0,0 +1,709 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ShareByMail;
use OC\HintException;
use OC\Share20\Exception\InvalidShare;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IDBConnection;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Mail\IMailer;
use OCP\Security\ISecureRandom;
use OC\Share20\Share;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
/**
* Class ShareByMail
*
* @package OCA\ShareByMail
*/
class ShareByMailProvider implements IShareProvider {
/** @var IDBConnection */
private $dbConnection;
/** @var ILogger */
private $logger;
/** @var ISecureRandom */
private $secureRandom;
/** @var IUserManager */
private $userManager;
/** @var IRootFolder */
private $rootFolder;
/** @var IL10N */
private $l;
/** @var IMailer */
private $mailer;
/** @var IURLGenerator */
private $urlGenerator;
/**
* Return the identifier of this provider.
*
* @return string Containing only [a-zA-Z0-9]
*/
public function identifier() {
return 'ocShareByMail';
}
/**
* DefaultShareProvider constructor.
*
* @param IDBConnection $connection
* @param ISecureRandom $secureRandom
* @param IUserManager $userManager
* @param IRootFolder $rootFolder
* @param IL10N $l
* @param ILogger $logger
* @param IMailer $mailer
* @param IURLGenerator $urlGenerator
*/
public function __construct(
IDBConnection $connection,
ISecureRandom $secureRandom,
IUserManager $userManager,
IRootFolder $rootFolder,
IL10N $l,
ILogger $logger,
IMailer $mailer,
IURLGenerator $urlGenerator
) {
$this->dbConnection = $connection;
$this->secureRandom = $secureRandom;
$this->userManager = $userManager;
$this->rootFolder = $rootFolder;
$this->l = $l;
$this->logger = $logger;
$this->mailer = $mailer;
$this->urlGenerator = $urlGenerator;
}
/**
* Share a path
*
* @param IShare $share
* @return IShare The share object
* @throws ShareNotFound
* @throws \Exception
*/
public function create(IShare $share) {
$shareWith = $share->getSharedWith();
/*
* Check if file is not already shared with the remote user
*/
$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
if (!empty($alreadyShared)) {
$message = 'Sharing %s failed, this item is already shared with %s';
$message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
throw new \Exception($message_t);
}
$shareId = $this->createMailShare($share);
$data = $this->getRawShare($shareId);
return $this->createShareObject($data);
}
/**
* @param IShare $share
* @return int
* @throws \Exception
*/
protected function createMailShare(IShare $share) {
$share->setToken($this->generateToken());
$shareId = $this->addShareToDB(
$share->getNodeId(),
$share->getNodeType(),
$share->getSharedWith(),
$share->getSharedBy(),
$share->getShareOwner(),
$share->getPermissions(),
$share->getToken()
);
try {
$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
['token' => $share->getToken()]);
$this->sendMailNotification($share->getNode()->getName(),
$link,
$share->getShareOwner(),
$share->getSharedBy(), $share->getSharedWith());
} catch (HintException $hintException) {
$this->logger->error('Failed to send share by mail: ' . $hintException->getMessage());
$this->removeShareFromTable($shareId);
throw $hintException;
} catch (\Exception $e) {
$this->logger->error('Failed to send share by mail: ' . $e->getMessage());
$this->removeShareFromTable($shareId);
throw new HintException('Failed to send share by mail',
$this->l->t('Failed to send share by E-mail'));
}
return $shareId;
}
protected function sendMailNotification($filename, $link, $owner, $initiator, $shareWith) {
if ($owner === $initiator) {
$subject = (string)$this->l->t('%s shared »%s« with you', array($owner, $filename));
} else {
$subject = (string)$this->l->t('%s shared »%s« with you on behalf of %s', array($owner, $filename, $initiator));
}
$message = $this->mailer->createMessage();
$htmlBody = $this->createMailBody('mail', $filename, $link, $owner, $initiator);
$textBody = $this->createMailBody('altmail', $filename, $link, $owner, $initiator);
$message->setTo([$shareWith]);
$message->setSubject($subject);
$message->setBody($textBody, 'text/plain');
$message->setHtmlBody($htmlBody);
$this->mailer->send($message);
}
/**
* create mail body
*
* @param $filename
* @param $link
* @param $owner
* @param $initiator
* @return string plain text mail
* @throws HintException
*/
protected function createMailBody($template, $filename, $link, $owner, $initiator) {
$mailBodyTemplate = new \OC_Template('sharebymail', $template, '');
$mailBodyTemplate->assign ('filename', $filename);
$mailBodyTemplate->assign ('link', $link);
$mailBodyTemplate->assign ('owner', $owner);
$mailBodyTemplate->assign ('initiator', $initiator);
$mailBodyTemplate->assign ('onBehalfOf', $initiator !== $owner);
$mailBody = $mailBodyTemplate->fetchPage();
if (is_string($mailBody)) {
return $mailBody;
}
throw new HintException('Failed to create the E-mail',
$this->l->t('Failed to create the E-mail'));
}
/**
* generate share token
*
* @return string
*/
protected function generateToken() {
$token = $this->secureRandom->generate(
15, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
return $token;
}
/**
* Get all children of this share
*
* @param IShare $parent
* @return IShare[]
*/
public function getChildren(IShare $parent) {
$children = [];
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
->orderBy('id');
$cursor = $qb->execute();
while($data = $cursor->fetch()) {
$children[] = $this->createShareObject($data);
}
$cursor->closeCursor();
return $children;
}
/**
* add share to the database and return the ID
*
* @param int $itemSource
* @param string $itemType
* @param string $shareWith
* @param string $sharedBy
* @param string $uidOwner
* @param int $permissions
* @param string $token
* @return int
*/
protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert('share')
->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
->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('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;
}
/**
* Update a share
*
* @param IShare $share
* @return IShare The share object
*/
public function update(IShare $share) {
/*
* We allow updating the permissions of mail shares
*/
$qb = $this->dbConnection->getQueryBuilder();
$qb->update('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->execute();
return $share;
}
/**
* @inheritdoc
*/
public function move(IShare $share, $recipient) {
/**
* nothing to do here, mail shares are only outgoing shares
*/
return $share;
}
/**
* Delete a share (owner unShares the file)
*
* @param IShare $share
*/
public function delete(IShare $share) {
$this->removeShareFromTable($share->getId());
}
/**
* @inheritdoc
*/
public function deleteFromSelf(IShare $share, $recipient) {
// nothing to do here, mail shares are only outgoing shares
return;
}
/**
* @inheritdoc
*/
public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share');
$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
/**
* Reshares for this user are shares where they are the owner.
*/
if ($reshares === false) {
//Special case for old shares created via the web UI
$or1 = $qb->expr()->andX(
$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
$qb->expr()->isNull('uid_initiator')
);
$qb->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
$or1
)
);
} else {
$qb->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
)
);
}
if ($node !== null) {
$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
}
if ($limit !== -1) {
$qb->setMaxResults($limit);
}
$qb->setFirstResult($offset);
$qb->orderBy('id');
$cursor = $qb->execute();
$shares = [];
while($data = $cursor->fetch()) {
$shares[] = $this->createShareObject($data);
}
$cursor->closeCursor();
return $shares;
}
/**
* @inheritdoc
*/
public function getShareById($id, $recipientId = null) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ShareNotFound();
}
try {
$share = $this->createShareObject($data);
} catch (InvalidShare $e) {
throw new ShareNotFound();
}
return $share;
}
/**
* Get shares for a given path
*
* @param \OCP\Files\Node $path
* @return IShare[]
*/
public function getSharesByPath(Node $path) {
$qb = $this->dbConnection->getQueryBuilder();
$cursor = $qb->select('*')
->from('share')
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
->execute();
$shares = [];
while($data = $cursor->fetch()) {
$shares[] = $this->createShareObject($data);
}
$cursor->closeCursor();
return $shares;
}
/**
* @inheritdoc
*/
public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
/** @var IShare[] $shares */
$shares = [];
//Get shares directly with this user
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share');
// Order by id
$qb->orderBy('id');
// Set limit and offset
if ($limit !== -1) {
$qb->setMaxResults($limit);
}
$qb->setFirstResult($offset);
$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
// Filter by node if provided
if ($node !== null) {
$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
}
$cursor = $qb->execute();
while($data = $cursor->fetch()) {
$shares[] = $this->createShareObject($data);
}
$cursor->closeCursor();
return $shares;
}
/**
* Get a share by token
*
* @param string $token
* @return IShare
* @throws ShareNotFound
*/
public function getShareByToken($token) {
$qb = $this->dbConnection->getQueryBuilder();
$cursor = $qb->select('*')
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
->execute();
$data = $cursor->fetch();
if ($data === false) {
throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
}
try {
$share = $this->createShareObject($data);
} catch (InvalidShare $e) {
throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
}
return $share;
}
/**
* remove share from table
*
* @param string $shareId
*/
protected function removeShareFromTable($shareId) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
$qb->execute();
}
/**
* Create a share object from an database row
*
* @param array $data
* @return IShare
* @throws InvalidShare
* @throws ShareNotFound
*/
protected function createShareObject($data) {
$share = new Share($this->rootFolder, $this->userManager);
$share->setId((int)$data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])
->setMailSend((bool)$data['mail_send'])
->setToken($data['token']);
$shareTime = new \DateTime();
$shareTime->setTimestamp((int)$data['stime']);
$share->setShareTime($shareTime);
$share->setSharedWith($data['share_with']);
if ($data['uid_initiator'] !== null) {
$share->setShareOwner($data['uid_owner']);
$share->setSharedBy($data['uid_initiator']);
} else {
//OLD SHARE
$share->setSharedBy($data['uid_owner']);
$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
$owner = $path->getOwner();
$share->setShareOwner($owner->getUID());
}
$share->setNodeId((int)$data['file_source']);
$share->setNodeType($data['item_type']);
$share->setProviderId($this->identifier());
return $share;
}
/**
* Get the node with file $id for $user
*
* @param string $userId
* @param int $id
* @return \OCP\Files\File|\OCP\Files\Folder
* @throws InvalidShare
*/
private function getNode($userId, $id) {
try {
$userFolder = $this->rootFolder->getUserFolder($userId);
} catch (NotFoundException $e) {
throw new InvalidShare();
}
$nodes = $userFolder->getById($id);
if (empty($nodes)) {
throw new InvalidShare();
}
return $nodes[0];
}
/**
* A user is deleted from the system
* So clean up the relevant shares.
*
* @param string $uid
* @param int $shareType
*/
public function userDeleted($uid, $shareType) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
->execute();
}
/**
* This provider does not support group shares
*
* @param string $gid
*/
public function groupDeleted($gid) {
return;
}
/**
* This provider does not support group shares
*
* @param string $uid
* @param string $gid
*/
public function userDeletedFromGroup($uid, $gid) {
return;
}
/**
* get database row of a give share
*
* @param $id
* @return array
* @throws ShareNotFound
*/
protected function getRawShare($id) {
// Now fetch the inserted share and create a complete share object
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ShareNotFound;
}
return $data;
}
public function getSharesInFolder($userId, Folder $node, $reshares) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->select('*')
->from('share', 's')
->andWhere($qb->expr()->orX(
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
))
->andWhere(
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
);
/**
* Reshares for this user are shares where they are the owner.
*/
if ($reshares === false) {
$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
} else {
$qb->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
)
);
}
$qb->innerJoin('s', 'filecache' ,'f', 's.file_source = f.fileid');
$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
$qb->orderBy('id');
$cursor = $qb->execute();
$shares = [];
while ($data = $cursor->fetch()) {
$shares[$data['fileid']][] = $this->createShareObject($data);
}
$cursor->closeCursor();
return $shares;
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/** @var OC_Theme $theme */
/** @var array $_ */
if ($_['onBehalfOf']) {
print_unescaped($l->t("Hey there,\n\n%s shared »%s« with you on behalf of %s.\n\n%s\n\n", [$_['owner'], $_['filename'], $_['initiator'], $_['link']]));
} else {
print_unescaped($l->t("Hey there,\n\n%s shared »%s« with you.\n\n%s\n\n", [$_['owner'], $_['filename'], $_['link']]));
}
// TRANSLATORS term at the end of a mail
p($l->t("Cheers!"));
print_unescaped("\n");
?>
--
<?php p($theme->getName() . ' - ' . $theme->getSlogan()); ?>
<?php print_unescaped("\n".$theme->getBaseUrl());

View File

@ -0,0 +1,64 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/** @var OC_Theme $theme */
/** @var array $_ */
?>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr><td>
<table cellspacing="0" cellpadding="0" border="0" width="600px">
<tr>
<td bgcolor="<?php p($theme->getMailHeaderColor());?>" width="20px">&nbsp;</td>
<td bgcolor="<?php p($theme->getMailHeaderColor());?>">
<img src="<?php p(\OC::$server->getURLGenerator()->getAbsoluteURL(image_path('', 'logo-mail.gif'))); ?>" alt="<?php p($theme->getName()); ?>"/>
</td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr>
<td width="20px">&nbsp;</td>
<td style="font-weight:normal; font-size:0.8em; line-height:1.2em; font-family:verdana,'arial',sans;">
<?php
if ($_['onBehalfOf']) {
print_unescaped($l->t('Hey there,<br><br>%s shared <a href="%s">%s</a> with you on behalf of %s.<br><br>', [$_['owner'], $_['link'], $_['filename'], $_['initiator']]));
} else {
print_unescaped($l->t('Hey there,<br><br>%s shared <a href="%s">%s</a> with you.<br><br>', [$_['owner'], $_['link'], $_['filename']]));
}
// TRANSLATORS term at the end of a mail
p($l->t('Cheers!'));
?>
</td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr>
<td width="20px">&nbsp;</td>
<td style="font-weight:normal; font-size:0.8em; line-height:1.2em; font-family:verdana,'arial',sans;">--<br>
<?php p($theme->getName()); ?> -
<?php p($theme->getSlogan()); ?>
<br><a href="<?php p($theme->getBaseUrl()); ?>"><?php p($theme->getBaseUrl());?></a>
</td>
</tr>
<tr>
<td colspan="2">&nbsp;</td>
</tr>
</table>
</td></tr>
</table>

View File

@ -0,0 +1,64 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ShareByMail\Tests;
use OCA\ShareByMail\Settings;
use Test\TestCase;
class SettingsTest extends TestCase {
/** @var Settings */
private $instance;
public function setUp() {
parent::setUp();
$this->instance = new Settings();
}
public function testAnnounceShareProvider() {
$before = [
'oc_appconfig' =>
json_encode([
'key1' => 'value1',
'key2' => 'value2'
]),
'oc_foo' => 'oc_bar'
];
$after = [
'oc_appconfig' =>
json_encode([
'key1' => 'value1',
'key2' => 'value2',
'shareByMailEnabled' => true
]),
'oc_foo' => 'oc_bar'
];
$this->instance->announceShareProvider(['array' => &$before]);
$this->assertSame($after, $before);
}
}

View File

@ -0,0 +1,655 @@
<?php
/**
* @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\ShareByMail\Tests;
use OC\HintException;
use OCA\ShareByMail\ShareByMailProvider;
use OCP\Files\IRootFolder;
use OCP\IDBConnection;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Mail\IMailer;
use OCP\Security\ISecureRandom;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Test\TestCase;
/**
* Class ShareByMailProviderTest
*
* @package OCA\ShareByMail\Tests
* @group DB
*/
class ShareByMailProviderTest extends TestCase {
/** @var IDBConnection */
private $connection;
/** @var IManager */
private $shareManager;
/** @var IL10N | \PHPUnit_Framework_MockObject_MockObject */
private $l;
/** @var ILogger | \PHPUnit_Framework_MockObject_MockObject */
private $logger;
/** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */
private $rootFolder;
/** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
private $userManager;
/** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject */
private $secureRandom;
/** @var IMailer | \PHPUnit_Framework_MockObject_MockObject */
private $mailer;
/** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
/** @var IShare | \PHPUnit_Framework_MockObject_MockObject */
private $share;
public function setUp() {
parent::setUp();
$this->shareManager = \OC::$server->getShareManager();
$this->connection = \OC::$server->getDatabaseConnection();
$this->l = $this->getMockBuilder('OCP\IL10N')->getMock();
$this->l->method('t')
->will($this->returnCallback(function($text, $parameters = []) {
return vsprintf($text, $parameters);
}));
$this->logger = $this->getMockBuilder('OCP\ILogger')->getMock();
$this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')->getMock();
$this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock();
$this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock();
$this->mailer = $this->getMockBuilder('\OCP\Mail\IMailer')->getMock();
$this->urlGenerator = $this->getMockBuilder('\OCP\IUrlGenerator')->getMock();
$this->share = $this->getMockBuilder('\OCP\Share\IShare')->getMock();
$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
}
/**
* 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 = []) {
$instance = $this->getMockBuilder('OCA\ShareByMail\ShareByMailProvider')
->setConstructorArgs(
[
$this->connection,
$this->secureRandom,
$this->userManager,
$this->rootFolder,
$this->l,
$this->logger,
$this->mailer,
$this->urlGenerator
]
);
if (!empty($mockedMethods)) {
$instance->setMethods($mockedMethods);
return $instance->getMock();
}
return new ShareByMailProvider(
$this->connection,
$this->secureRandom,
$this->userManager,
$this->rootFolder,
$this->l,
$this->logger,
$this->mailer,
$this->urlGenerator
);
}
public function tearDown() {
$this->connection->getQueryBuilder()->delete('share')->execute();
return parent::tearDown();
}
public function testCreate() {
$share = $this->getMockBuilder('\OCP\Share\IShare')->getMock();
$share->expects($this->once())->method('getSharedWith')->willReturn('user1');
$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('getRawShare')->with(42)->willReturn('rawShare');
$instance->expects($this->once())->method('createShareObject')->with('rawShare')->willReturn('shareObject');
$this->assertSame('shareObject',
$instance->create($share)
);
}
/**
* @expectedException \Exception
*/
public function testCreateFailed() {
$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() {
$this->share->expects($this->any())->method('getToken')->willReturn('token');
$this->share->expects($this->once())->method('setToken')->with('token');
$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);
$instance->expects($this->once())->method('sendMailNotification');
$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
->with('files_sharing.sharecontroller.showShare', ['token' => 'token']);
$instance->expects($this->once())->method('sendMailNotification');
$this->assertSame(42,
$this->invokePrivate($instance, 'createMailShare', [$this->share])
);
}
/**
* @expectedException \OC\HintException
*/
public function testCreateMailShareFailed() {
$this->share->expects($this->any())->method('getToken')->willReturn('token');
$this->share->expects($this->once())->method('setToken')->with('token');
$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);
$instance->expects($this->once())->method('sendMailNotification');
$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
->with('files_sharing.sharecontroller.showShare', ['token' => 'token']);
$instance->expects($this->once())->method('sendMailNotification')
->willReturnCallback(
function() {
throw new \Exception('should be converted to a hint exception');
}
);
$this->assertSame(42,
$this->invokePrivate($instance, 'createMailShare', [$this->share])
);
}
public function testGenerateToken() {
$instance = $this->getInstance();
$this->secureRandom->expects($this->once())->method('generate')->willReturn('token');
$this->assertSame('token',
$this->invokePrivate($instance, 'generateToken')
);
}
public function testAddShareToDB() {
$itemSource = 11;
$itemType = 'file';
$shareWith = 'user@server.com';
$sharedBy = 'user1';
$uidOwner = 'user2';
$permissions = 1;
$token = 'token';
$instance = $this->getInstance();
$id = $this->invokePrivate(
$instance,
'addShareToDB',
[
$itemSource,
$itemType,
$shareWith,
$sharedBy,
$uidOwner,
$permissions,
$token
]
);
$qb = $this->connection->getQueryBuilder();
$result = $qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->execute()->fetchAll();
$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']);
}
public function testUpdate() {
$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->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->once())->method('getId')->willReturn($id);
$this->assertSame($this->share,
$instance->update($this->share)
);
$qb = $this->connection->getQueryBuilder();
$result = $qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->execute()->fetchAll();
$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']);
}
public function testDelete() {
$instance = $this->getInstance(['removeShareFromTable']);
$this->share->expects($this->once())->method('getId')->willReturn(42);
$instance->expects($this->once())->method('removeShareFromTable')->with(42);
$instance->delete($this->share);
}
public function testGetShareById() {
$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);
}
/**
* @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testGetShareByIdFailed() {
$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() {
$itemSource = 11;
$itemType = 'file';
$shareWith = 'user@server.com';
$sharedBy = 'user1';
$uidOwner = 'user2';
$permissions = 1;
$token = 'token';
$node = $this->getMockBuilder('OCP\Files\Node')->getMock();
$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() {
$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, \OCP\Share::SHARE_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;
}
);
$this->assertInstanceOf('OCP\Share\IShare',
$instance->getShareByToken('token')
);
}
/**
* @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testGetShareByTokenFailed() {
$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", \OCP\Share::SHARE_TYPE_LINK);
$this->assertTrue($idMail !== $idPublic);
$this->assertInstanceOf('OCP\Share\IShare',
$instance->getShareByToken('token2')
);
}
public function testRemoveShareFromTable() {
$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)));
$before = $query->execute()->fetchAll();
$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)));
$after = $query->execute()->fetchAll();
$this->assertTrue(is_array($after));
$this->assertEmpty($after);
}
public function testUserDeleted() {
$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');
$before = $query->execute()->fetchAll();
$this->assertTrue(is_array($before));
$this->assertSame(2, count($before));
$instance = $this->getInstance();
$instance->userDeleted($uidOwner, \OCP\Share::SHARE_TYPE_EMAIL);
$query = $this->connection->getQueryBuilder();
$query->select('*')->from('share');
$after = $query->execute()->fetchAll();
$this->assertTrue(is_array($after));
$this->assertSame(1, count($after));
$this->assertSame($id, (int)$after[0]['id']);
}
public function testGetRawShare() {
$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']);
}
/**
* @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testGetRawShareFailed() {
$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, $shareType = \OCP\Share::SHARE_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('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() {
$userManager = \OC::$server->getUserManager();
$rootFolder = \OC::$server->getRootFolder();
$provider = $this->getInstance(['sendMailNotification']);
$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(\OCP\Constants::PERMISSION_READ)
->setNode($file1);
$provider->create($share1);
$share2 = $this->shareManager->newShare();
$share2->setSharedWith('user@server.com')
->setSharedBy($u2->getUID())
->setShareOwner($u1->getUID())
->setPermissions(\OCP\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();
}
}

View File

@ -255,7 +255,7 @@ Feature: provisioning
Scenario: Delete a user Scenario: Delete a user
Given As an "admin" Given As an "admin"
And user "brand-new-user" exists And user "brand-new-user" exists
When sending "DELETE" to "/cloud/users/brand-new-user" When sending "DELETE" to "/cloud/users/brand-new-user"
Then the OCS status code should be "100" Then the OCS status code should be "100"
And the HTTP status code should be "200" And the HTTP status code should be "200"
And user "brand-new-user" does not exist And user "brand-new-user" does not exist
@ -291,6 +291,7 @@ Feature: provisioning
| files_trashbin | | files_trashbin |
| files_versions | | files_versions |
| provisioning_api | | provisioning_api |
| sharebymail |
| systemtags | | systemtags |
| theming | | theming |
| twofactor_backupcodes | | twofactor_backupcodes |

View File

@ -25,6 +25,7 @@
isDefaultExpireDateEnforced: oc_appconfig.core.defaultExpireDateEnforced === true, isDefaultExpireDateEnforced: oc_appconfig.core.defaultExpireDateEnforced === true,
isDefaultExpireDateEnabled: oc_appconfig.core.defaultExpireDateEnabled === true, isDefaultExpireDateEnabled: oc_appconfig.core.defaultExpireDateEnabled === true,
isRemoteShareAllowed: oc_appconfig.core.remoteShareAllowed, isRemoteShareAllowed: oc_appconfig.core.remoteShareAllowed,
isMailShareAllowed: oc_appconfig.shareByMailEnabled !== undefined,
defaultExpireDate: oc_appconfig.core.defaultExpireDate, defaultExpireDate: oc_appconfig.core.defaultExpireDate,
isResharingAllowed: oc_appconfig.core.resharingAllowed, isResharingAllowed: oc_appconfig.core.resharingAllowed,
allowGroupSharing: oc_appconfig.core.allowGroupSharing allowGroupSharing: oc_appconfig.core.allowGroupSharing

View File

@ -24,25 +24,28 @@
'{{#if avatarEnabled}}' + '{{#if avatarEnabled}}' +
'<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' + '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
'{{/if}}' + '{{/if}}' +
'<span class="has-tooltip username" title="{{shareWith}}">{{shareWithDisplayName}}</span>' + '<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
'<span class="sharingOptionsGroup">' + '<span class="sharingOptionsGroup">' +
'{{#if editPermissionPossible}}' + '{{#if editPermissionPossible}}' +
'{{#unless isFileSharedByMail}}' +
'<span class="shareOption">' + '<span class="shareOption">' +
'<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' + '<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
'<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' + '<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
'</span>' + '</span>' +
'{{/unless}}' +
'{{/if}}' + '{{/if}}' +
'{{#unless isMailShare}}' +
'<a href="#"><span class="icon icon-more"></span></a>' + '<a href="#"><span class="icon icon-more"></span></a>' +
'<div class="popovermenu bubble hidden menu">' + '<div class="popovermenu bubble hidden menu">' +
'<ul>' + '<ul>' +
'{{#if isResharingAllowed}} {{#if sharePermissionPossible}}' + '{{#if isResharingAllowed}} {{#if sharePermissionPossible}} {{#unless isMailShare}}' +
'<li>' + '<li>' +
'<span class="shareOption">' + '<span class="shareOption">' +
'<input id="canShare-{{cid}}-{{shareWith}}" type="checkbox" name="share" class="permissions checkbox" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />' + '<input id="canShare-{{cid}}-{{shareWith}}" type="checkbox" name="share" class="permissions checkbox" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />' +
'<label for="canShare-{{cid}}-{{shareWith}}">{{canShareLabel}}</label>' + '<label for="canShare-{{cid}}-{{shareWith}}">{{canShareLabel}}</label>' +
'</span>' + '</span>' +
'</li>' + '</li>' +
'{{/if}} {{/if}}' + '{{/unless}} {{/if}} {{/if}}' +
'{{#if isFolder}}' + '{{#if isFolder}}' +
'{{#if createPermissionPossible}}' + '{{#if createPermissionPossible}}' +
'<li>' + '<li>' +
@ -74,7 +77,9 @@
'</li>' + '</li>' +
'</ul>' + '</ul>' +
'</div>' + '</div>' +
'</span>' + '{{/unless}}' +
'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span class="hidden-visually">{{unshareLabel}}</span></a>' +
'</span>' +
'</li>' + '</li>' +
'{{/each}}' + '{{/each}}' +
'{{#each linkReshares}}' + '{{#each linkReshares}}' +
@ -141,6 +146,7 @@
getShareeObject: function(shareIndex) { getShareeObject: function(shareIndex) {
var shareWith = this.model.getShareWith(shareIndex); var shareWith = this.model.getShareWith(shareIndex);
var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex); var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex);
var shareWithTitle = '';
var shareType = this.model.getShareType(shareIndex); var shareType = this.model.getShareType(shareIndex);
var hasPermissionOverride = {}; var hasPermissionOverride = {};
@ -148,6 +154,16 @@
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')'; shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_REMOTE) { } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote') + ')'; shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'email') + ')';
}
if (shareType === OC.Share.SHARE_TYPE_GROUP) {
shareWithTitle = shareWith + " (" + t('core', 'group') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
shareWithTitle = shareWith + " (" + t('core', 'remote') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
shareWithTitle = shareWith + " (" + t('core', 'email') + ')';
} }
return _.extend(hasPermissionOverride, { return _.extend(hasPermissionOverride, {
@ -160,10 +176,13 @@
wasMailSent: this.model.notificationMailWasSent(shareIndex), wasMailSent: this.model.notificationMailWasSent(shareIndex),
shareWith: shareWith, shareWith: shareWith,
shareWithDisplayName: shareWithDisplayName, shareWithDisplayName: shareWithDisplayName,
shareWithTitle: shareWithTitle,
shareType: shareType, shareType: shareType,
shareId: this.model.get('shares')[shareIndex].id, shareId: this.model.get('shares')[shareIndex].id,
modSeed: shareType !== OC.Share.SHARE_TYPE_USER, modSeed: shareType !== OC.Share.SHARE_TYPE_USER,
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder()
}); });
}, },

View File

@ -154,10 +154,16 @@
var users = result.ocs.data.exact.users.concat(result.ocs.data.users); var users = result.ocs.data.exact.users.concat(result.ocs.data.users);
var groups = result.ocs.data.exact.groups.concat(result.ocs.data.groups); var groups = result.ocs.data.exact.groups.concat(result.ocs.data.groups);
var remotes = result.ocs.data.exact.remotes.concat(result.ocs.data.remotes); var remotes = result.ocs.data.exact.remotes.concat(result.ocs.data.remotes);
if (typeof(result.ocs.data.emails) !== 'undefined') {
var emails = result.ocs.data.exact.emails.concat(result.ocs.data.emails);
} else {
var emails = [];
}
var usersLength; var usersLength;
var groupsLength; var groupsLength;
var remotesLength; var remotesLength;
var emailsLength;
var i, j; var i, j;
@ -212,10 +218,18 @@
break; break;
} }
} }
} else if (share.share_type === OC.Share.SHARE_TYPE_EMAIL) {
emailsLength = emails.length;
for (j = 0; j < emailsLength; j++) {
if (emails[j].value.shareWith === share.share_with) {
emails.splice(j, 1);
break;
}
}
} }
} }
var suggestions = users.concat(groups).concat(remotes); var suggestions = users.concat(groups).concat(remotes).concat(emails);
if (suggestions.length > 0) { if (suggestions.length > 0) {
$('.shareWithField').removeClass('error') $('.shareWithField').removeClass('error')
@ -258,16 +272,13 @@
sharee: text sharee: text
}); });
} else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE) { } else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE) {
if (item.value.server) {
text = t('core', '{sharee} (at {server})', {
sharee: text,
server: item.value.server
});
} else {
text = t('core', '{sharee} (remote)', { text = t('core', '{sharee} (remote)', {
sharee: text sharee: text
}); });
} } else if (item.value.shareType === OC.Share.SHARE_TYPE_EMAIL) {
text = t('core', '{sharee} (email)', {
sharee: text
});
} }
var insert = $("<div class='share-autocomplete-item'/>"); var insert = $("<div class='share-autocomplete-item'/>");
var avatar = $("<div class='avatardiv'></div>").appendTo(insert); var avatar = $("<div class='avatardiv'></div>").appendTo(insert);
@ -397,7 +408,7 @@
var infoTemplate = this._getRemoteShareInfoTemplate(); var infoTemplate = this._getRemoteShareInfoTemplate();
remoteShareInfo = infoTemplate({ remoteShareInfo = infoTemplate({
docLink: this.configModel.getFederatedShareDocLink(), docLink: this.configModel.getFederatedShareDocLink(),
tooltip: t('core', 'Share with people on other Nextclouds using the syntax username@example.com/nextcloud') tooltip: t('core', 'Share with people on other servers using the syntax username@example.com/nextcloud')
}); });
} }
@ -405,19 +416,33 @@
}, },
_renderSharePlaceholderPart: function () { _renderSharePlaceholderPart: function () {
var sharePlaceholder = t('core', 'Share with users…'); var allowGroupSharing = this.configModel.get('allowGroupSharing');
var allowRemoteSharing = this.configModel.get('isRemoteShareAllowed');
var allowMailSharing = this.configModel.get('isMailShareAllowed');
if (this.configModel.get('allowGroupSharing')) { if (!allowGroupSharing && !allowRemoteSharing && allowMailSharing) {
if (this.configModel.get('isRemoteShareAllowed')) { return t('core', 'Share with users or by mail...');
sharePlaceholder = t('core', 'Share with users, groups or remote users…'); }
} else { if (!allowGroupSharing && allowRemoteSharing && !allowMailSharing) {
sharePlaceholder = t('core', 'Share with users or groups…'); return t('core', 'Share with users or remote users...');
} }
} else if (this.configModel.get('isRemoteShareAllowed')) { if (!allowGroupSharing && allowRemoteSharing && allowMailSharing) {
sharePlaceholder = t('core', 'Share with users or remote users…'); return t('core', 'Share with users, remote users or by mail...');
}
if (allowGroupSharing && !allowRemoteSharing && !allowMailSharing) {
return t('core', 'Share with users or groups...');
}
if (allowGroupSharing && !allowRemoteSharing && allowMailSharing) {
return t('core', 'Share with users, groups or by mail...');
}
if (allowGroupSharing && allowRemoteSharing && !allowMailSharing) {
return t('core', 'Share with users, groups or remote users...');
}
if (allowGroupSharing && allowRemoteSharing && allowMailSharing) {
return t('core', 'Share with users, groups, remote users or by mail...');
} }
return sharePlaceholder; return t('core', 'Share with users...');
}, },
/** /**

View File

@ -25,6 +25,7 @@
"password_policy", "password_policy",
"provisioning_api", "provisioning_api",
"serverinfo", "serverinfo",
"sharebymail",
"survey_client", "survey_client",
"systemtags", "systemtags",
"templateeditor", "templateeditor",

View File

@ -29,9 +29,9 @@ class Constants {
const SHARE_TYPE_USER = 0; const SHARE_TYPE_USER = 0;
const SHARE_TYPE_GROUP = 1; const SHARE_TYPE_GROUP = 1;
const SHARE_TYPE_LINK = 3; const SHARE_TYPE_LINK = 3;
const SHARE_TYPE_EMAIL = 4; // ToDo Check if it is still in use otherwise remove it const SHARE_TYPE_EMAIL = 4;
const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
const SHARE_TYPE_REMOTE = 6; // ToDo Check if it is still in use otherwise remove it const SHARE_TYPE_REMOTE = 6;
const FORMAT_NONE = -1; const FORMAT_NONE = -1;
const FORMAT_STATUSES = -2; const FORMAT_STATUSES = -2;

View File

@ -30,6 +30,7 @@ namespace OC\Share20;
use OC\Cache\CappedMemoryCache; use OC\Cache\CappedMemoryCache;
use OC\Files\Mount\MoveableMount; use OC\Files\Mount\MoveableMount;
use OC\HintException; use OC\HintException;
use OC\Share20\Exception\ProviderException;
use OCP\Files\File; use OCP\Files\File;
use OCP\Files\Folder; use OCP\Files\Folder;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
@ -185,6 +186,10 @@ class Manager implements IManager {
if ($share->getSharedWith() === null) { if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty'); throw new \InvalidArgumentException('SharedWith should not be empty');
} }
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
}
} else { } else {
// We can't handle other types yet // We can't handle other types yet
throw new \InvalidArgumentException('unkown share type'); throw new \InvalidArgumentException('unkown share type');
@ -580,6 +585,16 @@ class Manager implements IManager {
if ($share->getPassword() !== null) { if ($share->getPassword() !== null) {
$share->setPassword($this->hasher->hash($share->getPassword())); $share->setPassword($this->hasher->hash($share->getPassword()));
} }
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
$this->linkCreateChecks($share);
$share->setToken(
$this->secureRandom->generate(
\OC\Share\Constants::TOKEN_LENGTH,
\OCP\Security\ISecureRandom::CHAR_LOWER.
\OCP\Security\ISecureRandom::CHAR_UPPER.
\OCP\Security\ISecureRandom::CHAR_DIGITS
)
);
} }
// Cannot share with the owner // Cannot share with the owner
@ -1034,6 +1049,16 @@ class Manager implements IManager {
// If it is not a link share try to fetch a federated share by token // If it is not a link share try to fetch a federated share by token
if ($share === null) { if ($share === null) {
$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE); $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
try {
$share = $provider->getShareByToken($token);
} catch (ShareNotFound $e) {
$share = null;
}
}
// If it is not a link share try to fetch a federated share by token
if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
$share = $provider->getShareByToken($token); $share = $provider->getShareByToken($token);
} }
@ -1277,4 +1302,17 @@ class Manager implements IManager {
return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes'; return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
} }
/**
* @inheritdoc
*/
public function shareProviderExists($shareType) {
try {
$this->factory->getProviderForType($shareType);
} catch (ProviderException $e) {
return false;
}
return true;
}
} }

View File

@ -28,6 +28,7 @@ use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\FederatedShareProvider; use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\FederatedFileSharing\Notifications; use OCA\FederatedFileSharing\Notifications;
use OCA\FederatedFileSharing\TokenHandler; use OCA\FederatedFileSharing\TokenHandler;
use OCA\ShareByMail\ShareByMailProvider;
use OCP\Share\IProviderFactory; use OCP\Share\IProviderFactory;
use OC\Share20\Exception\ProviderException; use OC\Share20\Exception\ProviderException;
use OCP\IServerContainer; use OCP\IServerContainer;
@ -45,6 +46,8 @@ class ProviderFactory implements IProviderFactory {
private $defaultProvider = null; private $defaultProvider = null;
/** @var FederatedShareProvider */ /** @var FederatedShareProvider */
private $federatedProvider = null; private $federatedProvider = null;
/** @var ShareByMailProvider */
private $shareByMailProvider;
/** /**
* IProviderFactory constructor. * IProviderFactory constructor.
@ -125,6 +128,39 @@ class ProviderFactory implements IProviderFactory {
return $this->federatedProvider; return $this->federatedProvider;
} }
/**
* Create the federated share provider
*
* @return FederatedShareProvider
*/
protected function getShareByMailProvider() {
if ($this->shareByMailProvider === null) {
/*
* Check if the app is enabled
*/
$appManager = $this->serverContainer->getAppManager();
if (!$appManager->isEnabledForUser('sharebymail')) {
return null;
}
$l = $this->serverContainer->getL10N('sharebymail');
$this->shareByMailProvider = new ShareByMailProvider(
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getSecureRandom(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getLazyRootFolder(),
$l,
$this->serverContainer->getLogger(),
$this->serverContainer->getMailer(),
$this->serverContainer->getURLGenerator()
);
}
return $this->shareByMailProvider;
}
/** /**
* @inheritdoc * @inheritdoc
*/ */
@ -134,6 +170,8 @@ class ProviderFactory implements IProviderFactory {
$provider = $this->defaultShareProvider(); $provider = $this->defaultShareProvider();
} else if ($id === 'ocFederatedSharing') { } else if ($id === 'ocFederatedSharing') {
$provider = $this->federatedShareProvider(); $provider = $this->federatedShareProvider();
} else if ($id = 'ocMailShare') {
$provider = $this->getShareByMailProvider();
} }
if ($provider === null) { if ($provider === null) {
@ -155,6 +193,8 @@ class ProviderFactory implements IProviderFactory {
$provider = $this->defaultShareProvider(); $provider = $this->defaultShareProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
$provider = $this->federatedShareProvider(); $provider = $this->federatedShareProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
$provider = $this->getShareByMailProvider();
} }
if ($provider === null) { if ($provider === null) {

View File

@ -286,4 +286,12 @@ interface IManager {
*/ */
public function outgoingServer2ServerSharesAllowed(); public function outgoingServer2ServerSharesAllowed();
/**
* Check if a given share provider exists
* @param int $shareType
* @return bool
* @since 9.2.0
*/
public function shareProviderExists($shareType);
} }

View File

@ -2530,6 +2530,46 @@ class ManagerTest extends \Test\TestCase {
$this->manager->moveShare($share, 'recipient'); $this->manager->moveShare($share, 'recipient');
} }
/**
* @dataProvider dataTestShareProviderExists
*/
public function testShareProviderExists($shareType, $expected) {
$factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
$factory->expects($this->any())->method('getProviderForType')
->willReturnCallback(function ($id) {
if ($id === \OCP\Share::SHARE_TYPE_USER) {
return true;
}
throw new Exception\ProviderException();
});
$manager = new Manager(
$this->logger,
$this->config,
$this->secureRandom,
$this->hasher,
$this->mountManager,
$this->groupManager,
$this->l,
$factory,
$this->userManager,
$this->rootFolder,
$this->eventDispatcher
);
$this->assertSame($expected,
$manager->shareProviderExists($shareType)
);
}
public function dataTestShareProviderExists() {
return [
[\OCP\Share::SHARE_TYPE_USER, true],
[42, false],
];
}
public function testGetSharesInFolder() { public function testGetSharesInFolder() {
$factory = new DummyFactory2($this->createMock(IServerContainer::class)); $factory = new DummyFactory2($this->createMock(IServerContainer::class));