Merge pull request #4136 from nextcloud/expire-date-for-all-shares
Unified sharing options
This commit is contained in:
commit
ca9d25169d
29 changed files with 893 additions and 162 deletions
|
@ -67,7 +67,7 @@ class RequestHandlerControllerTest extends TestCase {
|
||||||
|
|
||||||
/** @var \OCA\FederatedFileSharing\AddressHandler|\PHPUnit_Framework_MockObject_MockObject */
|
/** @var \OCA\FederatedFileSharing\AddressHandler|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $addressHandler;
|
private $addressHandler;
|
||||||
|
|
||||||
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
|
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $userManager;
|
private $userManager;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ class RequestHandlerControllerTest extends TestCase {
|
||||||
$this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock();
|
$this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock();
|
||||||
|
|
||||||
$this->cloudIdManager = new CloudIdManager();
|
$this->cloudIdManager = new CloudIdManager();
|
||||||
|
|
||||||
$this->registerHttpHelper($httpHelperMock);
|
$this->registerHttpHelper($httpHelperMock);
|
||||||
|
|
||||||
$this->s2s = new RequestHandlerController(
|
$this->s2s = new RequestHandlerController(
|
||||||
|
@ -384,6 +384,7 @@ class RequestHandlerControllerTest extends TestCase {
|
||||||
'parent' => null,
|
'parent' => null,
|
||||||
'accepted' => '0',
|
'accepted' => '0',
|
||||||
'expiration' => null,
|
'expiration' => null,
|
||||||
|
'password' => null,
|
||||||
'mail_send' => '0'
|
'mail_send' => '0'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ Turning the feature off removes shared files and folders on the server for all s
|
||||||
<licence>AGPL</licence>
|
<licence>AGPL</licence>
|
||||||
<author>Michael Gapczynski, Bjoern Schiessle</author>
|
<author>Michael Gapczynski, Bjoern Schiessle</author>
|
||||||
<default_enable/>
|
<default_enable/>
|
||||||
<version>1.2.0</version>
|
<version>1.4.0</version>
|
||||||
<types>
|
<types>
|
||||||
<filesystem/>
|
<filesystem/>
|
||||||
</types>
|
</types>
|
||||||
|
|
|
@ -34,3 +34,8 @@ if (version_compare($installedVersion, '0.9.1', '<')) {
|
||||||
if (version_compare($installedVersion, '1.1.1', '<')) {
|
if (version_compare($installedVersion, '1.1.1', '<')) {
|
||||||
$m = new Migration(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig());
|
$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();
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
namespace OCA\Files_Sharing;
|
namespace OCA\Files_Sharing;
|
||||||
|
|
||||||
|
use OCP\App\IAppManager;
|
||||||
use OCP\Capabilities\ICapability;
|
use OCP\Capabilities\ICapability;
|
||||||
use \OCP\IConfig;
|
use \OCP\IConfig;
|
||||||
|
|
||||||
|
@ -34,8 +35,12 @@ class Capabilities implements ICapability {
|
||||||
/** @var IConfig */
|
/** @var IConfig */
|
||||||
private $config;
|
private $config;
|
||||||
|
|
||||||
public function __construct(IConfig $config) {
|
/** @var IAppManager */
|
||||||
|
private $appManager;
|
||||||
|
|
||||||
|
public function __construct(IConfig $config, IAppManager $appManager) {
|
||||||
$this->config = $config;
|
$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['resharing'] = $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes') === 'yes';
|
||||||
|
|
||||||
$res['user']['send_mail'] = false;
|
$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_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
|
//Federated sharing
|
||||||
$res['federation'] = [
|
$res['federation'] = [
|
||||||
'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes',
|
'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 [
|
return [
|
||||||
'files_sharing' => $res,
|
'files_sharing' => $res,
|
||||||
];
|
];
|
||||||
|
|
|
@ -163,6 +163,11 @@ class ShareAPIController extends OCSController {
|
||||||
$result['file_parent'] = $node->getParent()->getId();
|
$result['file_parent'] = $node->getParent()->getId();
|
||||||
$result['file_target'] = $share->getTarget();
|
$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) {
|
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
|
||||||
$sharedWith = $this->userManager->get($share->getSharedWith());
|
$sharedWith = $this->userManager->get($share->getSharedWith());
|
||||||
$result['share_with'] = $share->getSharedWith();
|
$result['share_with'] = $share->getSharedWith();
|
||||||
|
@ -179,17 +184,13 @@ class ShareAPIController extends OCSController {
|
||||||
$result['token'] = $share->getToken();
|
$result['token'] = $share->getToken();
|
||||||
$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['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) {
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
|
||||||
$result['share_with'] = $share->getSharedWith();
|
$result['share_with'] = $share->getSharedWith();
|
||||||
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
|
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
|
||||||
$result['token'] = $share->getToken();
|
$result['token'] = $share->getToken();
|
||||||
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
|
||||||
$result['share_with'] = $share->getSharedWith();
|
$result['share_with'] = $share->getSharedWith();
|
||||||
|
$result['password'] = $share->getPassword();
|
||||||
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
|
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
|
||||||
$result['token'] = $share->getToken();
|
$result['token'] = $share->getToken();
|
||||||
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
|
} 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'));
|
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
|
* expirationdate, password and publicUpload only make sense for link shares
|
||||||
*/
|
*/
|
||||||
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
|
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;
|
$newPermissions = null;
|
||||||
if ($publicUpload === 'true') {
|
if ($publicUpload === 'true') {
|
||||||
|
@ -740,13 +742,30 @@ class ShareAPIController extends OCSController {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// For other shares only permissions is valid.
|
if ($permissions !== null) {
|
||||||
if ($permissions === null) {
|
|
||||||
throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
|
|
||||||
} else {
|
|
||||||
$permissions = (int)$permissions;
|
$permissions = (int)$permissions;
|
||||||
$share->setPermissions($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) {
|
if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
|
||||||
|
|
|
@ -123,6 +123,24 @@ class Migration {
|
||||||
$this->config->deleteAppValue('core', 'shareapi_allow_public_notification');
|
$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
|
* find the owner of a re-shared file/folder
|
||||||
*
|
*
|
||||||
|
|
|
@ -936,36 +936,6 @@ class ApiTest extends TestCase {
|
||||||
$this->shareManager->deleteShare($share2);
|
$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
|
* @medium
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace OCA\Files_Sharing\Tests;
|
||||||
|
|
||||||
use OCA\Files_Sharing\Capabilities;
|
use OCA\Files_Sharing\Capabilities;
|
||||||
use OCA\Files_Sharing\Tests\TestCase;
|
use OCA\Files_Sharing\Tests\TestCase;
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CapabilitiesTest
|
* 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
|
* function. Then obtain the capabilities and extract the first few
|
||||||
* levels in the array
|
* levels in the array
|
||||||
*
|
*
|
||||||
|
@ -54,9 +55,11 @@ class CapabilitiesTest extends \Test\TestCase {
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
private function getResults(array $map) {
|
private function getResults(array $map) {
|
||||||
$stub = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock();
|
$config = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock();
|
||||||
$stub->method('getAppValue')->will($this->returnValueMap($map));
|
$config->method('getAppValue')->will($this->returnValueMap($map));
|
||||||
$cap = new Capabilities($stub);
|
$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());
|
$result = $this->getFilesSharingPart($cap->getCapabilities());
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace OCA\Files_Sharing\Tests;
|
||||||
|
|
||||||
|
|
||||||
use OCA\Files_Sharing\Migration;
|
use OCA\Files_Sharing\Migration;
|
||||||
|
use OCP\Share;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class MigrationTest
|
* Class MigrationTest
|
||||||
|
@ -87,7 +88,7 @@ class MigrationTest extends TestCase {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// shared contact, shouldn't be modified
|
// 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('share_with', 'user1')
|
||||||
->setParameter('uid_owner', 'owner1')
|
->setParameter('uid_owner', 'owner1')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -103,7 +104,7 @@ class MigrationTest extends TestCase {
|
||||||
$query->execute()
|
$query->execute()
|
||||||
);
|
);
|
||||||
// shared calendar, shouldn't be modified
|
// 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('share_with', 'user1')
|
||||||
->setParameter('uid_owner', 'owner1')
|
->setParameter('uid_owner', 'owner1')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -119,7 +120,7 @@ class MigrationTest extends TestCase {
|
||||||
$query->execute()
|
$query->execute()
|
||||||
);
|
);
|
||||||
// single user share, shouldn't be modified
|
// 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('share_with', 'user1')
|
||||||
->setParameter('uid_owner', 'owner1')
|
->setParameter('uid_owner', 'owner1')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -135,7 +136,7 @@ class MigrationTest extends TestCase {
|
||||||
$query->execute()
|
$query->execute()
|
||||||
);
|
);
|
||||||
// single group share, shouldn't be modified
|
// 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('share_with', 'group1')
|
||||||
->setParameter('uid_owner', 'owner1')
|
->setParameter('uid_owner', 'owner1')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -168,7 +169,7 @@ class MigrationTest extends TestCase {
|
||||||
$query->execute()
|
$query->execute()
|
||||||
);
|
);
|
||||||
// first user share, shouldn't be modified
|
// 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('share_with', 'user1')
|
||||||
->setParameter('uid_owner', 'owner2')
|
->setParameter('uid_owner', 'owner2')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -185,7 +186,7 @@ class MigrationTest extends TestCase {
|
||||||
);
|
);
|
||||||
$parent = $query->getLastInsertId();
|
$parent = $query->getLastInsertId();
|
||||||
// first re-share, should be attached to the first user share after migration
|
// 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('share_with', 'user2')
|
||||||
->setParameter('uid_owner', 'user1')
|
->setParameter('uid_owner', 'user1')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -202,7 +203,7 @@ class MigrationTest extends TestCase {
|
||||||
);
|
);
|
||||||
$parent = $query->getLastInsertId();
|
$parent = $query->getLastInsertId();
|
||||||
// second re-share, should be attached to the first user share after migration
|
// 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('share_with', 'user3')
|
||||||
->setParameter('uid_owner', 'user2')
|
->setParameter('uid_owner', 'user2')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -219,7 +220,7 @@ class MigrationTest extends TestCase {
|
||||||
);
|
);
|
||||||
$parent = $query->getLastInsertId();
|
$parent = $query->getLastInsertId();
|
||||||
// third re-share, should be attached to the first user share after migration
|
// 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('share_with', 'user@server.com')
|
||||||
->setParameter('uid_owner', 'user3')
|
->setParameter('uid_owner', 'user3')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -236,7 +237,7 @@ class MigrationTest extends TestCase {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Link reshare should keep its parent
|
// 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('share_with', null)
|
||||||
->setParameter('uid_owner', 'user3')
|
->setParameter('uid_owner', 'user3')
|
||||||
->setParameter('uid_initiator', '')
|
->setParameter('uid_initiator', '')
|
||||||
|
@ -317,7 +318,7 @@ class MigrationTest extends TestCase {
|
||||||
'stime' => $query->createParameter('stime'),
|
'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('share_with', 'user'.($i+1))
|
||||||
->setParameter('uid_owner', 'user'.($i))
|
->setParameter('uid_owner', 'user'.($i))
|
||||||
->setParameter('uid_initiator', null)
|
->setParameter('uid_initiator', null)
|
||||||
|
@ -377,4 +378,63 @@ class MigrationTest extends TestCase {
|
||||||
$this->config->getAppValue('core', 'shareapi_setting1', null)
|
$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']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<description>Share provider which allows you to share files by mail</description>
|
<description>Share provider which allows you to share files by mail</description>
|
||||||
<licence>AGPL</licence>
|
<licence>AGPL</licence>
|
||||||
<author>Bjoern Schiessle</author>
|
<author>Bjoern Schiessle</author>
|
||||||
<version>1.1.0</version>
|
<version>1.2.0</version>
|
||||||
<namespace>ShareByMail</namespace>
|
<namespace>ShareByMail</namespace>
|
||||||
<category>other</category>
|
<category>other</category>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -17,6 +17,10 @@
|
||||||
<filesystem/>
|
<filesystem/>
|
||||||
</types>
|
</types>
|
||||||
|
|
||||||
|
<settings>
|
||||||
|
<admin>OCA\ShareByMail\Settings\Admin</admin>
|
||||||
|
</settings>
|
||||||
|
|
||||||
<activity>
|
<activity>
|
||||||
<providers>
|
<providers>
|
||||||
<provider>OCA\ShareByMail\Activity</provider>
|
<provider>OCA\ShareByMail\Activity</provider>
|
||||||
|
|
30
apps/sharebymail/js/settings-admin.js
Normal file
30
apps/sharebymail/js/settings-admin.js
Normal file
|
@ -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);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
67
apps/sharebymail/lib/Settings/Admin.php
Normal file
67
apps/sharebymail/lib/Settings/Admin.php
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
apps/sharebymail/lib/Settings/SettingsManager.php
Normal file
49
apps/sharebymail/lib/Settings/SettingsManager.php
Normal file
|
@ -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';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,7 +23,9 @@ namespace OCA\ShareByMail;
|
||||||
|
|
||||||
use OC\HintException;
|
use OC\HintException;
|
||||||
use OC\Share20\Exception\InvalidShare;
|
use OC\Share20\Exception\InvalidShare;
|
||||||
|
use OCA\ShareByMail\Settings\SettingsManager;
|
||||||
use OCP\Activity\IManager;
|
use OCP\Activity\IManager;
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
use OCP\Files\Node;
|
use OCP\Files\Node;
|
||||||
|
@ -75,13 +77,16 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
/** @var IManager */
|
/** @var IManager */
|
||||||
private $activityManager;
|
private $activityManager;
|
||||||
|
|
||||||
|
/** @var SettingsManager */
|
||||||
|
private $settingsManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the identifier of this provider.
|
* Return the identifier of this provider.
|
||||||
*
|
*
|
||||||
* @return string Containing only [a-zA-Z0-9]
|
* @return string Containing only [a-zA-Z0-9]
|
||||||
*/
|
*/
|
||||||
public function identifier() {
|
public function identifier() {
|
||||||
return 'ocShareByMail';
|
return 'ocMailShare';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,6 +101,7 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
* @param IMailer $mailer
|
* @param IMailer $mailer
|
||||||
* @param IURLGenerator $urlGenerator
|
* @param IURLGenerator $urlGenerator
|
||||||
* @param IManager $activityManager
|
* @param IManager $activityManager
|
||||||
|
* @param SettingsManager $settingsManager
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IDBConnection $connection,
|
IDBConnection $connection,
|
||||||
|
@ -106,7 +112,8 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
ILogger $logger,
|
ILogger $logger,
|
||||||
IMailer $mailer,
|
IMailer $mailer,
|
||||||
IURLGenerator $urlGenerator,
|
IURLGenerator $urlGenerator,
|
||||||
IManager $activityManager
|
IManager $activityManager,
|
||||||
|
SettingsManager $settingsManager
|
||||||
) {
|
) {
|
||||||
$this->dbConnection = $connection;
|
$this->dbConnection = $connection;
|
||||||
$this->secureRandom = $secureRandom;
|
$this->secureRandom = $secureRandom;
|
||||||
|
@ -117,6 +124,7 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
$this->mailer = $mailer;
|
$this->mailer = $mailer;
|
||||||
$this->urlGenerator = $urlGenerator;
|
$this->urlGenerator = $urlGenerator;
|
||||||
$this->activityManager = $activityManager;
|
$this->activityManager = $activityManager;
|
||||||
|
$this->settingsManager = $settingsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,10 +283,10 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
protected function createMailBody($template, $filename, $link, $owner, $initiator) {
|
protected function createMailBody($template, $filename, $link, $owner, $initiator) {
|
||||||
|
|
||||||
$mailBodyTemplate = new Template('sharebymail', $template, '');
|
$mailBodyTemplate = new Template('sharebymail', $template, '');
|
||||||
$mailBodyTemplate->assign ('filename', $filename);
|
$mailBodyTemplate->assign ('filename', \OCP\Util::sanitizeHTML($filename));
|
||||||
$mailBodyTemplate->assign ('link', $link);
|
$mailBodyTemplate->assign ('link', $link);
|
||||||
$mailBodyTemplate->assign ('owner', $owner);
|
$mailBodyTemplate->assign ('owner', \OCP\Util::sanitizeHTML($owner));
|
||||||
$mailBodyTemplate->assign ('initiator', $initiator);
|
$mailBodyTemplate->assign ('initiator', \OCP\Util::sanitizeHTML($initiator));
|
||||||
$mailBodyTemplate->assign ('onBehalfOf', $initiator !== $owner);
|
$mailBodyTemplate->assign ('onBehalfOf', $initiator !== $owner);
|
||||||
$mailBody = $mailBodyTemplate->fetchPage();
|
$mailBody = $mailBodyTemplate->fetchPage();
|
||||||
|
|
||||||
|
@ -290,6 +298,60 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
$this->l->t('Failed to create the E-mail'));
|
$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
|
* generate share token
|
||||||
*
|
*
|
||||||
|
@ -368,19 +430,31 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
* Update a share
|
* Update a share
|
||||||
*
|
*
|
||||||
* @param IShare $share
|
* @param IShare $share
|
||||||
|
* @param string|null $plainTextPassword
|
||||||
* @return IShare The share object
|
* @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 = $this->dbConnection->getQueryBuilder();
|
||||||
$qb->update('share')
|
$qb->update('share')
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
|
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
|
||||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||||
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
|
->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
|
||||||
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
||||||
->execute();
|
->set('password', $qb->createNamedParameter($share->getPassword()))
|
||||||
|
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||||
|
->execute();
|
||||||
|
|
||||||
return $share;
|
return $share;
|
||||||
}
|
}
|
||||||
|
@ -625,6 +699,7 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
$shareTime->setTimestamp((int)$data['stime']);
|
$shareTime->setTimestamp((int)$data['stime']);
|
||||||
$share->setShareTime($shareTime);
|
$share->setShareTime($shareTime);
|
||||||
$share->setSharedWith($data['share_with']);
|
$share->setSharedWith($data['share_with']);
|
||||||
|
$share->setPassword($data['password']);
|
||||||
|
|
||||||
if ($data['uid_initiator'] !== null) {
|
if ($data['uid_initiator'] !== null) {
|
||||||
$share->setShareOwner($data['uid_owner']);
|
$share->setShareOwner($data['uid_owner']);
|
||||||
|
@ -638,6 +713,13 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
$share->setShareOwner($owner->getUID());
|
$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->setNodeId((int)$data['file_source']);
|
||||||
$share->setNodeType($data['item_type']);
|
$share->setNodeType($data['item_type']);
|
||||||
|
|
||||||
|
|
32
apps/sharebymail/templates/altmailpassword.php
Normal file
32
apps/sharebymail/templates/altmailpassword.php
Normal file
|
@ -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());
|
59
apps/sharebymail/templates/mailpassword.php
Normal file
59
apps/sharebymail/templates/mailpassword.php
Normal file
|
@ -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"> </td></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="20px"> </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"> </td></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="20px"> </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"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
18
apps/sharebymail/templates/settings-admin.php
Normal file
18
apps/sharebymail/templates/settings-admin.php
Normal file
|
@ -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>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
namespace OCA\ShareByMail\Tests;
|
namespace OCA\ShareByMail\Tests;
|
||||||
|
|
||||||
|
|
||||||
use OC\HintException;
|
use OCA\ShareByMail\Settings\SettingsManager;
|
||||||
use OCA\ShareByMail\ShareByMailProvider;
|
use OCA\ShareByMail\ShareByMailProvider;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
|
@ -33,7 +33,6 @@ use OCP\IURLGenerator;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
use OCP\Mail\IMailer;
|
use OCP\Mail\IMailer;
|
||||||
use OCP\Security\ISecureRandom;
|
use OCP\Security\ISecureRandom;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
|
||||||
use OCP\Share\IManager;
|
use OCP\Share\IManager;
|
||||||
use OCP\Share\IShare;
|
use OCP\Share\IShare;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
|
@ -79,6 +78,9 @@ class ShareByMailProviderTest extends TestCase {
|
||||||
/** @var \OCP\Activity\IManager | \PHPUnit_Framework_MockObject_MockObject */
|
/** @var \OCP\Activity\IManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $activityManager;
|
private $activityManager;
|
||||||
|
|
||||||
|
/** @var SettingsManager | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $settingsManager;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
|
@ -98,6 +100,7 @@ class ShareByMailProviderTest extends TestCase {
|
||||||
$this->urlGenerator = $this->getMockBuilder('\OCP\IUrlGenerator')->getMock();
|
$this->urlGenerator = $this->getMockBuilder('\OCP\IUrlGenerator')->getMock();
|
||||||
$this->share = $this->getMockBuilder('\OCP\Share\IShare')->getMock();
|
$this->share = $this->getMockBuilder('\OCP\Share\IShare')->getMock();
|
||||||
$this->activityManager = $this->getMockBuilder('OCP\Activity\IManager')->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);
|
$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +124,8 @@ class ShareByMailProviderTest extends TestCase {
|
||||||
$this->logger,
|
$this->logger,
|
||||||
$this->mailer,
|
$this->mailer,
|
||||||
$this->urlGenerator,
|
$this->urlGenerator,
|
||||||
$this->activityManager
|
$this->activityManager,
|
||||||
|
$this->settingsManager
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -139,7 +143,8 @@ class ShareByMailProviderTest extends TestCase {
|
||||||
$this->logger,
|
$this->logger,
|
||||||
$this->mailer,
|
$this->mailer,
|
||||||
$this->urlGenerator,
|
$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('getPermissions')->willReturn($permissions + 1);
|
||||||
$this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner);
|
$this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner);
|
||||||
$this->share->expects($this->once())->method('getSharedBy')->willReturn($sharedBy);
|
$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,
|
$this->assertSame($this->share,
|
||||||
$instance->update($this->share)
|
$instance->update($this->share)
|
||||||
|
|
|
@ -477,7 +477,7 @@ kbd {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 42px;
|
padding-left: 42px;
|
||||||
font-weight: normal;
|
font-weight: 300;
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: $color-main-background;
|
background-color: $color-main-background;
|
||||||
|
@ -667,7 +667,7 @@ kbd {
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-weight: inherit;
|
font-weight: 300;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
/* prevent .action class to break the design */
|
/* prevent .action class to break the design */
|
||||||
&.action {
|
&.action {
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
.shareOption {
|
.shareOption {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
.unshare img,
|
.unshare img,
|
||||||
.showCruds img {
|
.showCruds img {
|
||||||
|
@ -184,3 +185,16 @@ a {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
color: rgba($color-main-text, .4);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
/* globals Handlebars */
|
/* globals Handlebars */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
var PASSWORD_PLACEHOLDER = '**********';
|
||||||
|
var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the mail share');
|
||||||
|
|
||||||
if (!OC.Share) {
|
if (!OC.Share) {
|
||||||
OC.Share = {};
|
OC.Share = {};
|
||||||
}
|
}
|
||||||
|
@ -25,12 +29,10 @@
|
||||||
'<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
|
'<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
|
||||||
'<span class="sharingOptionsGroup">' +
|
'<span class="sharingOptionsGroup">' +
|
||||||
'{{#if editPermissionPossible}}' +
|
'{{#if editPermissionPossible}}' +
|
||||||
'{{#unless isFileSharedByMail}}' +
|
|
||||||
'<span class="shareOption">' +
|
'<span class="shareOption">' +
|
||||||
'<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
|
'<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
|
||||||
'<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
|
'<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
|
||||||
'</span>' +
|
'</span>' +
|
||||||
'{{/unless}}' +
|
|
||||||
'{{/if}}' +
|
'{{/if}}' +
|
||||||
'<a href="#"><span class="icon icon-more"></span></a>' +
|
'<a href="#"><span class="icon icon-more"></span></a>' +
|
||||||
'{{{popoverMenu}}}' +
|
'{{{popoverMenu}}}' +
|
||||||
|
@ -87,6 +89,37 @@
|
||||||
'</li>' +
|
'</li>' +
|
||||||
'{{/unless}}{{/if}}' +
|
'{{/unless}}{{/if}}' +
|
||||||
'{{/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>' +
|
'<li>' +
|
||||||
'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
|
'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
|
@ -125,6 +158,13 @@
|
||||||
'click .unshare': 'onUnshare',
|
'click .unshare': 'onUnshare',
|
||||||
'click .icon-more': 'onToggleMenu',
|
'click .icon-more': 'onToggleMenu',
|
||||||
'click .permissions': 'onPermissionChange',
|
'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) {
|
initialize: function(options) {
|
||||||
|
@ -171,6 +211,11 @@
|
||||||
shareWithTitle = shareWith;
|
shareWithTitle = shareWith;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var share = this.model.get('shares')[shareIndex];
|
||||||
|
var password = share.password;
|
||||||
|
var hasPassword = password !== null && password !== '';
|
||||||
|
|
||||||
|
|
||||||
return _.extend(hasPermissionOverride, {
|
return _.extend(hasPermissionOverride, {
|
||||||
cid: this.cid,
|
cid: this.cid,
|
||||||
hasSharePermission: this.model.hasSharePermission(shareIndex),
|
hasSharePermission: this.model.hasSharePermission(shareIndex),
|
||||||
|
@ -187,19 +232,27 @@
|
||||||
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
|
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
|
||||||
isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
|
isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
|
||||||
isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE,
|
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() {
|
getShareProperties: function() {
|
||||||
return {
|
return {
|
||||||
unshareLabel: t('core', 'Unshare'),
|
unshareLabel: t('core', 'Unshare'),
|
||||||
canShareLabel: t('core', 'can reshare'),
|
canShareLabel: t('core', 'Can reshare'),
|
||||||
canEditLabel: t('core', 'can edit'),
|
canEditLabel: t('core', 'Can edit'),
|
||||||
createPermissionLabel: t('core', 'can create'),
|
createPermissionLabel: t('core', 'Can create'),
|
||||||
updatePermissionLabel: t('core', 'can change'),
|
updatePermissionLabel: t('core', 'Can change'),
|
||||||
deletePermissionLabel: t('core', 'can delete'),
|
deletePermissionLabel: t('core', 'Can delete'),
|
||||||
crudsLabel: t('core', 'access control'),
|
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'),
|
triangleSImage: OC.imagePath('core', 'actions/triangle-s'),
|
||||||
isResharingAllowed: this.configModel.get('isResharingAllowed'),
|
isResharingAllowed: this.configModel.get('isResharingAllowed'),
|
||||||
sharePermissionPossible: this.model.sharePermissionPossible(),
|
sharePermissionPossible: this.model.sharePermissionPossible(),
|
||||||
|
@ -211,6 +264,7 @@
|
||||||
createPermission: OC.PERMISSION_CREATE,
|
createPermission: OC.PERMISSION_CREATE,
|
||||||
updatePermission: OC.PERMISSION_UPDATE,
|
updatePermission: OC.PERMISSION_UPDATE,
|
||||||
deletePermission: OC.PERMISSION_DELETE,
|
deletePermission: OC.PERMISSION_DELETE,
|
||||||
|
readPermission: OC.PERMISSION_READ,
|
||||||
isFolder: this.model.isFolder()
|
isFolder: this.model.isFolder()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -313,6 +367,19 @@
|
||||||
this.$('.popovermenu').on('afterHide', function() {
|
this.$('.popovermenu').on('afterHide', function() {
|
||||||
_this._menuOpen = false;
|
_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) {
|
if (this._menuOpen != false) {
|
||||||
// Open menu again if it was opened before
|
// Open menu again if it was opened before
|
||||||
var shareId = parseInt(this._menuOpen, 10);
|
var shareId = parseInt(this._menuOpen, 10);
|
||||||
|
@ -401,6 +468,123 @@
|
||||||
this._menuOpen = $li.data('share-id');
|
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) {
|
onPermissionChange: function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -451,6 +635,34 @@
|
||||||
|
|
||||||
this._renderPermissionChange = shareId;
|
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;
|
OC.Share.ShareDialogShareeListView = ShareDialogShareeListView;
|
||||||
|
|
|
@ -363,6 +363,10 @@
|
||||||
return this.get('reshare').share_type;
|
return this.get('reshare').share_type;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getExpireDate: function(shareIndex) {
|
||||||
|
return this._shareExpireDate(shareIndex);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all share entries that only apply to the current item
|
* Returns all share entries that only apply to the current item
|
||||||
* (file/folder)
|
* (file/folder)
|
||||||
|
@ -449,6 +453,16 @@
|
||||||
return (share.permissions & permission) === permission;
|
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}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
|
@ -509,6 +523,10 @@
|
||||||
return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE);
|
return this._shareHasPermission(shareIndex, OC.PERMISSION_DELETE);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hasReadPermission: function(shareIndex) {
|
||||||
|
return this._shareHasPermission(shareIndex, OC.PERMISSION_READ);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
|
@ -757,7 +775,7 @@
|
||||||
isLinkShare: true,
|
isLinkShare: true,
|
||||||
id: share.id,
|
id: share.id,
|
||||||
token: share.token,
|
token: share.token,
|
||||||
password: share.share_with,
|
password: share.password,
|
||||||
link: link,
|
link: link,
|
||||||
permissions: share.permissions,
|
permissions: share.permissions,
|
||||||
// currently expiration is only effective for link shares.
|
// currently expiration is only effective for link shares.
|
||||||
|
|
|
@ -791,6 +791,13 @@
|
||||||
<notnull>false</notnull>
|
<notnull>false</notnull>
|
||||||
<length>255</length>
|
<length>255</length>
|
||||||
</field>
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>password</name>
|
||||||
|
<type>text</type>
|
||||||
|
<default></default>
|
||||||
|
<notnull>false</notnull>
|
||||||
|
<length>255</length>
|
||||||
|
</field>
|
||||||
|
|
||||||
<!-- Foreign Key users::uid -->
|
<!-- Foreign Key users::uid -->
|
||||||
<!-- This is the owner of the share
|
<!-- This is the owner of the share
|
||||||
|
|
|
@ -116,7 +116,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
|
|
||||||
//If a password is set store it
|
//If a password is set store it
|
||||||
if ($share->getPassword() !== null) {
|
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
|
//If an expiration date is set store it
|
||||||
|
@ -202,6 +202,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
|
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||||
->execute();
|
->execute();
|
||||||
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||||
$qb = $this->dbConn->getQueryBuilder();
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
|
@ -212,6 +213,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
|
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -224,6 +226,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
||||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||||
|
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -240,7 +243,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
$qb = $this->dbConn->getQueryBuilder();
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
$qb->update('share')
|
$qb->update('share')
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
|
->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_owner', $qb->createNamedParameter($share->getShareOwner()))
|
||||||
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
|
||||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||||
|
@ -646,7 +649,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
// exclude shares leading to trashbin on home storages
|
// exclude shares leading to trashbin on home storages
|
||||||
$pathSections = explode('/', $data['path'], 2);
|
$pathSections = explode('/', $data['path'], 2);
|
||||||
// FIXME: would not detect rare md5'd home storage case properly
|
// 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'))) {
|
&& in_array(explode(':', $data['storage_string_id'], 2)[0], array('home', 'object'))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -838,7 +841,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||||
$share->setSharedWith($data['share_with']);
|
$share->setSharedWith($data['share_with']);
|
||||||
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
|
||||||
$share->setPassword($data['share_with']);
|
$share->setPassword($data['password']);
|
||||||
$share->setToken($data['token']);
|
$share->setToken($data['token']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,9 @@ class Manager implements IManager {
|
||||||
|
|
||||||
// Check that read permissions are always set
|
// Check that read permissions are always set
|
||||||
// Link shares are allowed to have no read permissions to allow upload to hidden folders
|
// 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) {
|
($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
|
||||||
throw new \InvalidArgumentException('Shares need at least read permissions');
|
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());
|
$this->pathCreateChecks($share->getNode());
|
||||||
|
|
||||||
// Now update the share!
|
// Now update the share!
|
||||||
$provider = $this->factory->getProviderForType($share->getShareType());
|
$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) {
|
if ($expirationDateUpdated === true) {
|
||||||
\OC_Hook::emit('OCP\Share', 'post_set_expiration_date', [
|
\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
|
* Work around so we don't return expired shares but still follow
|
||||||
* proper pagination.
|
* proper pagination.
|
||||||
*/
|
*/
|
||||||
if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
|
|
||||||
$shares2 = [];
|
|
||||||
$today = new \DateTime();
|
|
||||||
|
|
||||||
while(true) {
|
$shares2 = [];
|
||||||
$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) {
|
while(true) {
|
||||||
break;
|
$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) {
|
if (count($shares2) === $limit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there was no limit on the select we are done
|
|
||||||
if ($limit === -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$offset += $added;
|
|
||||||
|
|
||||||
// Fetch again $limit shares
|
|
||||||
$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
|
|
||||||
|
|
||||||
// No more shares means we are done
|
|
||||||
if (empty($shares)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$shares = $shares2;
|
if (count($shares2) === $limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there was no limit on the select we are done
|
||||||
|
if ($limit === -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset += $added;
|
||||||
|
|
||||||
|
// Fetch again $limit shares
|
||||||
|
$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
|
||||||
|
|
||||||
|
// No more shares means we are done
|
||||||
|
if (empty($shares)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$shares = $shares2;
|
||||||
|
|
||||||
return $shares;
|
return $shares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,7 +993,18 @@ class Manager implements IManager {
|
||||||
return [];
|
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);
|
$share = $provider->getShareById($id, $recipient);
|
||||||
|
|
||||||
// Validate link shares expiration date
|
$this->checkExpireDate($share);
|
||||||
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
|
|
||||||
$share->getExpirationDate() !== null &&
|
|
||||||
$share->getExpirationDate() <= new \DateTime()) {
|
|
||||||
$this->deleteShare($share);
|
|
||||||
throw new ShareNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $share;
|
return $share;
|
||||||
}
|
}
|
||||||
|
@ -1066,11 +1087,7 @@ class Manager implements IManager {
|
||||||
throw new ShareNotFound();
|
throw new ShareNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($share->getExpirationDate() !== null &&
|
$this->checkExpireDate($share);
|
||||||
$share->getExpirationDate() <= new \DateTime()) {
|
|
||||||
$this->deleteShare($share);
|
|
||||||
throw new ShareNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reduce the permissions for link shares if public upload is not enabled
|
* Reduce the permissions for link shares if public upload is not enabled
|
||||||
|
@ -1083,6 +1100,15 @@ class Manager implements IManager {
|
||||||
return $share;
|
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
|
* Verify the password of a public share
|
||||||
*
|
*
|
||||||
|
@ -1091,7 +1117,9 @@ class Manager implements IManager {
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function checkPassword(\OCP\Share\IShare $share, $password) {
|
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?
|
//TODO maybe exception?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ use OCA\FederatedFileSharing\DiscoveryManager;
|
||||||
use OCA\FederatedFileSharing\FederatedShareProvider;
|
use OCA\FederatedFileSharing\FederatedShareProvider;
|
||||||
use OCA\FederatedFileSharing\Notifications;
|
use OCA\FederatedFileSharing\Notifications;
|
||||||
use OCA\FederatedFileSharing\TokenHandler;
|
use OCA\FederatedFileSharing\TokenHandler;
|
||||||
|
use OCA\ShareByMail\Settings\SettingsManager;
|
||||||
use OCA\ShareByMail\ShareByMailProvider;
|
use OCA\ShareByMail\ShareByMailProvider;
|
||||||
use OCP\Share\IProviderFactory;
|
use OCP\Share\IProviderFactory;
|
||||||
use OC\Share20\Exception\ProviderException;
|
use OC\Share20\Exception\ProviderException;
|
||||||
|
@ -149,18 +150,19 @@ class ProviderFactory implements IProviderFactory {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$l = $this->serverContainer->getL10N('sharebymail');
|
$settingsManager = new SettingsManager($this->serverContainer->getConfig());
|
||||||
|
|
||||||
$this->shareByMailProvider = new ShareByMailProvider(
|
$this->shareByMailProvider = new ShareByMailProvider(
|
||||||
$this->serverContainer->getDatabaseConnection(),
|
$this->serverContainer->getDatabaseConnection(),
|
||||||
$this->serverContainer->getSecureRandom(),
|
$this->serverContainer->getSecureRandom(),
|
||||||
$this->serverContainer->getUserManager(),
|
$this->serverContainer->getUserManager(),
|
||||||
$this->serverContainer->getLazyRootFolder(),
|
$this->serverContainer->getLazyRootFolder(),
|
||||||
$l,
|
$this->serverContainer->getL10N('sharebymail'),
|
||||||
$this->serverContainer->getLogger(),
|
$this->serverContainer->getLogger(),
|
||||||
$this->serverContainer->getMailer(),
|
$this->serverContainer->getMailer(),
|
||||||
$this->serverContainer->getURLGenerator(),
|
$this->serverContainer->getURLGenerator(),
|
||||||
$this->serverContainer->getActivityManager()
|
$this->serverContainer->getActivityManager(),
|
||||||
|
$settingsManager
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ interface IShare {
|
||||||
/**
|
/**
|
||||||
* Set the expiration date
|
* Set the expiration date
|
||||||
*
|
*
|
||||||
* @param \DateTime $expireDate
|
* @param null|\DateTime $expireDate
|
||||||
* @return \OCP\Share\IShare The modified object
|
* @return \OCP\Share\IShare The modified object
|
||||||
* @since 9.0.0
|
* @since 9.0.0
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -338,7 +338,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
$qb->insert('share')
|
$qb->insert('share')
|
||||||
->values([
|
->values([
|
||||||
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
|
'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_owner' => $qb->expr()->literal('shareOwner'),
|
||||||
'uid_initiator' => $qb->expr()->literal('sharedBy'),
|
'uid_initiator' => $qb->expr()->literal('sharedBy'),
|
||||||
'item_type' => $qb->expr()->literal('file'),
|
'item_type' => $qb->expr()->literal('file'),
|
||||||
|
@ -366,7 +366,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
|
|
||||||
$this->assertEquals($id, $share->getId());
|
$this->assertEquals($id, $share->getId());
|
||||||
$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
|
$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('sharedBy', $share->getSharedBy());
|
||||||
$this->assertEquals('shareOwner', $share->getShareOwner());
|
$this->assertEquals('shareOwner', $share->getShareOwner());
|
||||||
$this->assertEquals($ownerPath, $share->getNode());
|
$this->assertEquals($ownerPath, $share->getNode());
|
||||||
|
@ -752,7 +753,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
$qb->insert('share')
|
$qb->insert('share')
|
||||||
->values([
|
->values([
|
||||||
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
|
'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_owner' => $qb->expr()->literal('shareOwner'),
|
||||||
'uid_initiator' => $qb->expr()->literal('sharedBy'),
|
'uid_initiator' => $qb->expr()->literal('sharedBy'),
|
||||||
'item_type' => $qb->expr()->literal('file'),
|
'item_type' => $qb->expr()->literal('file'),
|
||||||
|
@ -814,7 +815,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
['home::shareOwner', 'files/test.txt', 'files/test2.txt'],
|
['home::shareOwner', 'files/test.txt', 'files/test2.txt'],
|
||||||
// regular file on external storage
|
// regular file on external storage
|
||||||
['smb::whatever', 'files/test.txt', 'files/test2.txt'],
|
['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'],
|
['smb::whatever', 'files_trashbin/files/test.txt', 'files_trashbin/files/test2.txt'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -2353,9 +2354,11 @@ class DefaultShareProviderTest extends \Test\TestCase {
|
||||||
$rootFolder
|
$rootFolder
|
||||||
);
|
);
|
||||||
|
|
||||||
$u1 = $userManager->createUser('testShare1', 'test');
|
$password = md5(time());
|
||||||
$u2 = $userManager->createUser('testShare2', 'test');
|
|
||||||
$u3 = $userManager->createUser('testShare3', 'test');
|
$u1 = $userManager->createUser('testShare1', $password);
|
||||||
|
$u2 = $userManager->createUser('testShare2', $password);
|
||||||
|
$u3 = $userManager->createUser('testShare3', $password);
|
||||||
|
|
||||||
$g1 = $groupManager->createGroup('group1');
|
$g1 = $groupManager->createGroup('group1');
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
||||||
// when updating major/minor version number.
|
// when updating major/minor version number.
|
||||||
|
|
||||||
$OC_Version = array(12, 0, 0, 13);
|
$OC_Version = array(12, 0, 0, 14);
|
||||||
|
|
||||||
// The human readable string
|
// The human readable string
|
||||||
$OC_VersionString = '12.0 alpha';
|
$OC_VersionString = '12.0 alpha';
|
||||||
|
|
Loading…
Reference in a new issue