diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php index 61f87e9ec6..233395dec9 100644 --- a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php +++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php @@ -67,7 +67,7 @@ class RequestHandlerControllerTest extends TestCase { /** @var \OCA\FederatedFileSharing\AddressHandler|\PHPUnit_Framework_MockObject_MockObject */ private $addressHandler; - + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ private $userManager; @@ -107,7 +107,7 @@ class RequestHandlerControllerTest extends TestCase { $this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock(); $this->cloudIdManager = new CloudIdManager(); - + $this->registerHttpHelper($httpHelperMock); $this->s2s = new RequestHandlerController( @@ -384,6 +384,7 @@ class RequestHandlerControllerTest extends TestCase { 'parent' => null, 'accepted' => '0', 'expiration' => null, + 'password' => null, 'mail_send' => '0' ]; diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index e2a08d951a..29a137fed0 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -10,7 +10,7 @@ Turning the feature off removes shared files and folders on the server for all s AGPL Michael Gapczynski, Bjoern Schiessle - 1.2.0 + 1.4.0 diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index ed0d7732b3..917cb7b663 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -34,3 +34,8 @@ if (version_compare($installedVersion, '0.9.1', '<')) { if (version_compare($installedVersion, '1.1.1', '<')) { $m = new Migration(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()); } + +if (version_compare($installedVersion, '1.4.0', '<')) { + $m = new Migration(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()); + $m->addPasswordColumn(); +} diff --git a/apps/files_sharing/lib/Capabilities.php b/apps/files_sharing/lib/Capabilities.php index bfbd15c112..ed00cdc00a 100644 --- a/apps/files_sharing/lib/Capabilities.php +++ b/apps/files_sharing/lib/Capabilities.php @@ -21,6 +21,7 @@ */ namespace OCA\Files_Sharing; +use OCP\App\IAppManager; use OCP\Capabilities\ICapability; use \OCP\IConfig; @@ -34,8 +35,12 @@ class Capabilities implements ICapability { /** @var IConfig */ private $config; - public function __construct(IConfig $config) { + /** @var IAppManager */ + private $appManager; + + public function __construct(IConfig $config, IAppManager $appManager) { $this->config = $config; + $this->appManager = $appManager; } /** @@ -76,16 +81,33 @@ class Capabilities implements ICapability { $res['resharing'] = $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes') === 'yes'; $res['user']['send_mail'] = false; + $res['user']['expire_date']['enabled'] = true; + // deprecated in favour of 'group', but we need to keep it for now + // in order to stay compatible with older clients $res['group_sharing'] = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes'; + + $res['group'] = []; + $res['group']['enabled'] = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes'; + $res['group']['expire_date']['enabled'] = true; } //Federated sharing $res['federation'] = [ 'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes', - 'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes' + 'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes', + 'expire_date' => ['enabled' => true] ]; + if ($this->appManager->isEnabledForUser('sharebymail')) { + $res['mailshare'] = [ + 'enabled' => true, + 'upload_files_drop' => ['enabled' => true], + 'password' => ['enabled' => true], + 'expire_date' => ['enabled' => true] + ]; + } + return [ 'files_sharing' => $res, ]; diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 78eef6c26b..bc525b6ef8 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -163,6 +163,11 @@ class ShareAPIController extends OCSController { $result['file_parent'] = $node->getParent()->getId(); $result['file_target'] = $share->getTarget(); + $expiration = $share->getExpirationDate(); + if ($expiration !== null) { + $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); + } + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { $sharedWith = $this->userManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); @@ -179,17 +184,13 @@ class ShareAPIController extends OCSController { $result['token'] = $share->getToken(); $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); - $expiration = $share->getExpirationDate(); - if ($expiration !== null) { - $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); - } - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { $result['share_with'] = $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['password'] = $share->getPassword(); $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL'); $result['token'] = $share->getToken(); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) { @@ -668,13 +669,14 @@ class ShareAPIController extends OCSController { throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist')); } + if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { + throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given')); + } + /* * expirationdate, password and publicUpload only make sense for link shares */ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { - if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { - throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given')); - } $newPermissions = null; if ($publicUpload === 'true') { @@ -740,13 +742,30 @@ class ShareAPIController extends OCSController { } } else { - // For other shares only permissions is valid. - if ($permissions === null) { - throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given')); - } else { + if ($permissions !== null) { $permissions = (int)$permissions; $share->setPermissions($permissions); } + + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) { + if ($password === '') { + $share->setPassword(null); + } else if ($password !== null) { + $share->setPassword($password); + } + } + + if ($expireDate === '') { + $share->setExpirationDate(null); + } else if ($expireDate !== null) { + try { + $expireDate = $this->parseDate($expireDate); + } catch (\Exception $e) { + throw new OCSBadRequestException($e->getMessage()); + } + $share->setExpirationDate($expireDate); + } + } if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) { diff --git a/apps/files_sharing/lib/Migration.php b/apps/files_sharing/lib/Migration.php index 605a11fd22..49e275cbe6 100644 --- a/apps/files_sharing/lib/Migration.php +++ b/apps/files_sharing/lib/Migration.php @@ -123,6 +123,24 @@ class Migration { $this->config->deleteAppValue('core', 'shareapi_allow_public_notification'); } + public function addPasswordColumn() { + $query = $this->connection->getQueryBuilder(); + $query + ->update('share') + ->set('password', 'share_with') + ->where($query->expr()->eq('share_type', $query->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))) + ->andWhere($query->expr()->isNotNull('share_with')); + $query->execute(); + + $clearQuery = $this->connection->getQueryBuilder(); + $clearQuery + ->update('share')->set('share_with', $clearQuery->createNamedParameter(null)) + ->where($clearQuery->expr()->eq('share_type', $clearQuery->createNamedParameter(\OCP\Share::SHARE_TYPE_LINK))); + + $clearQuery->execute(); + + } + /** * find the owner of a re-shared file/folder * diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 540905a7dc..046ede1f83 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -936,36 +936,6 @@ class ApiTest extends TestCase { $this->shareManager->deleteShare($share2); } - /** - * @medium - * @depends testCreateShareUserFile - */ - public function testUpdateShareInvalidPermissions() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1); - try { - $ocs->updateShare($share1->getId()); - $this->fail(); - } catch (OCSBadRequestException $e) { - - } - $ocs->cleanup(); - - //Permissions should not have changed! - $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId()); - $this->assertEquals(19, $share1->getPermissions()); - - $this->shareManager->deleteShare($share1); - } - /** * @medium */ diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php index 3d59b1f6f3..79ac1854e4 100644 --- a/apps/files_sharing/tests/CapabilitiesTest.php +++ b/apps/files_sharing/tests/CapabilitiesTest.php @@ -25,6 +25,7 @@ namespace OCA\Files_Sharing\Tests; use OCA\Files_Sharing\Capabilities; use OCA\Files_Sharing\Tests\TestCase; +use OCP\App\IAppManager; /** * Class CapabilitiesTest @@ -46,7 +47,7 @@ class CapabilitiesTest extends \Test\TestCase { } /** - * Create a mock config object and insert the values in $map tot the getAppValue + * Create a mock config object and insert the values in $map to the getAppValue * function. Then obtain the capabilities and extract the first few * levels in the array * @@ -54,9 +55,11 @@ class CapabilitiesTest extends \Test\TestCase { * @return string[] */ private function getResults(array $map) { - $stub = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock(); - $stub->method('getAppValue')->will($this->returnValueMap($map)); - $cap = new Capabilities($stub); + $config = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock(); + $config->method('getAppValue')->will($this->returnValueMap($map)); + $appManager = $this->getMockBuilder(IAppManager::class)->getMock(); + $appManager->expects($this->any())->method('isEnabledForUser')->with('sharebymail')->willReturn(true); + $cap = new Capabilities($config, $appManager); $result = $this->getFilesSharingPart($cap->getCapabilities()); return $result; } diff --git a/apps/files_sharing/tests/MigrationTest.php b/apps/files_sharing/tests/MigrationTest.php index 572f64da74..708de1c0ec 100644 --- a/apps/files_sharing/tests/MigrationTest.php +++ b/apps/files_sharing/tests/MigrationTest.php @@ -28,6 +28,7 @@ namespace OCA\Files_Sharing\Tests; use OCA\Files_Sharing\Migration; +use OCP\Share; /** * Class MigrationTest @@ -87,7 +88,7 @@ class MigrationTest extends TestCase { ) ); // shared contact, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_CONTACT) + $query->setParameter('share_type', Share::SHARE_TYPE_CONTACT) ->setParameter('share_with', 'user1') ->setParameter('uid_owner', 'owner1') ->setParameter('uid_initiator', '') @@ -103,7 +104,7 @@ class MigrationTest extends TestCase { $query->execute() ); // shared calendar, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + $query->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user1') ->setParameter('uid_owner', 'owner1') ->setParameter('uid_initiator', '') @@ -119,7 +120,7 @@ class MigrationTest extends TestCase { $query->execute() ); // single user share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + $query->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user1') ->setParameter('uid_owner', 'owner1') ->setParameter('uid_initiator', '') @@ -135,7 +136,7 @@ class MigrationTest extends TestCase { $query->execute() ); // single group share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_GROUP) + $query->setParameter('share_type', Share::SHARE_TYPE_GROUP) ->setParameter('share_with', 'group1') ->setParameter('uid_owner', 'owner1') ->setParameter('uid_initiator', '') @@ -168,7 +169,7 @@ class MigrationTest extends TestCase { $query->execute() ); // first user share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + $query->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user1') ->setParameter('uid_owner', 'owner2') ->setParameter('uid_initiator', '') @@ -185,7 +186,7 @@ class MigrationTest extends TestCase { ); $parent = $query->getLastInsertId(); // first re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + $query->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user2') ->setParameter('uid_owner', 'user1') ->setParameter('uid_initiator', '') @@ -202,7 +203,7 @@ class MigrationTest extends TestCase { ); $parent = $query->getLastInsertId(); // second re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + $query->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user3') ->setParameter('uid_owner', 'user2') ->setParameter('uid_initiator', '') @@ -219,7 +220,7 @@ class MigrationTest extends TestCase { ); $parent = $query->getLastInsertId(); // third re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_REMOTE) + $query->setParameter('share_type', Share::SHARE_TYPE_REMOTE) ->setParameter('share_with', 'user@server.com') ->setParameter('uid_owner', 'user3') ->setParameter('uid_initiator', '') @@ -236,7 +237,7 @@ class MigrationTest extends TestCase { ); // Link reshare should keep its parent - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_LINK) + $query->setParameter('share_type', Share::SHARE_TYPE_LINK) ->setParameter('share_with', null) ->setParameter('uid_owner', 'user3') ->setParameter('uid_initiator', '') @@ -317,7 +318,7 @@ class MigrationTest extends TestCase { 'stime' => $query->createParameter('stime'), ] ) - ->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_type', Share::SHARE_TYPE_USER) ->setParameter('share_with', 'user'.($i+1)) ->setParameter('uid_owner', 'user'.($i)) ->setParameter('uid_initiator', null) @@ -377,4 +378,63 @@ class MigrationTest extends TestCase { $this->config->getAppValue('core', 'shareapi_setting1', null) ); } + + public function testAddPasswordColumn() { + + $shareTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE, Share::SHARE_TYPE_EMAIL, Share::SHARE_TYPE_LINK]; + + foreach ($shareTypes as $shareType) { + + for ($i = 0; $i < 5; $i++) { + $query = $this->connection->getQueryBuilder(); + $query->insert($this->table) + ->values( + [ + 'share_type' => $query->createParameter('share_type'), + 'share_with' => $query->createParameter('share_with'), + 'uid_owner' => $query->createParameter('uid_owner'), + 'uid_initiator' => $query->createParameter('uid_initiator'), + 'parent' => $query->createParameter('parent'), + 'item_type' => $query->createParameter('item_type'), + 'item_source' => $query->createParameter('item_source'), + 'item_target' => $query->createParameter('item_target'), + 'file_source' => $query->createParameter('file_source'), + 'file_target' => $query->createParameter('file_target'), + 'permissions' => $query->createParameter('permissions'), + 'stime' => $query->createParameter('stime'), + ] + ) + ->setParameter('share_type', $shareType) + ->setParameter('share_with', 'shareWith') + ->setParameter('uid_owner', 'user' . ($i)) + ->setParameter('uid_initiator', null) + ->setParameter('parent', 0) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + + $this->assertSame(1, $query->execute()); + } + } + + $this->migration->addPasswordColumn(); + + $query = $this->connection->getQueryBuilder(); + $query->select('*')->from('share'); + $allShares = $query->execute()->fetchAll(); + + foreach ($allShares as $share) { + if ((int)$share['share_type'] === Share::SHARE_TYPE_LINK) { + $this->assertNull( $share['share_with']); + $this->assertSame('shareWith', $share['password']); + } else { + $this->assertSame('shareWith', $share['share_with']); + $this->assertNull($share['password']); + } + } + } } diff --git a/apps/sharebymail/appinfo/info.xml b/apps/sharebymail/appinfo/info.xml index 5528f6158d..ab50ef0369 100644 --- a/apps/sharebymail/appinfo/info.xml +++ b/apps/sharebymail/appinfo/info.xml @@ -5,7 +5,7 @@ Share provider which allows you to share files by mail AGPL Bjoern Schiessle - 1.1.0 + 1.2.0 ShareByMail other @@ -17,6 +17,10 @@ + + OCA\ShareByMail\Settings\Admin + + OCA\ShareByMail\Activity diff --git a/apps/sharebymail/js/settings-admin.js b/apps/sharebymail/js/settings-admin.js new file mode 100644 index 0000000000..7b43123303 --- /dev/null +++ b/apps/sharebymail/js/settings-admin.js @@ -0,0 +1,30 @@ +/** + * @copyright Copyright (c) 2017 Bjoern Schiessle + * + * @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 . + * + */ +$(function() { + + $('#sendPasswordMail').on('change', function() { + var status = 'no'; + if ($(this).is(':checked')) { + status = 'yes'; + } + OC.AppConfig.setValue('sharebymail', 'sendpasswordmail', status); + }); + +}); diff --git a/apps/sharebymail/lib/Settings/Admin.php b/apps/sharebymail/lib/Settings/Admin.php new file mode 100644 index 0000000000..b6e7e5d3b4 --- /dev/null +++ b/apps/sharebymail/lib/Settings/Admin.php @@ -0,0 +1,67 @@ + + * + * @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 . + * + */ + + +namespace OCA\ShareByMail\Settings; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\Settings\ISettings; + +class Admin implements ISettings { + + /** @var SettingsManager */ + private $settingsManager; + + public function __construct(SettingsManager $settingsManager) { + $this->settingsManager = $settingsManager; + } + + /** + * @return TemplateResponse + */ + public function getForm() { + + $parameters = [ + 'sendPasswordMail' => $this->settingsManager->sendPasswordByMail() + ]; + + return new TemplateResponse('sharebymail', 'settings-admin', $parameters, ''); + } + + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() { + return 'sharing'; + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * E.g.: 70 + */ + public function getPriority() { + return 40; + } + +} diff --git a/apps/sharebymail/lib/Settings/SettingsManager.php b/apps/sharebymail/lib/Settings/SettingsManager.php new file mode 100644 index 0000000000..205b253f33 --- /dev/null +++ b/apps/sharebymail/lib/Settings/SettingsManager.php @@ -0,0 +1,49 @@ + + * + * @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 . + * + */ + + +namespace OCA\ShareByMail\Settings; + + +use OCP\IConfig; + +class SettingsManager { + + /** @var IConfig */ + private $config; + + private $defaultSetting = 'yes'; + + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * should the password for a mail share be send to the recipient + * + * @return bool + */ + public function sendPasswordByMail() { + $sendPasswordByMail = $this->config->getAppValue('sharebymail', 'sendpasswordmail', $this->defaultSetting); + return $sendPasswordByMail === 'yes'; + } + +} diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php index e09ca308f3..332f1c0cf7 100644 --- a/apps/sharebymail/lib/ShareByMailProvider.php +++ b/apps/sharebymail/lib/ShareByMailProvider.php @@ -23,7 +23,9 @@ namespace OCA\ShareByMail; use OC\HintException; use OC\Share20\Exception\InvalidShare; +use OCA\ShareByMail\Settings\SettingsManager; use OCP\Activity\IManager; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Node; @@ -75,13 +77,16 @@ class ShareByMailProvider implements IShareProvider { /** @var IManager */ private $activityManager; + /** @var SettingsManager */ + private $settingsManager; + /** * Return the identifier of this provider. * * @return string Containing only [a-zA-Z0-9] */ public function identifier() { - return 'ocShareByMail'; + return 'ocMailShare'; } /** @@ -96,6 +101,7 @@ class ShareByMailProvider implements IShareProvider { * @param IMailer $mailer * @param IURLGenerator $urlGenerator * @param IManager $activityManager + * @param SettingsManager $settingsManager */ public function __construct( IDBConnection $connection, @@ -106,7 +112,8 @@ class ShareByMailProvider implements IShareProvider { ILogger $logger, IMailer $mailer, IURLGenerator $urlGenerator, - IManager $activityManager + IManager $activityManager, + SettingsManager $settingsManager ) { $this->dbConnection = $connection; $this->secureRandom = $secureRandom; @@ -117,6 +124,7 @@ class ShareByMailProvider implements IShareProvider { $this->mailer = $mailer; $this->urlGenerator = $urlGenerator; $this->activityManager = $activityManager; + $this->settingsManager = $settingsManager; } /** @@ -275,10 +283,10 @@ class ShareByMailProvider implements IShareProvider { protected function createMailBody($template, $filename, $link, $owner, $initiator) { $mailBodyTemplate = new Template('sharebymail', $template, ''); - $mailBodyTemplate->assign ('filename', $filename); + $mailBodyTemplate->assign ('filename', \OCP\Util::sanitizeHTML($filename)); $mailBodyTemplate->assign ('link', $link); - $mailBodyTemplate->assign ('owner', $owner); - $mailBodyTemplate->assign ('initiator', $initiator); + $mailBodyTemplate->assign ('owner', \OCP\Util::sanitizeHTML($owner)); + $mailBodyTemplate->assign ('initiator', \OCP\Util::sanitizeHTML($initiator)); $mailBodyTemplate->assign ('onBehalfOf', $initiator !== $owner); $mailBody = $mailBodyTemplate->fetchPage(); @@ -290,6 +298,60 @@ class ShareByMailProvider implements IShareProvider { $this->l->t('Failed to create the E-mail')); } + /** + * send password to recipient of a mail share + * + * @param string $filename + * @param string $initiator + * @param string $shareWith + */ + protected function sendPassword($filename, $initiator, $shareWith, $password) { + + if ($this->settingsManager->sendPasswordByMail() === false) { + return; + } + + $initiatorUser = $this->userManager->get($initiator); + $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator; + $subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]); + + $message = $this->mailer->createMessage(); + $htmlBody = $this->createMailBodyToSendPassword('mailpassword', $filename, $initiatorDisplayName, $password); + $textBody = $this->createMailBodyToSendPassword('altmailpassword', $filename,$initiatorDisplayName, $password); + $message->setTo([$shareWith]); + $message->setSubject($subject); + $message->setBody($textBody, 'text/plain'); + $message->setHtmlBody($htmlBody); + $this->mailer->send($message); + + } + + /** + * create mail body to send password to recipient + * + * @param string $filename + * @param string $initiator + * @param string $password + * @return string plain text mail + * @throws HintException + */ + protected function createMailBodyToSendPassword($template, $filename, $initiator, $password) { + + $mailBodyTemplate = new Template('sharebymail', $template, ''); + $mailBodyTemplate->assign ('filename', \OCP\Util::sanitizeHTML($filename)); + $mailBodyTemplate->assign ('password', \OCP\Util::sanitizeHTML($password)); + $mailBodyTemplate->assign ('initiator', \OCP\Util::sanitizeHTML($initiator)); + $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 * @@ -368,19 +430,31 @@ class ShareByMailProvider implements IShareProvider { * Update a share * * @param IShare $share + * @param string|null $plainTextPassword * @return IShare The share object */ - public function update(IShare $share) { + public function update(IShare $share, $plainTextPassword = null) { + + $originalShare = $this->getShareById($share->getId()); + + // a real password was given + $validPassword = $plainTextPassword !== null && $plainTextPassword !== ''; + + if($validPassword && $originalShare->getPassword() !== $share->getPassword()) { + $this->sendPassword($share->getNode()->getName(), $share->getSharedBy(), $share->getSharedWith(), $plainTextPassword); + } /* - * We allow updating the permissions of mail shares + * We allow updating the permissions and password 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(); + $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())) + ->set('password', $qb->createNamedParameter($share->getPassword())) + ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) + ->execute(); return $share; } @@ -625,6 +699,7 @@ class ShareByMailProvider implements IShareProvider { $shareTime->setTimestamp((int)$data['stime']); $share->setShareTime($shareTime); $share->setSharedWith($data['share_with']); + $share->setPassword($data['password']); if ($data['uid_initiator'] !== null) { $share->setShareOwner($data['uid_owner']); @@ -638,6 +713,13 @@ class ShareByMailProvider implements IShareProvider { $share->setShareOwner($owner->getUID()); } + if ($data['expiration'] !== null) { + $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']); + if ($expiration !== false) { + $share->setExpirationDate($expiration); + } + } + $share->setNodeId((int)$data['file_source']); $share->setNodeType($data['item_type']); diff --git a/apps/sharebymail/templates/altmailpassword.php b/apps/sharebymail/templates/altmailpassword.php new file mode 100644 index 0000000000..f6e4c5b415 --- /dev/null +++ b/apps/sharebymail/templates/altmailpassword.php @@ -0,0 +1,32 @@ + + * + * @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 . + * + */ + +/** @var OC_Theme $theme */ +/** @var array $_ */ +print_unescaped($l->t("Hey there,\n\n%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n\nIt is protected with the following password: %s\n\n", [$_['initiator'], $_['filename'], $_['password']])); +// TRANSLATORS term at the end of a mail +p($l->t("Cheers!")); +print_unescaped("\n"); +?> + + -- +getName() . ' - ' . $theme->getSlogan()); ?> +getBaseUrl()); diff --git a/apps/sharebymail/templates/mailpassword.php b/apps/sharebymail/templates/mailpassword.php new file mode 100644 index 0000000000..714a61cecd --- /dev/null +++ b/apps/sharebymail/templates/mailpassword.php @@ -0,0 +1,59 @@ + + * + * @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 . + * + */ + +/** @var OCA\Theming\ThemingDefaults $theme */ +/** @var array $_ */ +?> + + + +
+ + + + + + + + + + + + + + + + + +
+ <?php p($theme->getName()); ?> +
 
  + t('Hey there,

%s shared %s with you.
You should have already received a separate mail with a link to access it.

It is protected with the following password: %s

', [$_['initiator'], $_['filename'], $_['password']])); + // TRANSLATORS term at the end of a mail + p($l->t('Cheers!')); + ?> +
 
 --
+ getName()); ?> - + getSlogan()); ?> +
getBaseUrl());?> +
 
+
diff --git a/apps/sharebymail/templates/settings-admin.php b/apps/sharebymail/templates/settings-admin.php new file mode 100644 index 0000000000..c4e4108606 --- /dev/null +++ b/apps/sharebymail/templates/settings-admin.php @@ -0,0 +1,18 @@ + +
+

t('Share by mail')); ?>

+ t('Send a personalized link to a file or folder by mail.')); ?> + +

+ /> + +

+ +
+ diff --git a/apps/sharebymail/tests/ShareByMailProviderTest.php b/apps/sharebymail/tests/ShareByMailProviderTest.php index 65eded3eb7..288ebb4bb4 100644 --- a/apps/sharebymail/tests/ShareByMailProviderTest.php +++ b/apps/sharebymail/tests/ShareByMailProviderTest.php @@ -23,7 +23,7 @@ namespace OCA\ShareByMail\Tests; -use OC\HintException; +use OCA\ShareByMail\Settings\SettingsManager; use OCA\ShareByMail\ShareByMailProvider; use OCP\Files\IRootFolder; use OCP\IDBConnection; @@ -33,7 +33,6 @@ 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; @@ -79,6 +78,9 @@ class ShareByMailProviderTest extends TestCase { /** @var \OCP\Activity\IManager | \PHPUnit_Framework_MockObject_MockObject */ private $activityManager; + /** @var SettingsManager | \PHPUnit_Framework_MockObject_MockObject */ + private $settingsManager; + public function setUp() { parent::setUp(); @@ -98,6 +100,7 @@ class ShareByMailProviderTest extends TestCase { $this->urlGenerator = $this->getMockBuilder('\OCP\IUrlGenerator')->getMock(); $this->share = $this->getMockBuilder('\OCP\Share\IShare')->getMock(); $this->activityManager = $this->getMockBuilder('OCP\Activity\IManager')->getMock(); + $this->settingsManager = $this->getMockBuilder(SettingsManager::class)->disableOriginalConstructor()->getMock(); $this->userManager->expects($this->any())->method('userExists')->willReturn(true); } @@ -121,7 +124,8 @@ class ShareByMailProviderTest extends TestCase { $this->logger, $this->mailer, $this->urlGenerator, - $this->activityManager + $this->activityManager, + $this->settingsManager ] ); @@ -139,7 +143,8 @@ class ShareByMailProviderTest extends TestCase { $this->logger, $this->mailer, $this->urlGenerator, - $this->activityManager + $this->activityManager, + $this->settingsManager ); } @@ -311,7 +316,7 @@ class ShareByMailProviderTest extends TestCase { $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->share->expects($this->atLeastOnce())->method('getId')->willReturn($id); $this->assertSame($this->share, $instance->update($this->share) diff --git a/core/css/apps.scss b/core/css/apps.scss index 0c31e5bae4..da1c516205 100644 --- a/core/css/apps.scss +++ b/core/css/apps.scss @@ -477,7 +477,7 @@ kbd { border-radius: 0; text-align: left; padding-left: 42px; - font-weight: normal; + font-weight: 300; &:hover, &:focus { background-color: $color-main-background; @@ -667,7 +667,7 @@ kbd { width: auto; height: auto; margin: 0; - font-weight: inherit; + font-weight: 300; box-shadow: none; /* prevent .action class to break the design */ &.action { diff --git a/core/css/share.scss b/core/css/share.scss index 0e6eb3ccf8..de545955aa 100644 --- a/core/css/share.scss +++ b/core/css/share.scss @@ -106,6 +106,7 @@ .shareOption { white-space: nowrap; display: inline-block; + opacity: 1 !important; } .unshare img, .showCruds img { @@ -184,3 +185,16 @@ a { padding-top: 12px; color: rgba($color-main-text, .4); } + +.popovermenu .datepicker { + margin-left: 35px; +} + +.popovermenu .passwordField { + margin-left: 35px; + width: inherit !important; +} + +.ui-datepicker { + z-index: 1111 !important; +} diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index e46a761db6..a9945b594e 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -13,6 +13,10 @@ /* globals Handlebars */ (function() { + + var PASSWORD_PLACEHOLDER = '**********'; + var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the mail share'); + if (!OC.Share) { OC.Share = {}; } @@ -25,12 +29,10 @@ '{{shareWithDisplayName}}' + '' + '{{#if editPermissionPossible}}' + - '{{#unless isFileSharedByMail}}' + '' + '' + '' + '' + - '{{/unless}}' + '{{/if}}' + '' + '{{{popoverMenu}}}' + @@ -87,6 +89,37 @@ '' + '{{/unless}}{{/if}}' + '{{/if}}' + + '{{#if isMailShare}}' + + '{{#if hasCreatePermission}}' + + '
  • ' + + '' + + '' + + '' + + '' + + '
  • ' + + '{{/if}}' + + '
  • ' + + '' + + '' + + '' + + '
    ' + + ' ' + + ' ' + + ' ' + + '
    ' + + '
    ' + + '
  • ' + + '{{/if}}' + + '
  • ' + + '' + + '' + + '' + + '
    ' + + ' ' + + ' ' + + '
    ' + + '
    ' + + '
  • ' + '
  • ' + '{{unshareLabel}}' + '
  • ' + @@ -125,6 +158,13 @@ 'click .unshare': 'onUnshare', 'click .icon-more': 'onToggleMenu', 'click .permissions': 'onPermissionChange', + 'click .expireDate' : 'onExpireDateChange', + 'click .password' : 'onMailSharePasswordProtectChange', + 'click .secureDrop' : 'onSecureDropChange', + 'keyup input.passwordField': 'onMailSharePasswordKeyUp', + 'focusout input.passwordField': 'onMailSharePasswordEntered', + 'change .datepicker': 'onChangeExpirationDate', + 'click .datepicker' : 'showDatePicker' }, initialize: function(options) { @@ -171,6 +211,11 @@ shareWithTitle = shareWith; } + var share = this.model.get('shares')[shareIndex]; + var password = share.password; + var hasPassword = password !== null && password !== ''; + + return _.extend(hasPermissionOverride, { cid: this.cid, hasSharePermission: this.model.hasSharePermission(shareIndex), @@ -187,19 +232,27 @@ isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE, isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL, isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE, - isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder() + isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(), + isPasswordSet: hasPassword, + secureDropMode: !this.model.hasReadPermission(shareIndex), + hasExpireDate: this.model.getExpireDate(shareIndex) !== null, + expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), + passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, }); }, getShareProperties: function() { return { unshareLabel: t('core', 'Unshare'), - canShareLabel: t('core', 'can reshare'), - canEditLabel: t('core', 'can edit'), - createPermissionLabel: t('core', 'can create'), - updatePermissionLabel: t('core', 'can change'), - deletePermissionLabel: t('core', 'can delete'), - crudsLabel: t('core', 'access control'), + canShareLabel: t('core', 'Can reshare'), + canEditLabel: t('core', 'Can edit'), + createPermissionLabel: t('core', 'Can create'), + updatePermissionLabel: t('core', 'Can change'), + deletePermissionLabel: t('core', 'Can delete'), + secureDropLabel: t('core', 'Secure drop (upload only)'), + expireDateLabel: t('core', 'Set expiration date'), + passwordLabel: t('core', 'Password protect'), + crudsLabel: t('core', 'Access control'), triangleSImage: OC.imagePath('core', 'actions/triangle-s'), isResharingAllowed: this.configModel.get('isResharingAllowed'), sharePermissionPossible: this.model.sharePermissionPossible(), @@ -211,6 +264,7 @@ createPermission: OC.PERMISSION_CREATE, updatePermission: OC.PERMISSION_UPDATE, deletePermission: OC.PERMISSION_DELETE, + readPermission: OC.PERMISSION_READ, isFolder: this.model.isFolder() }; }, @@ -313,6 +367,19 @@ this.$('.popovermenu').on('afterHide', function() { _this._menuOpen = false; }); + this.$('.popovermenu').on('beforeHide', function() { + var shareId = parseInt(_this._menuOpen, 10); + if(!_.isNaN(shareId)) { + var datePickerClass = '.expirationDateContainer-' + _this.cid + '-' + shareId; + var datePickerInput = '#expirationDatePicker-' + _this.cid + '-' + shareId; + var expireDateCheckbox = '#expireDate-' + _this.cid + '-' + shareId; + if ($(expireDateCheckbox).prop('checked')) { + $(datePickerInput).removeClass('hidden-visually'); + $(datePickerClass).removeClass('hasDatepicker'); + $(datePickerClass + ' .ui-datepicker').hide(); + } + } + }); if (this._menuOpen != false) { // Open menu again if it was opened before var shareId = parseInt(this._menuOpen, 10); @@ -401,6 +468,123 @@ this._menuOpen = $li.data('share-id'); }, + onExpireDateChange: function(event) { + var element = $(event.target); + var li = element.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var datePickerClass = '.expirationDateContainer-' + this.cid + '-' + shareId; + var datePicker = $(datePickerClass); + var state = element.prop('checked'); + datePicker.toggleClass('hidden', !state); + if (!state) { + this.setExpirationDate(shareId, ''); + } else { + this.showDatePicker(event); + + } + }, + + showDatePicker: function(event) { + var element = $(event.target); + var li = element.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var expirationDatePicker = '#expirationDatePicker-' + this.cid + '-' + shareId; + var view = this; + $(expirationDatePicker).closest('div').datepicker({ + dateFormat : 'dd-mm-yy', + onSelect: + function (expireDate) { + view.setExpirationDate(shareId, expireDate); + }, + onClose: + function () { + $(expirationDatePicker).removeClass('hidden-visually'); + } + }); + + $(expirationDatePicker).addClass('hidden-visually'); + }, + + setExpirationDate: function(shareId, expireDate) { + this.model.updateShare(shareId, {expireDate: expireDate}, {}); + }, + + onMailSharePasswordProtectChange: function(event) { + var element = $(event.target); + var li = element.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; + var passwordContainer = $(passwordContainerClass); + var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); + var inputClass = '#passwordField-' + this.cid + '-' + shareId; + var passwordField = $(inputClass); + var state = element.prop('checked'); + if (!state) { + this.model.updateShare(shareId, {password: ''}); + passwordField.attr('value', ''); + passwordField.removeClass('error'); + passwordField.tooltip('hide'); + loading.addClass('hidden'); + passwordField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE); + // We first need to reset the password field before we hide it + passwordContainer.toggleClass('hidden', !state); + } else { + passwordContainer.toggleClass('hidden', !state); + passwordField = '#passwordField-' + this.cid + '-' + shareId; + this.$(passwordField).focus(); + } + }, + + onMailSharePasswordKeyUp: function(event) { + if(event.keyCode === 13) { + this.onMailSharePasswordEntered(event); + } + }, + + onMailSharePasswordEntered: function(event) { + var passwordField = $(event.target); + var li = passwordField.closest('li[data-share-id]'); + var shareId = li.data('share-id'); + var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; + var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); + if (!loading.hasClass('hidden')) { + // still in process + return; + } + + passwordField.removeClass('error'); + var password = passwordField.val(); + // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill + if(password === '' || password === PASSWORD_PLACEHOLDER || password === PASSWORD_PLACEHOLDER_MESSAGE) { + return; + } + + loading + .removeClass('hidden') + .addClass('inlineblock'); + + + this.model.updateShare(shareId, { + password: password + }, { + error: function(model, msg) { + // destroy old tooltips + passwordField.tooltip('destroy'); + loading.removeClass('inlineblock').addClass('hidden'); + passwordField.addClass('error'); + passwordField.attr('title', msg); + passwordField.tooltip({placement: 'bottom', trigger: 'manual'}); + passwordField.tooltip('show'); + }, + success: function(model, msg) { + passwordField.blur(); + passwordField.attr('value', ''); + passwordField.attr('placeholder', PASSWORD_PLACEHOLDER); + loading.removeClass('inlineblock').addClass('hidden'); + } + }); + }, + onPermissionChange: function(event) { event.preventDefault(); event.stopPropagation(); @@ -451,6 +635,34 @@ this._renderPermissionChange = shareId; }, + + onSecureDropChange: function(event) { + event.preventDefault(); + event.stopPropagation(); + var $element = $(event.target); + var $li = $element.closest('li[data-share-id]'); + var shareId = $li.data('share-id'); + + var permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE | OC.PERMISSION_READ; + if ($element.is(':checked')) { + permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE; + } + + /** disable checkboxes during save operation to avoid race conditions **/ + $li.find('input[type=checkbox]').prop('disabled', true); + var enableCb = function() { + $li.find('input[type=checkbox]').prop('disabled', false); + }; + var errorCb = function(elem, msg) { + OC.dialogs.alert(msg, t('core', 'Error while sharing')); + enableCb(); + }; + + this.model.updateShare(shareId, {permissions: permissions}, {error: errorCb, success: enableCb}); + + this._renderPermissionChange = shareId; + } + }); OC.Share.ShareDialogShareeListView = ShareDialogShareeListView; diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index ae4c07e3f4..6bb8d75b91 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -363,6 +363,10 @@ return this.get('reshare').share_type; }, + getExpireDate: function(shareIndex) { + return this._shareExpireDate(shareIndex); + }, + /** * Returns all share entries that only apply to the current item * (file/folder) @@ -449,6 +453,16 @@ return (share.permissions & permission) === permission; }, + + _shareExpireDate: function(shareIndex) { + var share = this.get('shares')[shareIndex]; + if(!_.isObject(share)) { + throw "Unknown Share"; + } + var date2 = share.expiration; + return date2; + }, + /** * @returns {boolean} */ @@ -509,6 +523,10 @@ return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE); }, + hasReadPermission: function(shareIndex) { + return this._shareHasPermission(shareIndex, OC.PERMISSION_READ); + }, + /** * @returns {boolean} */ @@ -757,7 +775,7 @@ isLinkShare: true, id: share.id, token: share.token, - password: share.share_with, + password: share.password, link: link, permissions: share.permissions, // currently expiration is only effective for link shares. diff --git a/db_structure.xml b/db_structure.xml index 545628a923..ca832b6281 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -791,6 +791,13 @@ false 255 + + password + text + + false + 255 +