summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-04-07 17:14:05 -0500
committerGitHub <noreply@github.com>2017-04-07 17:14:05 -0500
commitca9d25169dcdd2923a356e2a797d8704506a3787 (patch)
tree5d94aed1a5f79a5b0abe33d8732fc60e0a4054b3
parent9adfa60eb38f6c39ae075e1fa68037375c8789de (diff)
parentbf30090be5e3d339c9188d81a900ed2fe4bd6318 (diff)
downloadnextcloud-server-ca9d25169dcdd2923a356e2a797d8704506a3787.tar.gz
nextcloud-server-ca9d25169dcdd2923a356e2a797d8704506a3787.zip
Merge pull request #4136 from nextcloud/expire-date-for-all-shares
Unified sharing options
-rw-r--r--apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php5
-rw-r--r--apps/files_sharing/appinfo/info.xml2
-rw-r--r--apps/files_sharing/appinfo/update.php5
-rw-r--r--apps/files_sharing/lib/Capabilities.php26
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php43
-rw-r--r--apps/files_sharing/lib/Migration.php18
-rw-r--r--apps/files_sharing/tests/ApiTest.php30
-rw-r--r--apps/files_sharing/tests/CapabilitiesTest.php11
-rw-r--r--apps/files_sharing/tests/MigrationTest.php80
-rw-r--r--apps/sharebymail/appinfo/info.xml6
-rw-r--r--apps/sharebymail/js/settings-admin.js30
-rw-r--r--apps/sharebymail/lib/Settings/Admin.php67
-rw-r--r--apps/sharebymail/lib/Settings/SettingsManager.php49
-rw-r--r--apps/sharebymail/lib/ShareByMailProvider.php108
-rw-r--r--apps/sharebymail/templates/altmailpassword.php32
-rw-r--r--apps/sharebymail/templates/mailpassword.php59
-rw-r--r--apps/sharebymail/templates/settings-admin.php18
-rw-r--r--apps/sharebymail/tests/ShareByMailProviderTest.php15
-rw-r--r--core/css/apps.scss4
-rw-r--r--core/css/share.scss14
-rw-r--r--core/js/sharedialogshareelistview.js230
-rw-r--r--core/js/shareitemmodel.js20
-rw-r--r--db_structure.xml7
-rw-r--r--lib/private/Share20/DefaultShareProvider.php11
-rw-r--r--lib/private/Share20/Manager.php132
-rw-r--r--lib/private/Share20/ProviderFactory.php8
-rw-r--r--lib/public/Share/IShare.php2
-rw-r--r--tests/lib/Share20/DefaultShareProviderTest.php17
-rw-r--r--version.php2
29 files changed, 891 insertions, 160 deletions
diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
index 61f87e9ec67..233395dec9f 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 e2a08d951ac..29a137fed0b 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
<licence>AGPL</licence>
<author>Michael Gapczynski, Bjoern Schiessle</author>
<default_enable/>
- <version>1.2.0</version>
+ <version>1.4.0</version>
<types>
<filesystem/>
</types>
diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php
index ed0d7732b37..917cb7b6639 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 bfbd15c1122..ed00cdc00a6 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 78eef6c26bb..bc525b6ef82 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 605a11fd22c..49e275cbe6e 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 540905a7dc9..046ede1f83e 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -938,36 +938,6 @@ class ApiTest extends TestCase {
/**
* @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
*/
function testUpdateShareUpload() {
$node1 = $this->userFolder->get($this->folder);
diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php
index 3d59b1f6f34..79ac1854e40 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 572f64da743..708de1c0eca 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 5528f6158d9..ab50ef03694 100644
--- a/apps/sharebymail/appinfo/info.xml
+++ b/apps/sharebymail/appinfo/info.xml
@@ -5,7 +5,7 @@
<description>Share provider which allows you to share files by mail</description>
<licence>AGPL</licence>
<author>Bjoern Schiessle</author>
- <version>1.1.0</version>
+ <version>1.2.0</version>
<namespace>ShareByMail</namespace>
<category>other</category>
<dependencies>
@@ -17,6 +17,10 @@
<filesystem/>
</types>
+ <settings>
+ <admin>OCA\ShareByMail\Settings\Admin</admin>
+ </settings>
+
<activity>
<providers>
<provider>OCA\ShareByMail\Activity</provider>
diff --git a/apps/sharebymail/js/settings-admin.js b/apps/sharebymail/js/settings-admin.js
new file mode 100644
index 00000000000..7b431233032
--- /dev/null
+++ b/apps/sharebymail/js/settings-admin.js
@@ -0,0 +1,30 @@
+/**
+ * @copyright Copyright (c) 2017 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/>.
+ *
+ */
+$(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 00000000000..b6e7e5d3b4a
--- /dev/null
+++ b/apps/sharebymail/lib/Settings/Admin.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 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\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 00000000000..205b253f337
--- /dev/null
+++ b/apps/sharebymail/lib/Settings/SettingsManager.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 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\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 e09ca308f31..332f1c0cf74 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();
@@ -291,6 +299,60 @@ class ShareByMailProvider implements IShareProvider {
}
/**
+ * 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
*
* @return string
@@ -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 00000000000..f6e4c5b4158
--- /dev/null
+++ b/apps/sharebymail/templates/altmailpassword.php
@@ -0,0 +1,32 @@
+<?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 $_ */
+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");
+?>
+
+ --
+<?php p($theme->getName() . ' - ' . $theme->getSlogan()); ?>
+<?php print_unescaped("\n".$theme->getBaseUrl());
diff --git a/apps/sharebymail/templates/mailpassword.php b/apps/sharebymail/templates/mailpassword.php
new file mode 100644
index 00000000000..714a61cecd9
--- /dev/null
+++ b/apps/sharebymail/templates/mailpassword.php
@@ -0,0 +1,59 @@
+<?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 OCA\Theming\ThemingDefaults $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 colspan="2" bgcolor="<?php p($theme->getColorPrimary());?>">
+ <img src="<?php p(\OC::$server->getURLGenerator()->getAbsoluteURL(image_path('', 'logo-mail.png'))); ?>" 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
+ print_unescaped($l->t('Hey there,<br><br>%s shared <i>%s</i> with you.<br>You should have already received a separate mail with a link to access it.<br><br>It is protected with the following password: %s<br><br>', [$_['initiator'], $_['filename'], $_['password']]));
+ // 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>
diff --git a/apps/sharebymail/templates/settings-admin.php b/apps/sharebymail/templates/settings-admin.php
new file mode 100644
index 00000000000..c4e41086063
--- /dev/null
+++ b/apps/sharebymail/templates/settings-admin.php
@@ -0,0 +1,18 @@
+<?php
+/** @var array $_ */
+use OCA\Federation\TrustedServers;
+
+/** @var \OCP\IL10N $l */
+script('sharebymail', 'settings-admin');
+?>
+<div id="ncShareByMailSettings" class="section">
+ <h2><?php p($l->t('Share by mail')); ?></h2>
+ <em><?php p($l->t('Send a personalized link to a file or folder by mail.')); ?></em>
+
+ <p>
+ <input id="sendPasswordMail" type="checkbox" class="checkbox" <?php if($_['sendPasswordMail']) p('checked'); ?> />
+ <label for="sendPasswordMail"><?php p($l->t('Send password by mail')); ?></label>
+ </p>
+
+</div>
+
diff --git a/apps/sharebymail/tests/ShareByMailProviderTest.php b/apps/sharebymail/tests/ShareByMailProviderTest.php
index 65eded3eb7d..288ebb4bb45 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 0c31e5bae44..da1c5162051 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 0e6eb3ccf8b..de545955aa9 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 e46a761db6c..a9945b594e1 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 @@
'<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
'<span class="sharingOptionsGroup">' +
'{{#if editPermissionPossible}}' +
- '{{#unless isFileSharedByMail}}' +
'<span class="shareOption">' +
'<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
'<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
'</span>' +
- '{{/unless}}' +
'{{/if}}' +
'<a href="#"><span class="icon icon-more"></span></a>' +
'{{{popoverMenu}}}' +
@@ -87,6 +89,37 @@
'</li>' +
'{{/unless}}{{/if}}' +
'{{/if}}' +
+ '{{#if isMailShare}}' +
+ '{{#if hasCreatePermission}}' +
+ '<li>' +
+ '<span class="shareOption menuitem">' +
+ '<input id="secureDrop-{{cid}}-{{shareId}}" type="checkbox" name="secureDrop" class="checkbox secureDrop" {{#if secureDropMode}}checked="checked"{{/if}} data-permissions="{{readPermission}}"/>' +
+ '<label for="secureDrop-{{cid}}-{{shareId}}">{{secureDropLabel}}</label>' +
+ '</span>' +
+ '</li>' +
+ '{{/if}}' +
+ '<li>' +
+ '<span class="shareOption menuitem">' +
+ '<input id="password-{{cid}}-{{shareId}}" type="checkbox" name="password" class="password checkbox" {{#if isPasswordSet}}checked="checked"{{/if}}" />' +
+ '<label for="password-{{cid}}-{{shareId}}">{{passwordLabel}}</label>' +
+ '<div class="passwordContainer-{{cid}}-{{shareId}} {{#unless isPasswordSet}}hidden{{/unless}}">' +
+ ' <label for="passwordField-{{cid}}-{{shareId}}" class="hidden-visually" value="{{password}}">{{passwordLabel}}</label>' +
+ ' <input id="passwordField-{{cid}}-{{shareId}}" class="passwordField" type="password" placeholder="{{passwordPlaceholder}}" value="{{passwordValue}}" />' +
+ ' <span class="icon-loading-small hidden"></span>' +
+ '</div>' +
+ '</span>' +
+ '</li>' +
+ '{{/if}}' +
+ '<li>' +
+ '<span class="shareOption menuitem">' +
+ '<input id="expireDate-{{cid}}-{{shareId}}" type="checkbox" name="expirationDate" class="expireDate checkbox" {{#if hasExpireDate}}checked="checked"{{/if}}" />' +
+ '<label for="expireDate-{{cid}}-{{shareId}}">{{expireDateLabel}}</label>' +
+ '<div class="expirationDateContainer-{{cid}}-{{shareId}} {{#unless hasExpireDate}}hidden{{/unless}}">' +
+ ' <label for="expirationDatePicker-{{cid}}-{{shareId}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' +
+ ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{expireDate}}" />' +
+ '</div>' +
+ '</span>' +
+ '</li>' +
'<li>' +
'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
'</li>' +
@@ -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 ae4c07e3f4e..6bb8d75b91f 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 545628a9233..ca832b62819 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -791,6 +791,13 @@
<notnull>false</notnull>
<length>255</length>
</field>
+ <field>
+ <name>password</name>
+ <type>text</type>
+ <default></default>
+ <notnull>false</notnull>
+ <length>255</length>
+ </field>
<!-- Foreign Key users::uid -->
<!-- This is the owner of the share
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index e4ae26be13d..bf8bcc9c6d9 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -116,7 +116,7 @@ class DefaultShareProvider implements IShareProvider {
//If a password is set store it
if ($share->getPassword() !== null) {
- $qb->setValue('share_with', $qb->createNamedParameter($share->getPassword()));
+ $qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
}
//If an expiration date is set store it
@@ -202,6 +202,7 @@ class DefaultShareProvider implements IShareProvider {
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
+ ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
->execute();
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$qb = $this->dbConn->getQueryBuilder();
@@ -212,6 +213,7 @@ class DefaultShareProvider implements IShareProvider {
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
+ ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
->execute();
/*
@@ -224,6 +226,7 @@ class DefaultShareProvider implements IShareProvider {
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
+ ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
->execute();
/*
@@ -240,7 +243,7 @@ class DefaultShareProvider implements IShareProvider {
$qb = $this->dbConn->getQueryBuilder();
$qb->update('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
- ->set('share_with', $qb->createNamedParameter($share->getPassword()))
+ ->set('password', $qb->createNamedParameter($share->getPassword()))
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
@@ -646,7 +649,7 @@ class DefaultShareProvider implements IShareProvider {
// exclude shares leading to trashbin on home storages
$pathSections = explode('/', $data['path'], 2);
// FIXME: would not detect rare md5'd home storage case properly
- if ($pathSections[0] !== 'files'
+ if ($pathSections[0] !== 'files'
&& in_array(explode(':', $data['storage_string_id'], 2)[0], array('home', 'object'))) {
return false;
}
@@ -838,7 +841,7 @@ class DefaultShareProvider implements IShareProvider {
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$share->setSharedWith($data['share_with']);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
- $share->setPassword($data['share_with']);
+ $share->setPassword($data['password']);
$share->setToken($data['token']);
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index a02eb9205d0..292b07d28d5 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -266,7 +266,9 @@ class Manager implements IManager {
// Check that read permissions are always set
// Link shares are allowed to have no read permissions to allow upload to hidden folders
- if ($share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK &&
+ $noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
+ || $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
+ if (!$noReadPermissionRequired &&
($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
throw new \InvalidArgumentException('Shares need at least read permissions');
}
@@ -730,11 +732,30 @@ class Manager implements IManager {
}
}
+ $plainTextPassword = null;
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK || $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
+ // Password updated.
+ if ($share->getPassword() !== $originalShare->getPassword()) {
+ //Verify the password
+ $this->verifyPassword($share->getPassword());
+
+ // If a password is set. Hash it!
+ if ($share->getPassword() !== null) {
+ $plainTextPassword = $share->getPassword();
+ $share->setPassword($this->hasher->hash($plainTextPassword));
+ }
+ }
+ }
+
$this->pathCreateChecks($share->getNode());
// Now update the share!
$provider = $this->factory->getProviderForType($share->getShareType());
- $share = $provider->update($share);
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
+ $share = $provider->update($share, $plainTextPassword);
+ } else {
+ $share = $provider->update($share);
+ }
if ($expirationDateUpdated === true) {
\OC_Hook::emit('OCP\Share', 'post_set_expiration_date', [
@@ -915,55 +936,50 @@ class Manager implements IManager {
* Work around so we don't return expired shares but still follow
* proper pagination.
*/
- if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
- $shares2 = [];
- $today = new \DateTime();
-
- while(true) {
- $added = 0;
- foreach ($shares as $share) {
- // Check if the share is expired and if so delete it
- if ($share->getExpirationDate() !== null &&
- $share->getExpirationDate() <= $today
- ) {
- try {
- $this->deleteShare($share);
- } catch (NotFoundException $e) {
- //Ignore since this basically means the share is deleted
- }
- continue;
- }
- $added++;
- $shares2[] = $share;
- if (count($shares2) === $limit) {
- break;
- }
+ $shares2 = [];
+
+ while(true) {
+ $added = 0;
+ foreach ($shares as $share) {
+
+ try {
+ $this->checkExpireDate($share);
+ } catch (ShareNotFound $e) {
+ //Ignore since this basically means the share is deleted
+ continue;
}
+ $added++;
+ $shares2[] = $share;
+
if (count($shares2) === $limit) {
break;
}
+ }
- // If there was no limit on the select we are done
- if ($limit === -1) {
- break;
- }
+ if (count($shares2) === $limit) {
+ break;
+ }
- $offset += $added;
+ // If there was no limit on the select we are done
+ if ($limit === -1) {
+ break;
+ }
- // Fetch again $limit shares
- $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
+ $offset += $added;
- // No more shares means we are done
- if (empty($shares)) {
- break;
- }
- }
+ // Fetch again $limit shares
+ $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
- $shares = $shares2;
+ // No more shares means we are done
+ if (empty($shares)) {
+ break;
+ }
}
+ $shares = $shares2;
+
return $shares;
}
@@ -977,7 +993,18 @@ class Manager implements IManager {
return [];
}
- return $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
+ $shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
+
+ // remove all shares which are already expired
+ foreach ($shares as $key => $share) {
+ try {
+ $this->checkExpireDate($share);
+ } catch (ShareNotFound $e) {
+ unset($shares[$key]);
+ }
+ }
+
+ return $shares;
}
/**
@@ -998,13 +1025,7 @@ class Manager implements IManager {
$share = $provider->getShareById($id, $recipient);
- // Validate link shares expiration date
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
- $share->getExpirationDate() !== null &&
- $share->getExpirationDate() <= new \DateTime()) {
- $this->deleteShare($share);
- throw new ShareNotFound();
- }
+ $this->checkExpireDate($share);
return $share;
}
@@ -1066,11 +1087,7 @@ class Manager implements IManager {
throw new ShareNotFound();
}
- if ($share->getExpirationDate() !== null &&
- $share->getExpirationDate() <= new \DateTime()) {
- $this->deleteShare($share);
- throw new ShareNotFound();
- }
+ $this->checkExpireDate($share);
/*
* Reduce the permissions for link shares if public upload is not enabled
@@ -1083,6 +1100,15 @@ class Manager implements IManager {
return $share;
}
+ protected function checkExpireDate($share) {
+ if ($share->getExpirationDate() !== null &&
+ $share->getExpirationDate() <= new \DateTime()) {
+ $this->deleteShare($share);
+ throw new ShareNotFound();
+ }
+
+ }
+
/**
* Verify the password of a public share
*
@@ -1091,7 +1117,9 @@ class Manager implements IManager {
* @return bool
*/
public function checkPassword(\OCP\Share\IShare $share, $password) {
- if ($share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK) {
+ $passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
+ || $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
+ if (!$passwordProtected) {
//TODO maybe exception?
return false;
}
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 1a39cfbf337..b411f42b262 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -28,6 +28,7 @@ use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\FederatedFileSharing\Notifications;
use OCA\FederatedFileSharing\TokenHandler;
+use OCA\ShareByMail\Settings\SettingsManager;
use OCA\ShareByMail\ShareByMailProvider;
use OCP\Share\IProviderFactory;
use OC\Share20\Exception\ProviderException;
@@ -149,18 +150,19 @@ class ProviderFactory implements IProviderFactory {
return null;
}
- $l = $this->serverContainer->getL10N('sharebymail');
+ $settingsManager = new SettingsManager($this->serverContainer->getConfig());
$this->shareByMailProvider = new ShareByMailProvider(
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getSecureRandom(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getLazyRootFolder(),
- $l,
+ $this->serverContainer->getL10N('sharebymail'),
$this->serverContainer->getLogger(),
$this->serverContainer->getMailer(),
$this->serverContainer->getURLGenerator(),
- $this->serverContainer->getActivityManager()
+ $this->serverContainer->getActivityManager(),
+ $settingsManager
);
}
diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php
index 5b552b51c3c..8deec573c1b 100644
--- a/lib/public/Share/IShare.php
+++ b/lib/public/Share/IShare.php
@@ -189,7 +189,7 @@ interface IShare {
/**
* Set the expiration date
*
- * @param \DateTime $expireDate
+ * @param null|\DateTime $expireDate
* @return \OCP\Share\IShare The modified object
* @since 9.0.0
*/
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php
index a1e78313558..fce5668440d 100644
--- a/tests/lib/Share20/DefaultShareProviderTest.php
+++ b/tests/lib/Share20/DefaultShareProviderTest.php
@@ -338,7 +338,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$qb->insert('share')
->values([
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
- 'share_with' => $qb->expr()->literal('sharedWith'),
+ 'password' => $qb->expr()->literal('password'),
'uid_owner' => $qb->expr()->literal('shareOwner'),
'uid_initiator' => $qb->expr()->literal('sharedBy'),
'item_type' => $qb->expr()->literal('file'),
@@ -366,7 +366,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
- $this->assertEquals('sharedWith', $share->getPassword());
+ $this->assertNull($share->getSharedWith());
+ $this->assertEquals('password', $share->getPassword());
$this->assertEquals('sharedBy', $share->getSharedBy());
$this->assertEquals('shareOwner', $share->getShareOwner());
$this->assertEquals($ownerPath, $share->getNode());
@@ -752,7 +753,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$qb->insert('share')
->values([
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
- 'share_with' => $qb->expr()->literal('password'),
+ 'password' => $qb->expr()->literal('password'),
'uid_owner' => $qb->expr()->literal('shareOwner'),
'uid_initiator' => $qb->expr()->literal('sharedBy'),
'item_type' => $qb->expr()->literal('file'),
@@ -814,7 +815,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
['home::shareOwner', 'files/test.txt', 'files/test2.txt'],
// regular file on external storage
['smb::whatever', 'files/test.txt', 'files/test2.txt'],
- // regular file on external storage in trashbin-like folder,
+ // regular file on external storage in trashbin-like folder,
['smb::whatever', 'files_trashbin/files/test.txt', 'files_trashbin/files/test2.txt'],
];
}
@@ -2353,9 +2354,11 @@ class DefaultShareProviderTest extends \Test\TestCase {
$rootFolder
);
- $u1 = $userManager->createUser('testShare1', 'test');
- $u2 = $userManager->createUser('testShare2', 'test');
- $u3 = $userManager->createUser('testShare3', 'test');
+ $password = md5(time());
+
+ $u1 = $userManager->createUser('testShare1', $password);
+ $u2 = $userManager->createUser('testShare2', $password);
+ $u3 = $userManager->createUser('testShare3', $password);
$g1 = $groupManager->createGroup('group1');
diff --git a/version.php b/version.php
index a556a9f7299..0d1d327cb7f 100644
--- a/version.php
+++ b/version.php
@@ -26,7 +26,7 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = array(12, 0, 0, 13);
+$OC_Version = array(12, 0, 0, 14);
// The human readable string
$OC_VersionString = '12.0 alpha';