]> source.dussan.org Git - nextcloud-server.git/commitdiff
[Share 2.0] Enable share creation via OCS API
authorRoeland Jago Douma <rullzer@owncloud.com>
Tue, 15 Dec 2015 08:54:50 +0000 (09:54 +0100)
committerRoeland Jago Douma <rullzer@owncloud.com>
Wed, 6 Jan 2016 13:53:43 +0000 (14:53 +0100)
apps/files_sharing/api/ocssharewrapper.php
apps/files_sharing/api/share20ocs.php
apps/files_sharing/tests/api/share20ocstest.php

index ca04c656c285fe07d279c494fc09d482b90d09ae..2896f3fbf01f94334bf5be3292ce34910b2d870e 100644 (file)
@@ -29,13 +29,17 @@ 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->getGroupManager(),
                        \OC::$server->getUserManager(),
@@ -49,8 +53,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) {
index 6c25b4a44261b13549fca238c33e7bc8b2c93a2f..bf644ce00f6613409e3882ea76a553e17fe4fd82 100644 (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;
@@ -191,6 +190,127 @@ 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 (\Exception $e) {
+                       return new \OC_OCS_Result(null, 404, $e->getMessage());
+               }
+
+               $share = $this->formatShare($share);
+               return new \OC_OCS_Result($share);
+       }
+
        /**
         * @param IShare $share
         * @return bool
@@ -216,4 +336,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;
+       }
 }
index b7c56fe17f6a51c2123bbd4de9f38de2a152618b..2d69636541e46a2b15edd4007c61dd1318c9b0da 100644 (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,
@@ -391,4 +392,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());
+       }
 }