diff options
author | Björn Schießle <bjoern@schiessle.org> | 2018-08-09 10:44:11 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-09 10:44:11 +0200 |
commit | 6aa6d2186cbc7c5a5db0cf8e1a20c82896266321 (patch) | |
tree | 03d8cf8c3fbf6ba9296a8394b4b18d79b2870300 | |
parent | ca0f2f63eb19f0d92d83c1ebbd1a29d2c7c45e08 (diff) | |
parent | 4b7fa4ac2e2562025672a389567ee659adff01ab (diff) | |
download | nextcloud-server-6aa6d2186cbc7c5a5db0cf8e1a20c82896266321.tar.gz nextcloud-server-6aa6d2186cbc7c5a5db0cf8e1a20c82896266321.zip |
Merge pull request #10255 from nextcloud/add-support-for-room-shares
Add support for room shares
23 files changed, 828 insertions, 24 deletions
diff --git a/apps/admin_audit/lib/Actions/Sharing.php b/apps/admin_audit/lib/Actions/Sharing.php index b66c9f50eb8..0c4601eef38 100644 --- a/apps/admin_audit/lib/Actions/Sharing.php +++ b/apps/admin_audit/lib/Actions/Sharing.php @@ -78,6 +78,19 @@ class Sharing extends Action { 'id', ] ); + } elseif($params['shareType'] === Share::SHARE_TYPE_ROOM) { + $this->log( + 'The %s "%s" with ID "%s" has been shared to the room "%s" with permissions "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'itemTarget', + 'itemSource', + 'shareWith', + 'permissions', + 'id', + ] + ); } } @@ -122,6 +135,18 @@ class Sharing extends Action { 'id', ] ); + } elseif($params['shareType'] === Share::SHARE_TYPE_ROOM) { + $this->log( + 'The %s "%s" with ID "%s" has been unshared from the room "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'fileTarget', + 'itemSource', + 'shareWith', + 'id', + ] + ); } } diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php index 825b9821a2a..990cc4a808f 100644 --- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php @@ -124,6 +124,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL, + \OCP\Share::SHARE_TYPE_ROOM, ]; foreach ($requestedShareTypes as $requestedShareType) { // one of each type is enough to find out about the types diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php index 63b84eb5c6c..d4dd3b49f34 100644 --- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php @@ -298,6 +298,7 @@ class SharesPluginTest extends \Test\TestCase { [[\OCP\Share::SHARE_TYPE_GROUP]], [[\OCP\Share::SHARE_TYPE_LINK]], [[\OCP\Share::SHARE_TYPE_REMOTE]], + [[\OCP\Share::SHARE_TYPE_ROOM]], [[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP]], [[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK]], [[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK]], diff --git a/apps/files/lib/Command/TransferOwnership.php b/apps/files/lib/Command/TransferOwnership.php index 6113f6df54c..f417898f217 100644 --- a/apps/files/lib/Command/TransferOwnership.php +++ b/apps/files/lib/Command/TransferOwnership.php @@ -217,7 +217,7 @@ class TransferOwnership extends Command { $output->writeln("Collecting all share information for files and folder of $this->sourceUser ..."); $progress = new ProgressBar($output, count($this->shares)); - foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) { + foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_ROOM] as $shareType) { $offset = 0; while (true) { $sharePage = $this->shareManager->getSharesBy($this->sourceUser, $shareType, null, true, 50, $offset); diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index d71b998ffb1..9443b9776ae 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -214,7 +214,8 @@ class ApiController extends Controller { \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, - \OCP\Share::SHARE_TYPE_EMAIL + \OCP\Share::SHARE_TYPE_EMAIL, + \OCP\Share::SHARE_TYPE_ROOM ]; foreach ($requestedShareTypes as $requestedShareType) { // one of each type is enough to find out about the types diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index a925920f3bc..0f8dc58a85e 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -144,6 +144,8 @@ hasShares = true; } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) { hasShares = true; + } else if (shareType === OC.Share.SHARE_TYPE_ROOM) { + hasShares = true; } }); OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink); diff --git a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php index d95b434e48f..6c7242ef613 100644 --- a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php +++ b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php @@ -26,14 +26,17 @@ declare(strict_types=1); namespace OCA\Files_Sharing\Controller; +use OCP\App\IAppManager; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; +use OCP\AppFramework\QueryException; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\IGroupManager; use OCP\IRequest; +use OCP\IServerContainer; use OCP\IUserManager; use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; @@ -57,13 +60,21 @@ class DeletedShareAPIController extends OCSController { /** @var IRootFolder */ private $rootFolder; + /** @var IAppManager */ + private $appManager; + + /** @var IServerContainer */ + private $serverContainer; + public function __construct(string $appName, IRequest $request, ShareManager $shareManager, string $UserId, IUserManager $userManager, IGroupManager $groupManager, - IRootFolder $rootFolder) { + IRootFolder $rootFolder, + IAppManager $appManager, + IServerContainer $serverContainer) { parent::__construct($appName, $request); $this->shareManager = $shareManager; @@ -71,8 +82,13 @@ class DeletedShareAPIController extends OCSController { $this->userManager = $userManager; $this->groupManager = $groupManager; $this->rootFolder = $rootFolder; + $this->appManager = $appManager; + $this->serverContainer = $serverContainer; } + /** + * @suppress PhanUndeclaredClassMethod + */ private function formatShare(IShare $share): array { $result = [ @@ -120,9 +136,19 @@ class DeletedShareAPIController extends OCSController { $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); } - $group = $this->groupManager->get($share->getSharedWith()); - $result['share_with'] = $share->getSharedWith(); - $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith(); + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $group = $this->groupManager->get($share->getSharedWith()); + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = ''; + + try { + $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share)); + } catch (QueryException $e) { + } + } return $result; @@ -132,7 +158,10 @@ class DeletedShareAPIController extends OCSController { * @NoAdminRequired */ public function index(): DataResponse { - $shares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0); + $groupShares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0); + $roomShares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_ROOM, null, -1, 0); + + $shares = array_merge($groupShares, $roomShares); $shares = array_map(function (IShare $share) { return $this->formatShare($share); @@ -165,4 +194,21 @@ class DeletedShareAPIController extends OCSController { return new DataResponse([]); } + + /** + * Returns the helper of DeletedShareAPIController for room shares. + * + * If the Talk application is not enabled or the helper is not available + * a QueryException is thrown instead. + * + * @return \OCA\Spreed\Share\Helper\DeletedShareAPIController + * @throws QueryException + */ + private function getRoomShareHelper() { + if (!$this->appManager->isEnabledForUser('spreed')) { + throw new QueryException(); + } + + return $this->serverContainer->query('\OCA\Spreed\Share\Helper\DeletedShareAPIController'); + } } diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index bda0047e66c..461c0e47320 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -37,6 +37,7 @@ use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; +use OCP\AppFramework\QueryException; use OCP\Constants; use OCP\Files\Folder; use OCP\Files\Node; @@ -46,6 +47,7 @@ use OCP\IGroupManager; use OCP\IL10N; use OCP\IUserManager; use OCP\IRequest; +use OCP\IServerContainer; use OCP\IURLGenerator; use OCP\Files\IRootFolder; use OCP\Lock\LockedException; @@ -84,6 +86,8 @@ class ShareAPIController extends OCSController { private $config; /** @var IAppManager */ private $appManager; + /** @var IServerContainer */ + private $serverContainer; /** * Share20OCS constructor. @@ -99,6 +103,7 @@ class ShareAPIController extends OCSController { * @param IL10N $l10n * @param IConfig $config * @param IAppManager $appManager + * @param IServerContainer $serverContainer */ public function __construct( string $appName, @@ -111,7 +116,8 @@ class ShareAPIController extends OCSController { string $userId, IL10N $l10n, IConfig $config, - IAppManager $appManager + IAppManager $appManager, + IServerContainer $serverContainer ) { parent::__construct($appName, $request); @@ -125,6 +131,7 @@ class ShareAPIController extends OCSController { $this->l = $l10n; $this->config = $config; $this->appManager = $appManager; + $this->serverContainer = $serverContainer; } /** @@ -134,6 +141,8 @@ class ShareAPIController extends OCSController { * @param Node|null $recipientNode * @return array * @throws NotFoundException In case the node can't be resolved. + * + * @suppress PhanUndeclaredClassMethod */ protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array { $sharedBy = $this->userManager->get($share->getSharedBy()); @@ -231,6 +240,14 @@ class ShareAPIController extends OCSController { $shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0); $shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' ')); $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength); + } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = ''; + + try { + $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share)); + } catch (QueryException $e) { + } } @@ -315,7 +332,8 @@ class ShareAPIController extends OCSController { throw new OCSNotFoundException($this->l->t('Could not delete share')); } - if ($share->getShareType() === Share::SHARE_TYPE_GROUP && + if (($share->getShareType() === Share::SHARE_TYPE_GROUP || + $share->getShareType() === Share::SHARE_TYPE_ROOM) && $share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) { $this->shareManager->deleteFromSelf($share, $this->currentUser); @@ -515,6 +533,12 @@ class ShareAPIController extends OCSController { } $share->setSharedWith($shareWith); $share->setPermissions($permissions); + } else if ($shareType === Share::SHARE_TYPE_ROOM) { + try { + $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate); + } catch (QueryException $e) { + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); + } } else { throw new OCSBadRequestException($this->l->t('Unknown share type')); } @@ -546,8 +570,9 @@ class ShareAPIController extends OCSController { $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0); $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0); $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0); + $roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0); - $shares = array_merge($userShares, $groupShares, $circleShares); + $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares); $shares = array_filter($shares, function (IShare $share) { return $share->getShareOwner() !== $this->currentUser; @@ -594,6 +619,7 @@ class ShareAPIController extends OCSController { if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); } + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0)); } $formatted = []; @@ -679,8 +705,9 @@ class ShareAPIController extends OCSController { } else { $circleShares = []; } + $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0); - $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares); + $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares); if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); @@ -864,6 +891,7 @@ class ShareAPIController extends OCSController { /* Check if this is an incomming share */ $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); + $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0)); /** @var \OCP\Share\IShare[] $incomingShares */ if (!empty($incomingShares)) { @@ -888,6 +916,9 @@ class ShareAPIController extends OCSController { return new DataResponse($this->formatShare($share)); } + /** + * @suppress PhanUndeclaredClassMethod + */ protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool { // A file with permissions 0 can't be accessed by us. So Don't show it if ($share->getPermissions() === 0) { @@ -921,6 +952,14 @@ class ShareAPIController extends OCSController { return true; } + if ($share->getShareType() === Share::SHARE_TYPE_ROOM) { + try { + return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser); + } catch (QueryException $e) { + return false; + } + } + return false; } @@ -988,6 +1027,13 @@ class ShareAPIController extends OCSController { // Do nothing, just try the other share type } + try { + $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser); + return $share; + } catch (ShareNotFound $e) { + // Do nothing, just try the other share type + } + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { throw new ShareNotFound(); } @@ -1016,4 +1062,21 @@ class ShareAPIController extends OCSController { $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED); } } + + /** + * Returns the helper of ShareAPIController for room shares. + * + * If the Talk application is not enabled or the helper is not available + * a QueryException is thrown instead. + * + * @return \OCA\Spreed\Share\Helper\ShareAPIController + * @throws QueryException + */ + private function getRoomShareHelper() { + if (!$this->appManager->isEnabledForUser('spreed')) { + throw new QueryException(); + } + + return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController'); + } } diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php index fd4c537210f..cb02a2b5f23 100644 --- a/apps/files_sharing/lib/MountProvider.php +++ b/apps/files_sharing/lib/MountProvider.php @@ -74,6 +74,7 @@ class MountProvider implements IMountProvider { $shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1)); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_CIRCLE, null, -1)); + $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_ROOM, null, -1)); // filter out excluded shares and group shares that includes self $shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) { diff --git a/apps/files_sharing/lib/Updater.php b/apps/files_sharing/lib/Updater.php index 784fe8b72b1..848ada62c7b 100644 --- a/apps/files_sharing/lib/Updater.php +++ b/apps/files_sharing/lib/Updater.php @@ -59,6 +59,7 @@ class Updater { $shares = $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_USER, $src, false, -1); $shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $src, false, -1)); + $shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_ROOM, $src, false, -1)); // If the path we move is not a share we don't care if (empty($shares)) { diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index a68ec7de1f0..0616daed62d 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -41,6 +41,7 @@ use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; +use OCP\IServerContainer; /** * Class ApiTest @@ -109,6 +110,7 @@ class ApiTest extends TestCase { })); $config = $this->createMock(IConfig::class); $appManager = $this->createMock(IAppManager::class); + $serverContainer = $this->createMock(IServerContainer::class); return new ShareAPIController( self::APP_NAME, @@ -121,7 +123,8 @@ class ApiTest extends TestCase { $userId, $l, $config, - $appManager + $appManager, + $serverContainer ); } diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 4fd8162db3d..15c4071bc46 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -38,6 +38,7 @@ use OCA\Files_Sharing\Controller\ShareAPIController; use OCP\Files\NotFoundException; use OCP\IGroupManager; use OCP\IUserManager; +use OCP\IServerContainer; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; @@ -92,6 +93,9 @@ class ShareAPIControllerTest extends TestCase { /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */ private $appManager; + /** @var IServerContainer|\PHPUnit_Framework_MockObject_MockObject */ + private $serverContainer; + protected function setUp() { $this->shareManager = $this->createMock(IManager::class); $this->shareManager @@ -112,6 +116,7 @@ class ShareAPIControllerTest extends TestCase { })); $this->config = $this->createMock(IConfig::class); $this->appManager = $this->createMock(IAppManager::class); + $this->serverContainer = $this->createMock(IServerContainer::class); $this->ocs = new ShareAPIController( $this->appName, @@ -124,7 +129,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ); } @@ -144,7 +150,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ])->setMethods(['formatShare']) ->getMock(); } @@ -159,10 +166,10 @@ class ShareAPIControllerTest extends TestCase { */ public function testDeleteShareShareNotFound() { $this->shareManager - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getShareById') ->will($this->returnCallback(function($id) { - if ($id === 'ocinternal:42' || $id === 'ocFederatedSharing:42') { + if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42') { throw new \OCP\Share\Exceptions\ShareNotFound(); } else { throw new \Exception(); @@ -461,7 +468,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ])->setMethods(['canAccessShare']) ->getMock(); @@ -596,6 +604,65 @@ class ShareAPIControllerTest extends TestCase { $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); } + public function dataCanAccessRoomShare() { + $result = []; + + $share = $this->createMock(IShare::class); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_ROOM); + $share->method('getSharedWith')->willReturn('recipientRoom'); + + $result[] = [ + false, $share, false, false + ]; + + $result[] = [ + false, $share, false, true + ]; + + $result[] = [ + true, $share, true, true + ]; + + $result[] = [ + false, $share, true, false + ]; + + return $result; + } + + /** + * @dataProvider dataCanAccessRoomShare + * + * @param bool $expects + * @param \OCP\Share\IShare $share + * @param bool helperAvailable + * @param bool canAccessShareByHelper + */ + public function testCanAccessRoomShare(bool $expected, \OCP\Share\IShare $share, bool $helperAvailable, bool $canAccessShareByHelper) { + if (!$helperAvailable) { + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(false); + } else { + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(true); + + $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController') + ->setMethods(array('canAccessShare')) + ->getMock(); + $helper->method('canAccessShare') + ->with($share, $this->currentUser) + ->willReturn($canAccessShareByHelper); + + $this->serverContainer->method('query') + ->with('\OCA\Spreed\Share\Helper\ShareAPIController') + ->willReturn($helper); + } + + $this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + } + /** * @expectedException \OCP\AppFramework\OCS\OCSNotFoundException * @expectedExceptionMessage Please specify a file or folder path @@ -733,7 +800,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ])->setMethods(['formatShare']) ->getMock(); @@ -832,7 +900,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ])->setMethods(['formatShare']) ->getMock(); @@ -1128,6 +1197,186 @@ class ShareAPIControllerTest extends TestCase { $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', '', null, 'a1b2d3'); } + public function testCreateShareRoom() { + $ocs = $this->mockFormatShare(); + + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $userFolder = $this->getMockBuilder(Folder::class)->getMock(); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMockBuilder(File::class)->getMock(); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(true); + + $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController') + ->setMethods(array('createShare')) + ->getMock(); + $helper->method('createShare') + ->with( + $share, + 'recipientRoom', + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE, + '' + )->will($this->returnCallback( + function ($share) { + $share->setSharedWith('recipientRoom'); + $share->setPermissions( + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE + ); + } + )); + + $this->serverContainer->method('query') + ->with('\OCA\Spreed\Share\Helper\ShareAPIController') + ->willReturn($helper); + + $this->shareManager->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getPermissions() === ( + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE + ) && + $share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM && + $share->getSharedWith() === 'recipientRoom' && + $share->getSharedBy() === 'currentUser'; + })) + ->will($this->returnArgument(0)); + + $expected = new DataResponse([]); + $result = $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom'); + + $this->assertInstanceOf(get_class($expected), $result); + $this->assertEquals($expected->getData(), $result->getData()); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSForbiddenException + * @expectedExceptionMessage Sharing valid-path failed because the back end does not support room shares + */ + public function testCreateShareRoomHelperNotAvailable() { + $ocs = $this->mockFormatShare(); + + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $userFolder = $this->getMockBuilder(Folder::class)->getMock(); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMockBuilder(File::class)->getMock(); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $path->method('getPath')->willReturn('valid-path'); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(false); + + $this->shareManager->expects($this->never())->method('createShare'); + + $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom'); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSNotFoundException + * @expectedExceptionMessage Exception thrown by the helper + */ + public function testCreateShareRoomHelperThrowException() { + $ocs = $this->mockFormatShare(); + + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $userFolder = $this->getMockBuilder(Folder::class)->getMock(); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMockBuilder(File::class)->getMock(); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(true); + + $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController') + ->setMethods(array('createShare')) + ->getMock(); + $helper->method('createShare') + ->with( + $share, + 'recipientRoom', + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE, + '' + )->will($this->returnCallback( + function ($share) { + throw new OCSNotFoundException("Exception thrown by the helper"); + } + )); + + $this->serverContainer->method('query') + ->with('\OCA\Spreed\Share\Helper\ShareAPIController') + ->willReturn($helper); + + $this->shareManager->expects($this->never())->method('createShare'); + + $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom'); + } + /** * Test for https://github.com/owncloud/core/issues/22587 * TODO: Remove once proper solution is in place @@ -1149,7 +1398,8 @@ class ShareAPIControllerTest extends TestCase { $this->currentUser, $this->l, $this->config, - $this->appManager + $this->appManager, + $this->serverContainer ])->setMethods(['formatShare']) ->getMock(); @@ -1681,7 +1931,8 @@ class ShareAPIControllerTest extends TestCase { ->method('getSharedWith') ->will($this->returnValueMap([ ['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, []], - ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]] + ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]], + ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, []] ])); $this->shareManager->expects($this->never())->method('updateShare'); @@ -1726,7 +1977,8 @@ class ShareAPIControllerTest extends TestCase { ->method('getSharedWith') ->will($this->returnValueMap([ ['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, [$incomingShare]], - ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []] + ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []], + ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, []] ])); $this->shareManager->expects($this->never())->method('updateShare'); @@ -1740,6 +1992,69 @@ class ShareAPIControllerTest extends TestCase { } } + public function testUpdateShareCannotIncreasePermissionsRoomShare() { + $ocs = $this->mockFormatShare(); + + $folder = $this->createMock(Folder::class); + + $share = \OC::$server->getShareManager()->newShare(); + $share + ->setId(42) + ->setSharedBy($this->currentUser) + ->setShareOwner('anotheruser') + ->setShareType(\OCP\Share::SHARE_TYPE_ROOM) + ->setSharedWith('group1') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($folder); + + // note: updateShare will modify the received instance but getSharedWith will reread from the database, + // so their values will be different + $incomingShare = \OC::$server->getShareManager()->newShare(); + $incomingShare + ->setId(42) + ->setSharedBy($this->currentUser) + ->setShareOwner('anotheruser') + ->setShareType(\OCP\Share::SHARE_TYPE_ROOM) + ->setSharedWith('group1') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['permissions', null, '31'], + ])); + + $this->shareManager + ->method('getShareById') + ->will($this->returnCallback( + function ($id) use ($share) { + if ($id !== 'ocRoomShare:42') { + throw new \OCP\Share\Exceptions\ShareNotFound(); + } + + return $share; + } + )); + + $this->shareManager->expects($this->any()) + ->method('getSharedWith') + ->will($this->returnValueMap([ + ['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, []], + ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []], + ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, [$incomingShare]] + ])); + + $this->shareManager->expects($this->never())->method('updateShare'); + + try { + $ocs->updateShare(42, 31); + $this->fail(); + } catch (OCSNotFoundException $e) { + $this->assertEquals('Cannot increase permissions', $e->getMessage()); + } + } + public function testUpdateShareCanIncreasePermissionsIfOwner() { $ocs = $this->mockFormatShare(); @@ -2410,4 +2725,160 @@ class ShareAPIControllerTest extends TestCase { $this->assertTrue($exception); } } + + public function dataFormatRoomShare() { + $file = $this->getMockBuilder(File::class)->getMock(); + $parent = $this->getMockBuilder(Folder::class)->getMock(); + + $file->method('getMimeType')->willReturn('myMimeType'); + + $file->method('getPath')->willReturn('file'); + + $parent->method('getId')->willReturn(1); + $file->method('getId')->willReturn(3); + + $file->method('getParent')->willReturn($parent); + + $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock(); + $cache->method('getNumericStorageId')->willReturn(100); + $storage = $this->getMockBuilder(Storage::class)->getMock(); + $storage->method('getId')->willReturn('storageId'); + $storage->method('getCache')->willReturn($cache); + + $file->method('getStorage')->willReturn($storage); + + $result = []; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_ROOM) + ->setSharedWith('recipientRoom') + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setNote('personal note') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_ROOM, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'note' => 'personal note', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipientRoom', + 'share_with_displayname' => '', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, false, [] + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_ROOM) + ->setSharedWith('recipientRoom') + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setNote('personal note') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_ROOM, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'note' => 'personal note', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipientRoom', + 'share_with_displayname' => 'recipientRoomName', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, true, [ + 'share_with_displayname' => 'recipientRoomName' + ] + ]; + + return $result; + } + + /** + * @dataProvider dataFormatRoomShare + * + * @param array $expects + * @param \OCP\Share\IShare $share + * @param bool $helperAvailable + * @param array $formatShareByHelper + */ + public function testFormatRoomShare(array $expects, \OCP\Share\IShare $share, bool $helperAvailable, array $formatShareByHelper) { + $this->rootFolder->method('getUserFolder') + ->with($this->currentUser) + ->will($this->returnSelf()); + + $this->rootFolder->method('getById') + ->with($share->getNodeId()) + ->willReturn([$share->getNode()]); + + $this->rootFolder->method('getRelativePath') + ->with($share->getNode()->getPath()) + ->will($this->returnArgument(0)); + + if (!$helperAvailable) { + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(false); + } else { + $this->appManager->method('isEnabledForUser') + ->with('spreed') + ->willReturn(true); + + $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController') + ->setMethods(array('formatShare')) + ->getMock(); + $helper->method('formatShare') + ->with($share) + ->willReturn($formatShareByHelper); + + $this->serverContainer->method('query') + ->with('\OCA\Spreed\Share\Helper\ShareAPIController') + ->willReturn($helper); + } + + $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]); + $this->assertEquals($expects, $result); + } } diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php index b521e109cf9..7b533bf8106 100644 --- a/apps/files_sharing/tests/MountProviderTest.php +++ b/apps/files_sharing/tests/MountProviderTest.php @@ -114,6 +114,12 @@ class MountProviderTest extends \Test\TestCase { $this->makeMockShare(4, 101, 'user2', '/share4', 31), $this->makeMockShare(5, 100, 'user1', '/share4', 31), ]; + $roomShares = [ + $this->makeMockShare(6, 102, 'user2', '/share6', 0), + $this->makeMockShare(7, 102, 'user1', '/share6', 31), + $this->makeMockShare(8, 102, 'user2', '/share6', 31), + $this->makeMockShare(9, 102, 'user2', '/share6', 31), + ]; // tests regarding circles are made in the app itself. $circleShares = []; $this->user->expects($this->any()) @@ -131,15 +137,20 @@ class MountProviderTest extends \Test\TestCase { ->method('getSharedWith') ->with('user1', \OCP\Share::SHARE_TYPE_CIRCLE, null, -1) ->will($this->returnValue($circleShares)); + $this->shareManager->expects($this->at(3)) + ->method('getSharedWith') + ->with('user1', \OCP\Share::SHARE_TYPE_ROOM, null, -1) + ->will($this->returnValue($roomShares)); $this->shareManager->expects($this->any()) ->method('newShare') ->will($this->returnCallback(function() use ($rootFolder, $userManager) { return new \OC\Share20\Share($rootFolder, $userManager); })); $mounts = $this->provider->getMountsForUser($this->user, $this->loader); - $this->assertCount(2, $mounts); + $this->assertCount(3, $mounts); $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]); $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]); + $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]); $mountedShare1 = $mounts[0]->getShare(); $this->assertEquals('2', $mountedShare1->getId()); $this->assertEquals('user2', $mountedShare1->getShareOwner()); @@ -152,6 +163,12 @@ class MountProviderTest extends \Test\TestCase { $this->assertEquals(101, $mountedShare2->getNodeId()); $this->assertEquals('/share4', $mountedShare2->getTarget()); $this->assertEquals(31, $mountedShare2->getPermissions()); + $mountedShare3 = $mounts[2]->getShare(); + $this->assertEquals('8', $mountedShare3->getId()); + $this->assertEquals('user2', $mountedShare3->getShareOwner()); + $this->assertEquals(102, $mountedShare3->getNodeId()); + $this->assertEquals('/share6', $mountedShare3->getTarget()); + $this->assertEquals(31, $mountedShare3->getPermissions()); } public function mergeSharesDataProvider() { @@ -316,6 +333,7 @@ class MountProviderTest extends \Test\TestCase { // tests regarding circles are made in the app itself. $circleShares = []; + $roomShares = []; $this->shareManager->expects($this->at(0)) ->method('getSharedWith') ->with('user1', \OCP\Share::SHARE_TYPE_USER) @@ -328,6 +346,10 @@ class MountProviderTest extends \Test\TestCase { ->method('getSharedWith') ->with('user1', \OCP\Share::SHARE_TYPE_CIRCLE, null, -1) ->will($this->returnValue($circleShares)); + $this->shareManager->expects($this->at(3)) + ->method('getSharedWith') + ->with('user1', \OCP\Share::SHARE_TYPE_ROOM, null, -1) + ->will($this->returnValue($roomShares)); $this->shareManager->expects($this->any()) ->method('newShare') ->will($this->returnCallback(function() use ($rootFolder, $userManager) { diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js index 91060f6a735..554a3a82b34 100644 --- a/apps/files_sharing/tests/js/shareSpec.js +++ b/apps/files_sharing/tests/js/shareSpec.js @@ -108,6 +108,26 @@ describe('OCA.Sharing.Util tests', function() { expect($action.find('.icon').hasClass('icon-public')).toEqual(false); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); }); + it('shows simple share text with share icon when shared to a room', function() { + var $action, $tr; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc', + shareTypes: [OC.Share.SHARE_TYPE_ROOM] + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.find('>span').text().trim()).toEqual('Shared'); + expect($action.find('.icon').hasClass('icon-shared')).toEqual(true); + expect($action.find('.icon').hasClass('icon-public')).toEqual(false); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); + }); it('shows simple share text with public icon when shared with link', function() { var $action, $tr; OC.Share.statuses = {1: {link: true, path: '/subdir'}}; diff --git a/build/integration/features/bootstrap/Provisioning.php b/build/integration/features/bootstrap/Provisioning.php index 1a2c32ed8c6..c320be2be6c 100644 --- a/build/integration/features/bootstrap/Provisioning.php +++ b/build/integration/features/bootstrap/Provisioning.php @@ -680,6 +680,30 @@ trait Provisioning { } /** + * @Given /^app "([^"]*)" is not enabled$/ + * + * Checks that the app is disabled or not installed. + * + * @param string $app + */ + public function appIsNotEnabled($app) { + $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=enabled"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + $options['headers'] = [ + 'OCS-APIREQUEST' => 'true', + ]; + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfAppsResponded($this->response); + Assert::assertNotContains($app, $respondedArray); + Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** * @Then /^user "([^"]*)" is disabled$/ * @param string $user */ diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 5708b7115e4..dd5cc9fff4f 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -43,6 +43,18 @@ Feature: sharing Then the OCS status code should be "100" And the HTTP status code should be "200" + Scenario: Creating a new room share when Talk is not enabled + Given As an "admin" + And app "spreed" is not enabled + And user "user0" exists + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareWith | a-room-token | + | shareType | 10 | + Then the OCS status code should be "403" + And the HTTP status code should be "401" + Scenario: Creating a new public share Given user "user0" exists And As an "user0" diff --git a/core/js/share.js b/core/js/share.js index e4d9364b2d1..cef05eb6479 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -12,6 +12,7 @@ OC.Share = _.extend(OC.Share || {}, { SHARE_TYPE_CIRCLE:7, SHARE_TYPE_GUEST:8, SHARE_TYPE_REMOTE_GROUP:9, + SHARE_TYPE_ROOM:10, /** * Regular expression for splitting parts of remote share owners: diff --git a/core/js/sharedialogresharerinfoview.js b/core/js/sharedialogresharerinfoview.js index fadd0a41f7b..06e18fef3f2 100644 --- a/core/js/sharedialogresharerinfoview.js +++ b/core/js/sharedialogresharerinfoview.js @@ -99,6 +99,17 @@ undefined, {escape: false} ); + } else if (this.model.getReshareType() === OC.Share.SHARE_TYPE_ROOM) { + sharedByText = t( + 'core', + 'Shared with you and the conversation {conversation} by {owner}', + { + conversation: this.model.getReshareWithDisplayName(), + owner: ownerDisplayName + }, + undefined, + {escape: false} + ); } else { sharedByText = t( 'core', diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index 2ed46f46768..2627d5fa662 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -243,6 +243,8 @@ } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) { shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'email') + ')'; } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) { + } else if (shareType === OC.Share.SHARE_TYPE_ROOM) { + shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'conversation') + ')'; } if (shareType === OC.Share.SHARE_TYPE_GROUP) { @@ -291,7 +293,7 @@ shareWithTitle: shareWithTitle, shareType: shareType, shareId: this.model.get('shares')[shareIndex].id, - modSeed: shareType !== OC.Share.SHARE_TYPE_USER && (shareType !== OC.Share.SHARE_TYPE_CIRCLE || shareWithAvatar), + modSeed: shareWithAvatar || (shareType !== OC.Share.SHARE_TYPE_USER && shareType !== OC.Share.SHARE_TYPE_CIRCLE && shareType !== OC.Share.SHARE_TYPE_ROOM), isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE, isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP, isNoteAvailable: shareType !== OC.Share.SHARE_TYPE_REMOTE && shareType !== OC.Share.SHARE_TYPE_REMOTE_GROUP, diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php index 4eb79734c06..72dc5cd43be 100644 --- a/lib/private/Share/Constants.php +++ b/lib/private/Share/Constants.php @@ -31,6 +31,7 @@ class Constants { const SHARE_TYPE_USER = 0; const SHARE_TYPE_GROUP = 1; + // const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider const SHARE_TYPE_LINK = 3; const SHARE_TYPE_EMAIL = 4; const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it @@ -38,6 +39,8 @@ class Constants { const SHARE_TYPE_CIRCLE = 7; const SHARE_TYPE_GUEST = 8; const SHARE_TYPE_REMOTE_GROUP = 9; + const SHARE_TYPE_ROOM = 10; + // const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider const FORMAT_NONE = -1; const FORMAT_STATUSES = -2; diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index d0316b44c1a..037ea53048a 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -239,6 +239,7 @@ class Manager implements IManager { if ($circle === null) { throw new \InvalidArgumentException('SharedWith is not a valid circle'); } + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) { } else { // We can't handle other types yet throw new \InvalidArgumentException('unknown share type'); @@ -1247,6 +1248,15 @@ class Manager implements IManager { } } + if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) { + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM); + $share = $provider->getShareByToken($token); + } catch (ProviderException $e) { + } catch (ShareNotFound $e) { + } + } + if ($share === null) { throw new ShareNotFound($this->l->t('The requested share does not exist anymore')); } diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 0aacca409d1..6cb6c082df5 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -60,6 +60,8 @@ class ProviderFactory implements IProviderFactory { private $shareByCircleProvider = null; /** @var bool */ private $circlesAreNotAvailable = false; + /** @var \OCA\Spreed\Share\RoomShareProvider */ + private $roomShareProvider = null; /** * IProviderFactory constructor. @@ -221,6 +223,30 @@ class ProviderFactory implements IProviderFactory { return $this->shareByCircleProvider; } + /** + * Create the room share provider + * + * @return RoomShareProvider + */ + protected function getRoomShareProvider() { + if ($this->roomShareProvider === null) { + /* + * Check if the app is enabled + */ + $appManager = $this->serverContainer->getAppManager(); + if (!$appManager->isEnabledForUser('spreed')) { + return null; + } + + try { + $this->roomShareProvider = $this->serverContainer->query('\OCA\Spreed\Share\RoomShareProvider'); + } catch (\OCP\AppFramework\QueryException $e) { + return null; + } + } + + return $this->roomShareProvider; + } /** * @inheritdoc @@ -235,6 +261,8 @@ class ProviderFactory implements IProviderFactory { $provider = $this->getShareByMailProvider(); } else if ($id === 'ocCircleShare') { $provider = $this->getShareByCircleProvider(); + } else if ($id === 'ocRoomShare') { + $provider = $this->getRoomShareProvider(); } if ($provider === null) { @@ -261,6 +289,8 @@ class ProviderFactory implements IProviderFactory { $provider = $this->getShareByMailProvider(); } else if ($shareType === \OCP\Share::SHARE_TYPE_CIRCLE) { $provider = $this->getShareByCircleProvider(); + } else if ($shareType === \OCP\Share::SHARE_TYPE_ROOM) { + $provider = $this->getRoomShareProvider(); } @@ -281,6 +311,10 @@ class ProviderFactory implements IProviderFactory { if ($shareByCircle !== null) { $shares[] = $shareByCircle; } + $roomShare = $this->getRoomShareProvider(); + if ($roomShare !== null) { + $shares[] = $roomShare; + } return $shares; } diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 7106e22b264..1125cae9565 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -2165,6 +2165,56 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($share, $ret); } + public function testGetShareByTokenRoom() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'shareapi_allow_links', 'yes') + ->willReturn('no'); + + $factory = $this->createMock(IProviderFactory::class); + + $manager = new Manager( + $this->logger, + $this->config, + $this->secureRandom, + $this->hasher, + $this->mountManager, + $this->groupManager, + $this->l, + $this->l10nFactory, + $factory, + $this->userManager, + $this->rootFolder, + $this->eventDispatcher, + $this->mailer, + $this->urlGenerator, + $this->defaults + ); + + $share = $this->createMock(IShare::class); + + $roomShareProvider = $this->createMock(IShareProvider::class); + + $factory->expects($this->any()) + ->method('getProviderForType') + ->will($this->returnCallback(function($shareType) use ($roomShareProvider) { + if ($shareType !== \OCP\Share::SHARE_TYPE_ROOM) { + throw new Exception\ProviderException(); + } + + return $roomShareProvider; + })); + + $roomShareProvider->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $ret = $manager->getShareByToken('token'); + $this->assertSame($share, $ret); + } + public function testGetShareByTokenWithException() { $this->config ->expects($this->once()) |