Merge pull request #20773 from owncloud/share2.0_create

[Sharing 2.0] create share
This commit is contained in:
Thomas Müller 2016-01-07 14:57:05 +01:00
commit 601457d221
14 changed files with 2542 additions and 74 deletions

View File

@ -29,13 +29,18 @@ class OCSShareWrapper {
return new Share20OCS(
new \OC\Share20\Manager(
\OC::$server->getLogger(),
\OC::$server->getAppConfig(),
\OC::$server->getConfig(),
new \OC\Share20\DefaultShareProvider(
\OC::$server->getDatabaseConnection(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getRootFolder()
)
),
\OC::$server->getSecureRandom(),
\OC::$server->getHasher(),
\OC::$server->getMountManager(),
\OC::$server->getGroupManager(),
\OC::$server->getL10N('core')
),
\OC::$server->getGroupManager(),
\OC::$server->getUserManager(),
@ -49,8 +54,8 @@ class OCSShareWrapper {
return \OCA\Files_Sharing\API\Local::getAllShares($params);
}
public function createShare($params) {
return \OCA\Files_Sharing\API\Local::createShare($params);
public function createShare() {
return $this->getShare20OCS()->createShare();
}
public function getShare($params) {

View File

@ -25,7 +25,6 @@ use OC\Share20\IShare;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\IRequest;
use OCP\Files\Folder;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Files\IRootFolder;
@ -98,7 +97,7 @@ class Share20OCS {
$result['item_type'] = 'file';
}
$result['storage_id'] = $path->getStorage()->getId();
$result['storage'] = \OC\Files\Cache\Storage::getNumericStorageId($path->getStorage()->getId());
$result['storage'] = $path->getStorage()->getCache()->getNumericStorageId();
$result['item_source'] = $path->getId();
$result['file_source'] = $path->getId();
$result['file_parent'] = $path->getParent()->getId();
@ -191,6 +190,130 @@ class Share20OCS {
return new \OC_OCS_Result();
}
/**
* @return \OC_OCS_Result
*/
public function createShare() {
$share = $this->shareManager->newShare();
// Verify path
$path = $this->request->getParam('path', null);
if ($path === null) {
return new \OC_OCS_Result(null, 404, 'please specify a file or folder path');
}
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
try {
$path = $userFolder->get($path);
} catch (\OCP\Files\NotFoundException $e) {
return new \OC_OCS_Result(null, 404, 'wrong path, file/folder doesn\'t exist');
}
$share->setPath($path);
// Parse permissions (if available)
$permissions = $this->request->getParam('permissions', null);
if ($permissions === null) {
$permissions = \OCP\Constants::PERMISSION_ALL;
} else {
$permissions = (int)$permissions;
}
if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) {
return new \OC_OCS_Result(null, 404, 'invalid permissions');
}
// Shares always require read permissions
$permissions |= \OCP\Constants::PERMISSION_READ;
if ($path instanceof \OCP\Files\File) {
// Single file shares should never have delete or create permissions
$permissions &= ~\OCP\Constants::PERMISSION_DELETE;
$permissions &= ~\OCP\Constants::PERMISSION_CREATE;
}
$shareWith = $this->request->getParam('shareWith', null);
$shareType = (int)$this->request->getParam('shareType', '-1');
if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
// Valid user is required to share
if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
return new \OC_OCS_Result(null, 404, 'please specify a valid user');
}
$share->setSharedWith($this->userManager->get($shareWith));
$share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
// Valid group is required to share
if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
return new \OC_OCS_Result(null, 404, 'please specify a valid group');
}
$share->setSharedWith($this->groupManager->get($shareWith));
$share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
//Can we even share links?
if (!$this->shareManager->shareApiAllowLinks()) {
return new \OC_OCS_Result(null, 404, 'public link sharing is disabled by the administrator');
}
$publicUpload = $this->request->getParam('publicUpload', null);
if ($publicUpload === 'true') {
// Check if public upload is allowed
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
return new \OC_OCS_Result(null, 403, '"public upload disabled by the administrator');
}
// Public upload can only be set for folders
if ($path instanceof \OCP\Files\File) {
return new \OC_OCS_Result(null, 404, '"public upload is only possible for public shared folders');
}
$share->setPermissions(
\OCP\Constants::PERMISSION_READ |
\OCP\Constants::PERMISSION_CREATE |
\OCP\Constants::PERMISSION_UPDATE
);
} else {
$share->setPermissions(\OCP\Constants::PERMISSION_READ);
}
// Set password
$share->setPassword($this->request->getParam('password', null));
//Expire date
$expireDate = $this->request->getParam('expireDate', null);
if ($expireDate !== null) {
try {
$expireDate = $this->parseDate($expireDate);
$share->setExpirationDate($expireDate);
} catch (\Exception $e) {
return new \OC_OCS_Result(null, 404, 'Invalid Date. Format must be YYYY-MM-DD.');
}
}
} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
//fixme Remote shares are handled by old code path for now
return \OCA\Files_Sharing\API\Local::createShare([]);
} else {
return new \OC_OCS_Result(null, 400, "unknown share type");
}
$share->setShareType($shareType);
$share->setSharedBy($this->currentUser);
try {
$share = $this->shareManager->createShare($share);
} catch (\OC\HintException $e) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
return new \OC_OCS_Result(null, $code, $e->getHint());
}catch (\Exception $e) {
return new \OC_OCS_Result(null, 403, $e->getMessage());
}
$share = $this->formatShare($share);
return new \OC_OCS_Result($share);
}
/**
* @param IShare $share
* @return bool
@ -216,4 +339,30 @@ class Share20OCS {
return false;
}
/**
* Make sure that the passed date is valid ISO 8601
* So YYYY-MM-DD
* If not throw an exception
*
* @param string $expireDate
*
* @throws \Exception
* @return \DateTime
*/
private function parseDate($expireDate) {
try {
$date = new \DateTime($expireDate);
} catch (\Exception $e) {
throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
}
if ($date === false) {
throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
}
$date->setTime(0,0,0);
return $date;
}
}

View File

@ -65,6 +65,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->rootFolder = $this->getMock('OCP\Files\IRootFolder');
$this->urlGenerator = $this->getMock('OCP\IURLGenerator');
$this->currentUser = $this->getMock('OCP\IUser');
$this->currentUser->method('getUID')->willReturn('currentUser');
$this->ocs = new Share20OCS(
$this->shareManager,
@ -171,8 +172,18 @@ class Share20OCSTest extends \Test\TestCase {
$group = $this->getMock('OCP\IGroup');
$group->method('getGID')->willReturn('groupId');
$storage = $this->getMock('OCP\Files\Storage');
$cache = $this->getMockBuilder('OC\Files\Cache\Cache')
->disableOriginalConstructor()
->getMock();
$cache->method('getNumericStorageId')->willReturn(101);
$storage = $this->getMockBuilder('OC\Files\Storage\Storage')
->disableOriginalConstructor()
->getMock();
$storage->method('getId')->willReturn('STORAGE');
$storage->method('getCache')->willReturn($cache);
$parentFolder = $this->getMock('OCP\Files\Folder');
$parentFolder->method('getId')->willReturn(3);
@ -223,7 +234,7 @@ class Share20OCSTest extends \Test\TestCase {
'parent' => 6,
'storage_id' => 'STORAGE',
'path' => 'file',
'storage' => null, // HACK around static function
'storage' => 101,
'mail_send' => 0,
];
$data[] = [$share, $expected];
@ -262,7 +273,7 @@ class Share20OCSTest extends \Test\TestCase {
'parent' => 6,
'storage_id' => 'STORAGE',
'path' => 'folder',
'storage' => null, // HACK around static function
'storage' => 101,
'mail_send' => 0,
];
$data[] = [$share, $expected];
@ -304,7 +315,7 @@ class Share20OCSTest extends \Test\TestCase {
'parent' => 6,
'storage_id' => 'STORAGE',
'path' => 'folder',
'storage' => null, // HACK around static function
'storage' => 101,
'mail_send' => 0,
'url' => 'url',
];
@ -391,4 +402,280 @@ class Share20OCSTest extends \Test\TestCase {
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_LINK);
$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
}
public function testCreateShareNoPath() {
$expected = new \OC_OCS_Result(null, 404, 'please specify a file or folder path');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareInvalidPath() {
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'invalid-path'],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$userFolder->expects($this->once())
->method('get')
->with('invalid-path')
->will($this->throwException(new \OCP\Files\NotFoundException()));
$expected = new \OC_OCS_Result(null, 404, 'wrong path, file/folder doesn\'t exist');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareInvalidPermissions() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, 32],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\File');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$expected = new \OC_OCS_Result(null, 404, 'invalid permissions');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareUserNoShareWith() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, \OCP\Constants::PERMISSION_ALL],
['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\File');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$expected = new \OC_OCS_Result(null, 404, 'please specify a valid user');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareUserNoValidShareWith() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, \OCP\Constants::PERMISSION_ALL],
['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER],
['shareWith', $this->any(), 'invalidUser'],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\File');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$expected = new \OC_OCS_Result(null, 404, 'please specify a valid user');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareUser() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS')
->setConstructorArgs([
$this->shareManager,
$this->groupManager,
$this->userManager,
$this->request,
$this->rootFolder,
$this->urlGenerator,
$this->currentUser
])->setMethods(['formatShare'])
->getMock();
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, \OCP\Constants::PERMISSION_ALL],
['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER],
['shareWith', null, 'validUser'],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\File');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$user = $this->getMock('\OCP\IUser');
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
$this->userManager->method('get')->with('validUser')->willReturn($user);
$share->method('setPath')->with($path);
$share->method('setPermissions')
->with(
\OCP\Constants::PERMISSION_ALL &
~\OCP\Constants::PERMISSION_DELETE &
~\OCP\Constants::PERMISSION_CREATE);
$share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_USER);
$share->method('setSharedWith')->with($user);
$share->method('setSharedBy')->with($this->currentUser);
$expected = new \OC_OCS_Result();
$result = $ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareGroupNoValidShareWith() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, \OCP\Constants::PERMISSION_ALL],
['shareType', $this->any(), \OCP\Share::SHARE_TYPE_GROUP],
['shareWith', $this->any(), 'invalidGroup'],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\File');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$expected = new \OC_OCS_Result(null, 404, 'please specify a valid user');
$result = $this->ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
public function testCreateShareGroup() {
$share = $this->getMock('\OC\Share20\IShare');
$this->shareManager->method('newShare')->willReturn($share);
$ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS')
->setConstructorArgs([
$this->shareManager,
$this->groupManager,
$this->userManager,
$this->request,
$this->rootFolder,
$this->urlGenerator,
$this->currentUser
])->setMethods(['formatShare'])
->getMock();
$this->request
->method('getParam')
->will($this->returnValueMap([
['path', null, 'valid-path'],
['permissions', null, \OCP\Constants::PERMISSION_ALL],
['shareType', '-1', \OCP\Share::SHARE_TYPE_GROUP],
['shareWith', null, 'validGroup'],
]));
$userFolder = $this->getMock('\OCP\Files\Folder');
$this->rootFolder->expects($this->once())
->method('getUserFolder')
->with('currentUser')
->willReturn($userFolder);
$path = $this->getMock('\OCP\Files\Folder');
$userFolder->expects($this->once())
->method('get')
->with('valid-path')
->willReturn($path);
$group = $this->getMock('\OCP\IGroup');
$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
$this->groupManager->method('get')->with('validGroup')->willReturn($group);
$share->method('setPath')->with($path);
$share->method('setPermissions')->with(\OCP\Constants::PERMISSION_ALL);
$share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_GROUP);
$share->method('setSharedWith')->with($group);
$share->method('setSharedBy')->with($this->currentUser);
$expected = new \OC_OCS_Result();
$result = $ocs->createShare();
$this->assertEquals($expected->getMeta(), $result->getMeta());
$this->assertEquals($expected->getData(), $result->getData());
}
}

View File

@ -90,7 +90,13 @@ trait Provisioning {
} elseif ($this->currentServer === 'REMOTE') {
$this->createdRemoteUsers[$user] = $user;
}
//Quick hack to login once with the current user
$options2 = [
'auth' => [$user, '123456'],
];
$url = $fullUrl.'/'.$user;
$client->send($client->createRequest('GET', $url, $options2));
}
public function createUser($user) {

View File

@ -231,20 +231,23 @@ Feature: sharing
And User "user2" should be included in the response
And User "user3" should not be included in the response
Scenario: getting all shares of a file with reshares
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And user "user3" exists
And file "textfile0.txt" of user "user0" is shared with user "user1"
And file "textfile0.txt" of user "user1" is shared with user "user2"
And As an "user0"
When sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=textfile0.txt"
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And User "user1" should be included in the response
And User "user2" should be included in the response
And User "user3" should not be included in the response
# Skip this test for now. Since the new shares do not create reshares
# TODO enable when getshares is updated
#
# Scenario: getting all shares of a file with reshares
# Given user "user0" exists
# And user "user1" exists
# And user "user2" exists
# And user "user3" exists
# And file "textfile0.txt" of user "user0" is shared with user "user1"
# And file "textfile0.txt" of user "user1" is shared with user "user2"
# And As an "user0"
# When sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=textfile0.txt"
# Then the OCS status code should be "100"
# And the HTTP status code should be "200"
# And User "user1" should be included in the response
# And User "user2" should be included in the response
# And User "user3" should not be included in the response
Scenario: getting share info of a share
Given user "user0" exists
@ -263,7 +266,7 @@ Feature: sharing
| file_source | A_NUMBER |
| file_target | /textfile0.txt |
| path | /textfile0.txt |
| permissions | 23 |
| permissions | 19 |
| stime | A_NUMBER |
| storage | A_NUMBER |
| mail_send | 0 |
@ -326,7 +329,7 @@ Feature: sharing
| permissions | 8 |
And As an "user1"
When creating a share with
| path | /textfile0. (2).txt |
| path | /textfile0 (2).txt |
| shareType | 0 |
| shareWith | user2 |
| permissions | 31 |
@ -346,7 +349,7 @@ Feature: sharing
| permissions | 16 |
And As an "user1"
When creating a share with
| path | /textfile0. (2).txt |
| path | /textfile0 (2).txt |
| shareType | 0 |
| shareWith | user2 |
| permissions | 31 |

View File

@ -684,7 +684,8 @@
</field>
<!-- Foreign Key users::uid -->
<!-- This is the initiator of the share -->
<!-- This is the owner of the share
which does not have to be the initiator of the share -->
<field>
<name>uid_owner</name>
<type>text</type>
@ -694,18 +695,17 @@
</field>
<!-- Foreign Key users::uid -->
<!-- This is the owner of the file, this can be
different from the initiator of the share.
The naming is subobtimal but prevents huge
migration steps -->
<!-- This is the initiator of the share -->
<field>
<name>uid_fileowner</name>
<name>uid_initiator</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>64</length>
</field>
<!-- Foreign Key share::id or NULL -->
<field>
<name>parent</name>

View File

@ -64,11 +64,90 @@ class DefaultShareProvider implements IShareProvider {
/**
* Share a path
*
*
* @param IShare $share
* @return IShare The share object
* @throws ShareNotFound
* @throws \Exception
*/
public function create(IShare $share) {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share');
$qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
//Set the UID of the user we share with
$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
//Set the GID of the group we share with
$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getGID()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
//Set the token of the share
$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
//If a password is set store it
if ($share->getPassword() !== null) {
$qb->setValue('share_with', $qb->createNamedParameter($share->getPassword()));
}
//If an expiration date is set store it
if ($share->getExpirationDate() !== null) {
$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
}
} else {
throw new \Exception('invalid share type!');
}
// Set what is shares
$qb->setValue('item_type', $qb->createParameter('itemType'));
if ($share->getPath() instanceof \OCP\Files\File) {
$qb->setParameter('itemType', 'file');
} else {
$qb->setParameter('itemType', 'folder');
}
// Set the file id
$qb->setValue('item_source', $qb->createNamedParameter($share->getPath()->getId()));
$qb->setValue('file_source', $qb->createNamedParameter($share->getPath()->getId()));
// set the permissions
$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
// Set who created this share
$qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()));
// Set who is the owner of this file/folder (and this the owner of the share)
$qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()));
// Set the file target
$qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
// Set the time this share was created
$qb->setValue('stime', $qb->createNamedParameter(time()));
// insert the data and fetch the id of the share
$this->dbConn->beginTransaction();
$qb->execute();
$id = $this->dbConn->lastInsertId('*PREFIX*share');
$this->dbConn->commit();
// Now fetch the inserted share and create a complete share object
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('*PREFIX*share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new ShareNotFound();
}
$share = $this->createShare($data);
return $share;
}
/**
@ -170,11 +249,29 @@ class DefaultShareProvider implements IShareProvider {
/**
* Get shares for a given path
*
* @param \OCP\IUser $user
* @param \OCP\Files\Node $path
* @return IShare[]
*/
public function getSharesByPath(IUser $user, Node $path) {
public function getSharesByPath(Node $path) {
$qb = $this->dbConn->getQueryBuilder();
$cursor = $qb->select('*')
->from('share')
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)),
$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))
)
)->execute();
$shares = [];
while($data = $cursor->fetch()) {
$shares[] = $this->createShare($data);
}
$cursor->closeCursor();
return $shares;
}
/**
@ -223,16 +320,21 @@ class DefaultShareProvider implements IShareProvider {
$share->setSharedWith($data['share_with']);
}
$share->setSharedBy($this->userManager->get($data['uid_owner']));
if ($data['uid_initiator'] === null) {
//OLD SHARE
$share->setSharedBy($this->userManager->get($data['uid_owner']));
$folder = $this->rootFolder->getUserFolder($share->getSharedBy()->getUID());
$path = $folder->getById((int)$data['file_source'])[0];
// TODO: getById can return an array. How to handle this properly??
$folder = $this->rootFolder->getUserFolder($share->getSharedBy()->getUID());
$path = $folder->getById((int)$data['file_source'])[0];
$owner = $path->getOwner();
$share->setShareOwner($owner);
} else {
//New share!
$share->setSharedBy($this->userManager->get($data['uid_initiator']));
$share->setShareOwner($this->userManager->get($data['uid_owner']));
}
$owner = $path->getOwner();
$share->setShareOwner($owner);
$path = $this->rootFolder->getUserFolder($owner->getUID())->getById((int)$data['file_source'])[0];
$path = $this->rootFolder->getUserFolder($share->getShareOwner()->getUID())->getById((int)$data['file_source'])[0];
$share->setPath($path);
if ($data['expiration'] !== null) {

View File

@ -101,7 +101,7 @@ interface IShare {
* @param \DateTime $expireDate
* @return Share The modified object
*/
public function setExpirationDate(\DateTime $expireDate);
public function setExpirationDate($expireDate);
/**
* Get the share expiration date
@ -110,6 +110,14 @@ interface IShare {
*/
public function getExpirationDate();
/**
* Set the sharer of the path
*
* @param IUser|string $sharedBy
* @return Share The modified object
*/
public function setSharedBy($sharedBy);
/**
* Get share sharer
*
@ -117,6 +125,15 @@ interface IShare {
*/
public function getSharedBy();
/**
* Set the original share owner (who owns the path)
*
* @param IUser|string
*
* @return Share The modified object
*/
public function setShareOwner($shareOwner);
/**
* Get the original share owner (who owns the path)
*
@ -140,6 +157,14 @@ interface IShare {
*/
public function getPassword();
/**
* Set the token
*
* @param string $token
* @return Share The modified object
*/
public function setToken($token);
/**
* Get the token
*
@ -154,6 +179,14 @@ interface IShare {
*/
public function getParent();
/**
* Set the target of this share
*
* @param string $target
* @return Share The modified object
*/
public function setTarget($target);
/**
* Get the target of this share
*

View File

@ -81,11 +81,10 @@ interface IShareProvider {
/**
* Get shares for a given path
*
* @param \OCP\IUser $user
* @param \OCP\Files\Node $path
* @return IShare[]
*/
public function getSharesByPath(\OCP\IUser $user, \OCP\Files\Node $path);
public function getSharesByPath(\OCP\Files\Node $path);
/**
* Get shared with the given user

View File

@ -21,53 +21,458 @@
namespace OC\Share20;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IL10N;
use OCP\ILogger;
use OCP\Security\ISecureRandom;
use OCP\Security\IHasher;
use OCP\Files\Mount\IMountManager;
use OCP\IGroupManager;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\IUser;
use OC\Share20\Exception\ShareNotFound;
use OC\HintException;
/**
* This class is the communication hub for all sharing related operations.
*/
class Manager {
/**
* @var IShareProvider[]
*/
/** @var IShareProvider[] */
private $defaultProvider;
/** @var ILogger */
private $logger;
/** @var IAppConfig */
private $appConfig;
/** @var IConfig */
private $config;
/** @var ISecureRandom */
private $secureRandom;
/** @var IHasher */
private $hasher;
/** @var IMountManager */
private $mountManager;
/** @var IGroupManager */
private $groupManager;
/** @var IL10N */
private $l;
/**
* Manager constructor.
*
* @param ILogger $logger
* @param IAppConfig $appConfig
* @param IConfig $config
* @param IShareProvider $defaultProvider
* @param ISecureRandom $secureRandom
* @param IHasher $hasher
* @param IMountManager $mountManager
* @param IGroupManager $groupManager
* @param IL10N $l
*/
public function __construct(
ILogger $logger,
IAppConfig $appConfig,
IShareProvider $defaultProvider
IConfig $config,
IShareProvider $defaultProvider,
ISecureRandom $secureRandom,
IHasher $hasher,
IMountManager $mountManager,
IGroupManager $groupManager,
IL10N $l
) {
$this->logger = $logger;
$this->appConfig = $appConfig;
$this->config = $config;
$this->secureRandom = $secureRandom;
$this->hasher = $hasher;
$this->mountManager = $mountManager;
$this->groupManager = $groupManager;
$this->l = $l;
// TEMP SOLUTION JUST TO GET STARTED
$this->defaultProvider = $defaultProvider;
}
/**
* Verify if a password meets all requirements
*
* @param string $password
* @throws \Exception
*/
protected function verifyPassword($password) {
if ($password === null) {
// No password is set, check if this is allowed.
if ($this->shareApiLinkEnforcePassword()) {
throw new \InvalidArgumentException('Passwords are enforced for link shares');
}
return;
}
// Let others verify the password
$accepted = true;
$message = '';
\OCP\Util::emitHook('\OC\Share', 'verifyPassword', [
'password' => $password,
'accepted' => &$accepted,
'message' => &$message
]);
if (!$accepted) {
throw new \Exception($message);
}
}
/**
* Check for generic requirements before creating a share
*
* @param IShare $share
* @throws \Exception
*/
protected function generalCreateChecks(IShare $share) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
// We expect a valid user as sharedWith for user shares
if (!($share->getSharedWith() instanceof \OCP\IUser)) {
throw new \InvalidArgumentException('SharedWith should be an IUser');
}
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
// We expect a valid group as sharedWith for group shares
if (!($share->getSharedWith() instanceof \OCP\IGroup)) {
throw new \InvalidArgumentException('SharedWith should be an IGroup');
}
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
if ($share->getSharedWith() !== null) {
throw new \InvalidArgumentException('SharedWith should be empty');
}
} else {
// We can't handle other types yet
throw new \InvalidArgumentException('unkown share type');
}
// Verify the initiator of the share is et
if ($share->getSharedBy() === null) {
throw new \InvalidArgumentException('SharedBy should be set');
}
// Cannot share with yourself
if ($share->getSharedWith() === $share->getSharedBy()) {
throw new \InvalidArgumentException('Can\'t share with yourself');
}
// The path should be set
if ($share->getPath() === null) {
throw new \InvalidArgumentException('Path should be set');
}
// And it should be a file or a folder
if (!($share->getPath() instanceof \OCP\Files\File) &&
!($share->getPath() instanceof \OCP\Files\Folder)) {
throw new \InvalidArgumentException('Path should be either a file or a folder');
}
// Check if we actually have share permissions
if (!$share->getPath()->isShareable()) {
$message_t = $this->l->t('You are not allowed to share %s', [$share->getPath()->getPath()]);
throw new HintException($message_t, $message_t, 404);
}
// Permissions should be set
if ($share->getPermissions() === null) {
throw new \InvalidArgumentException('A share requires permissions');
}
// Check that we do not share with more permissions than we have
if ($share->getPermissions() & ~$share->getPath()->getPermissions()) {
$message_t = $this->l->t('Cannot increase permissions of %s', [$share->getPath()->getPath()]);
throw new HintException($message_t, $message_t, 404);
}
// Check that read permissions are always set
if (($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
throw new \InvalidArgumentException('Shares need at least read permissions');
}
}
/**
* Validate if the expiration date fits the system settings
*
* @param \DateTime $expireDate The current expiration date (can be null)
* @return \DateTime|null The expiration date or null if $expireDate was null and it is not required
* @throws \OC\HintException
*/
protected function validateExpiredate($expireDate) {
if ($expireDate !== null) {
//Make sure the expiration date is a date
$expireDate->setTime(0, 0, 0);
$date = new \DateTime();
$date->setTime(0, 0, 0);
if ($date >= $expireDate) {
$message = $this->l->t('Expiration date is in the past');
throw new \OC\HintException($message, $message, 404);
}
}
// If we enforce the expiration date check that is does not exceed
if ($this->shareApiLinkDefaultExpireDateEnforced()) {
if ($expireDate === null) {
throw new \InvalidArgumentException('Expiration date is enforced');
}
$date = new \DateTime();
$date->setTime(0, 0, 0);
$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
if ($date < $expireDate) {
$message = $this->l->t('Cannot set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
throw new \OC\HintException($message, $message, 404);
}
return $expireDate;
}
// If expiredate is empty set a default one if there is a default
if ($expireDate === null && $this->shareApiLinkDefaultExpireDate()) {
$date = new \DateTime();
$date->setTime(0,0,0);
$date->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
return $date;
}
return $expireDate;
}
/**
* Check for pre share requirements for use shares
*
* @param IShare $share
* @throws \Exception
*/
protected function userCreateChecks(IShare $share) {
// Check if we can share with group members only
if ($this->shareWithGroupMembersOnly()) {
// Verify we can share with this user
$groups = array_intersect(
$this->groupManager->getUserGroupIds($share->getSharedBy()),
$this->groupManager->getUserGroupIds($share->getSharedWith())
);
if (empty($groups)) {
throw new \Exception('Only sharing with group members is allowed');
}
}
/*
* TODO: Could be costly, fix
*
* Also this is not what we want in the future.. then we want to squash identical shares.
*/
$existingShares = $this->defaultProvider->getSharesByPath($share->getPath());
foreach($existingShares as $existingShare) {
// Identical share already existst
if ($existingShare->getSharedWith() === $share->getSharedWith()) {
throw new \Exception('Path already shared with this user');
}
// The share is already shared with this user via a group share
if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP &&
$existingShare->getSharedWith()->inGroup($share->getSharedWith()) &&
$existingShare->getShareOwner() !== $share->getShareOwner()) {
throw new \Exception('Path already shared with this user');
}
}
}
/**
* Check for pre share requirements for group shares
*
* @param IShare $share
* @throws \Exception
*/
protected function groupCreateChecks(IShare $share) {
// Verify if the user can share with this group
if ($this->shareWithGroupMembersOnly()) {
if (!$share->getSharedWith()->inGroup($share->getSharedBy())) {
throw new \Exception('Only sharing within your own groups is allowed');
}
}
/*
* TODO: Could be costly, fix
*
* Also this is not what we want in the future.. then we want to squash identical shares.
*/
$existingShares = $this->defaultProvider->getSharesByPath($share->getPath());
foreach($existingShares as $existingShare) {
if ($existingShare->getSharedWith() === $share->getSharedWith()) {
throw new \Exception('Path already shared with this group');
}
}
}
/**
* Check for pre share requirements for link shares
*
* @param IShare $share
* @throws \Exception
*/
protected function linkCreateChecks(IShare $share) {
// Are link shares allowed?
if (!$this->shareApiAllowLinks()) {
throw new \Exception('Link sharing not allowed');
}
// Link shares by definition can't have share permissions
if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
throw new \InvalidArgumentException('Link shares can\'t have reshare permissions');
}
// We don't allow deletion on link shares
if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
throw new \InvalidArgumentException('Link shares can\'t have delete permissions');
}
// Check if public upload is allowed
if (!$this->shareApiLinkAllowPublicUpload() &&
($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE))) {
throw new \InvalidArgumentException('Public upload not allowed');
}
}
/**
* @param File|Folder $path
*/
protected function pathCreateChecks($path) {
// Make sure that we do not share a path that contains a shared mountpoint
if ($path instanceof \OCP\Files\Folder) {
$mounts = $this->mountManager->findIn($path->getPath());
foreach($mounts as $mount) {
if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
throw new \InvalidArgumentException('Path contains files shared with you');
}
}
}
}
/**
* Check if the user that is sharing can actually share
*
* @param IShare $share
* @return bool
*/
protected function canShare(IShare $share) {
if (!$this->shareApiEnabled()) {
return false;
}
if ($this->isSharingDisabledForUser($share->getSharedBy())) {
return false;
}
return true;
}
/**
* Share a path
*
* @param Share $share
* @param IShare $share
* @return Share The share object
* @throws \Exception
*
* TODO: handle link share permissions or check them
*/
public function createShare(Share $share) {
public function createShare(IShare $share) {
if (!$this->canShare($share)) {
throw new \Exception('The Share API is disabled');
}
$this->generalCreateChecks($share);
//Verify share type
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
$this->userCreateChecks($share);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$this->groupCreateChecks($share);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
$this->linkCreateChecks($share);
/*
* For now ignore a set token.
*/
$share->setToken(
$this->secureRandom->generate(
\OC\Share\Constants::TOKEN_LENGTH,
\OCP\Security\ISecureRandom::CHAR_LOWER.
\OCP\Security\ISecureRandom::CHAR_UPPER.
\OCP\Security\ISecureRandom::CHAR_DIGITS
)
);
//Verify the expiration date
$share->setExpirationDate($this->validateExpiredate($share->getExpirationDate()));
//Verify the password
$this->verifyPassword($share->getPassword());
// If a password is set. Hash it!
if ($share->getPassword() !== null) {
$share->setPassword($this->hasher->hash($share->getPassword()));
}
}
// Verify if there are any issues with the path
$this->pathCreateChecks($share->getPath());
// On creation of a share the owner is always the owner of the path
$share->setShareOwner($share->getPath()->getOwner());
// Generate the target
$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getPath()->getName();
$target = \OC\Files\Filesystem::normalizePath($target);
$share->setTarget($target);
// Pre share hook
$run = true;
$error = '';
$preHookData = [
'itemType' => $share->getPath() instanceof \OCP\Files\File ? 'file' : 'folder',
'itemSource' => $share->getPath()->getId(),
'shareType' => $share->getShareType(),
'uidOwner' => $share->getSharedBy()->getUID(),
'permissions' => $share->getPermissions(),
'fileSource' => $share->getPath()->getId(),
'expiration' => $share->getExpirationDate(),
'token' => $share->getToken(),
'run' => &$run,
'error' => &$error
];
\OC_Hook::emit('OCP\Share', 'pre_shared', $preHookData);
if ($run === false) {
throw new \Exception($error);
}
$share = $this->defaultProvider->create($share);
// Post share hook
$postHookData = [
'itemType' => $share->getPath() instanceof \OCP\Files\File ? 'file' : 'folder',
'itemSource' => $share->getPath()->getId(),
'shareType' => $share->getShareType(),
'uidOwner' => $share->getSharedBy()->getUID(),
'permissions' => $share->getPermissions(),
'fileSource' => $share->getPath()->getId(),
'expiration' => $share->getExpirationDate(),
'token' => $share->getToken(),
'id' => $share->getId(),
];
\OC_Hook::emit('OCP\Share', 'post_shared', $postHookData);
return $share;
}
/**
@ -251,4 +656,115 @@ class Manager {
*/
public function getAccessList(\OCP\Files\Node $path) {
}
/**
* Create a new share
* @return IShare;
*/
public function newShare() {
return new \OC\Share20\Share();
}
/**
* Is the share API enabled
*
* @return bool
*/
public function shareApiEnabled() {
return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
}
/**
* Is public link sharing enabled
*
* @return bool
*/
public function shareApiAllowLinks() {
return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
}
/**
* Is password on public link requires
*
* @return bool
*/
public function shareApiLinkEnforcePassword() {
return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
}
/**
* Is default expire date enabled
*
* @return bool
*/
public function shareApiLinkDefaultExpireDate() {
return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
}
/**
* Is default expire date enforced
*`
* @return bool
*/
public function shareApiLinkDefaultExpireDateEnforced() {
return $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
}
/**
* Number of default expire days
*shareApiLinkAllowPublicUpload
* @return int
*/
public function shareApiLinkDefaultExpireDays() {
return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
}
/**
* Allow public upload on link shares
*
* @return bool
*/
public function shareApiLinkAllowPublicUpload() {
return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
}
/**
* check if user can only share with group members
* @return bool
*/
public function shareWithGroupMembersOnly() {
return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
}
/**
* Copied from \OC_Util::isSharingDisabledForUser
*
* TODO: Deprecate fuction from OC_Util
*
* @param IUser $user
* @return bool
*/
public function isSharingDisabledForUser($user) {
if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$excludedGroups = json_decode($groupsList);
if (is_null($excludedGroups)) {
$excludedGroups = explode(',', $groupsList);
$newValue = json_encode($excludedGroups);
$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
}
$usersGroups = $this->groupManager->getUserGroupIds($user);
if (!empty($usersGroups)) {
$remainingGroups = array_diff($usersGroups, $excludedGroups);
// if the user is only in groups which are disabled for sharing then
// sharing is also disabled for the user
if (empty($remainingGroups)) {
return true;
}
}
}
return false;
}
}

View File

@ -163,7 +163,7 @@ class Share implements IShare {
* @param \DateTime $expireDate
* @return Share The modified object
*/
public function setExpirationDate(\DateTime $expireDate) {
public function setExpirationDate($expireDate) {
//TODO checks
$this->expireDate = $expireDate;

View File

@ -26,6 +26,12 @@ use OCP\IGroupManager;
use OCP\Files\IRootFolder;
use OC\Share20\DefaultShareProvider;
/**
* Class DefaultShareProviderTest
*
* @package Test\Share20
* @group DB
*/
class DefaultShareProviderTest extends \Test\TestCase {
/** @var IDBConnection */
@ -533,4 +539,186 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals(null, $children[1]->getExpirationDate());
$this->assertEquals('myTarget2', $children[1]->getTarget());
}
public function testCreateUserShare() {
$share = new \OC\Share20\Share();
$sharedWith = $this->getMock('OCP\IUser');
$sharedWith->method('getUID')->willReturn('sharedWith');
$sharedBy = $this->getMock('OCP\IUser');
$sharedBy->method('getUID')->willReturn('sharedBy');
$shareOwner = $this->getMock('OCP\IUser');
$shareOwner->method('getUID')->WillReturn('shareOwner');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedWith', $sharedWith],
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$path = $this->getMock('\OCP\Files\File');
$path->method('getId')->willReturn(100);
$path->method('getOwner')->willReturn($shareOwner);
$ownerFolder = $this->getMock('OCP\Files\Folder');
$userFolder = $this->getMock('OCP\Files\Folder');
$this->rootFolder
->method('getUserFolder')
->will($this->returnValueMap([
['sharedBy', $userFolder],
['shareOwner', $ownerFolder],
]));
$userFolder->method('getById')
->with(100)
->willReturn([$path]);
$ownerFolder->method('getById')
->with(100)
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_USER);
$share->setSharedWith($sharedWith);
$share->setSharedBy($sharedBy);
$share->setShareOwner($shareOwner);
$share->setPath($path);
$share->setPermissions(1);
$share->setTarget('/target');
$share2 = $this->provider->create($share);
$this->assertNotNull($share2->getId());
$this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share2->getShareType());
$this->assertSame($sharedWith, $share2->getSharedWith());
$this->assertSame($sharedBy, $share2->getSharedBy());
$this->assertSame($shareOwner, $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(time(), $share2->getSharetime());
$this->assertSame($path, $share2->getPath());
}
public function testCreateGroupShare() {
$share = new \OC\Share20\Share();
$sharedWith = $this->getMock('OCP\IGroup');
$sharedWith->method('getGID')->willReturn('sharedWith');
$sharedBy = $this->getMock('OCP\IUser');
$sharedBy->method('getUID')->willReturn('sharedBy');
$shareOwner = $this->getMock('OCP\IUser');
$shareOwner->method('getUID')->WillReturn('shareOwner');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$this->groupManager
->method('get')
->with('sharedWith')
->willReturn($sharedWith);
$path = $this->getMock('\OCP\Files\Folder');
$path->method('getId')->willReturn(100);
$path->method('getOwner')->willReturn($shareOwner);
$ownerFolder = $this->getMock('OCP\Files\Folder');
$userFolder = $this->getMock('OCP\Files\Folder');
$this->rootFolder
->method('getUserFolder')
->will($this->returnValueMap([
['sharedBy', $userFolder],
['shareOwner', $ownerFolder],
]));
$userFolder->method('getById')
->with(100)
->willReturn([$path]);
$ownerFolder->method('getById')
->with(100)
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
$share->setSharedWith($sharedWith);
$share->setSharedBy($sharedBy);
$share->setShareOwner($shareOwner);
$share->setPath($path);
$share->setPermissions(1);
$share->setTarget('/target');
$share2 = $this->provider->create($share);
$this->assertNotNull($share2->getId());
$this->assertSame(\OCP\Share::SHARE_TYPE_GROUP, $share2->getShareType());
$this->assertSame($sharedWith, $share2->getSharedWith());
$this->assertSame($sharedBy, $share2->getSharedBy());
$this->assertSame($shareOwner, $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(time(), $share2->getSharetime());
$this->assertSame($path, $share2->getPath());
}
public function testCreateLinkShare() {
$share = new \OC\Share20\Share();
$sharedBy = $this->getMock('OCP\IUser');
$sharedBy->method('getUID')->willReturn('sharedBy');
$shareOwner = $this->getMock('OCP\IUser');
$shareOwner->method('getUID')->WillReturn('shareOwner');
$this->userManager
->method('get')
->will($this->returnValueMap([
['sharedBy', $sharedBy],
['shareOwner', $shareOwner],
]));
$path = $this->getMock('\OCP\Files\Folder');
$path->method('getId')->willReturn(100);
$path->method('getOwner')->willReturn($shareOwner);
$ownerFolder = $this->getMock('OCP\Files\Folder');
$userFolder = $this->getMock('OCP\Files\Folder');
$this->rootFolder
->method('getUserFolder')
->will($this->returnValueMap([
['sharedBy', $userFolder],
['shareOwner', $ownerFolder],
]));
$userFolder->method('getById')
->with(100)
->willReturn([$path]);
$ownerFolder->method('getById')
->with(100)
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_LINK);
$share->setSharedBy($sharedBy);
$share->setShareOwner($shareOwner);
$share->setPath($path);
$share->setPermissions(1);
$share->setPassword('password');
$share->setToken('token');
$expireDate = new \DateTime();
$share->setExpirationDate($expireDate);
$share->setTarget('/target');
$share2 = $this->provider->create($share);
$this->assertNotNull($share2->getId());
$this->assertSame(\OCP\Share::SHARE_TYPE_LINK, $share2->getShareType());
$this->assertSame($sharedBy, $share2->getSharedBy());
$this->assertSame($shareOwner, $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(time(), $share2->getSharetime());
$this->assertSame($path, $share2->getPath());
$this->assertSame('password', $share2->getPassword());
$this->assertSame('token', $share2->getToken());
$this->assertEquals($expireDate, $share2->getExpirationDate());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
$OC_Version = array(9, 0, 0, 5);
$OC_Version = array(9, 0, 0, 6);
// The human readable string
$OC_VersionString = '9.0 pre alpha';