From 5b26487f142843ad99a663d1ce2223c46a9498b2 Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Wed, 5 Aug 2020 10:37:20 +0200 Subject: [PATCH] Expose status via Collaborators API Signed-off-by: Georg Ehrke --- .../lib/Controller/ShareAPIController.php | 22 +++++++- apps/files_sharing/tests/ApiTest.php | 5 +- .../Controller/ShareAPIControllerTest.php | 31 ++++++++--- .../Collaborators/UserPlugin.php | 51 ++++++++++++++++++- .../Collaborators/UserPluginTest.php | 47 +++++++++-------- 5 files changed, 126 insertions(+), 30 deletions(-) diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 78b2eb1bc5..52c9e600c9 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -70,6 +70,7 @@ use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; use OCP\Share\IShare; +use OCP\UserStatus\IManager as IUserStatusManager; /** * Class Share20OCS @@ -100,6 +101,8 @@ class ShareAPIController extends OCSController { private $appManager; /** @var IServerContainer */ private $serverContainer; + /** @var IUserStatusManager */ + private $userStatusManager; /** * Share20OCS constructor. @@ -116,6 +119,7 @@ class ShareAPIController extends OCSController { * @param IConfig $config * @param IAppManager $appManager * @param IServerContainer $serverContainer + * @param IUserStatusManager $userStatusManager */ public function __construct( string $appName, @@ -129,7 +133,8 @@ class ShareAPIController extends OCSController { IL10N $l10n, IConfig $config, IAppManager $appManager, - IServerContainer $serverContainer + IServerContainer $serverContainer, + IUserStatusManager $userStatusManager ) { parent::__construct($appName, $request); @@ -144,6 +149,7 @@ class ShareAPIController extends OCSController { $this->config = $config; $this->appManager = $appManager; $this->serverContainer = $serverContainer; + $this->userStatusManager = $userStatusManager; } /** @@ -220,6 +226,20 @@ class ShareAPIController extends OCSController { $sharedWith = $this->userManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); + $result['status'] = []; + + $userStatuses = $this->userStatusManager->getUserStatuses([$share->getSharedWith()]); + $userStatus = array_shift($userStatuses); + if ($userStatus) { + $result['status'] = [ + 'status' => $userStatus->getStatus(), + 'message' => $userStatus->getMessage(), + 'icon' => $userStatus->getIcon(), + 'clearAt' => $userStatus->getClearAt() + ? (int)$userStatus->getClearAt()->format('U') + : null, + ]; + } } elseif ($share->getShareType() === IShare::TYPE_GROUP) { $group = $this->groupManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 5339128fbe..80fb4c257c 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -46,6 +46,7 @@ use OCP\IL10N; use OCP\IRequest; use OCP\IServerContainer; use OCP\Share\IShare; +use OCP\UserStatus\IManager as IUserStatusManager; /** * Class ApiTest @@ -114,6 +115,7 @@ class ApiTest extends TestCase { $config = $this->createMock(IConfig::class); $appManager = $this->createMock(IAppManager::class); $serverContainer = $this->createMock(IServerContainer::class); + $userStatusManager = $this->createMock(IUserStatusManager::class); return new ShareAPIController( self::APP_NAME, @@ -127,7 +129,8 @@ class ApiTest extends TestCase { $l, $config, $appManager, - $serverContainer + $serverContainer, + $userStatusManager ); } diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 4da51f7e5e..a85a32713c 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -56,6 +56,7 @@ use OCP\Share\Exceptions\GenericShareException; use OCP\Share\IManager; use OCP\Share\IShare; use Test\TestCase; +use OCP\UserStatus\IManager as IUserStatusManager; /** * Class ShareAPIControllerTest @@ -104,6 +105,9 @@ class ShareAPIControllerTest extends TestCase { /** @var IServerContainer|\PHPUnit\Framework\MockObject\MockObject */ private $serverContainer; + /** @var IUserStatusManager|\PHPUnit\Framework\MockObject\MockObject */ + private $userStatusManager; + protected function setUp(): void { $this->shareManager = $this->createMock(IManager::class); $this->shareManager @@ -128,6 +132,7 @@ class ShareAPIControllerTest extends TestCase { $this->config = $this->createMock(IConfig::class); $this->appManager = $this->createMock(IAppManager::class); $this->serverContainer = $this->createMock(IServerContainer::class); + $this->userStatusManager = $this->createMock(IUserStatusManager::class); $this->ocs = new ShareAPIController( $this->appName, @@ -141,7 +146,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager ); } @@ -162,7 +168,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['formatShare']) ->getMock(); } @@ -588,6 +595,7 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'status' => [], ]; $data[] = [$share, $expected]; @@ -715,7 +723,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['canAccessShare']) ->getMock(); @@ -1334,7 +1343,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['formatShare']) ->getMock(); @@ -1677,7 +1687,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['formatShare']) ->getMock(); @@ -1777,7 +1788,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['formatShare']) ->getMock(); @@ -2340,7 +2352,8 @@ class ShareAPIControllerTest extends TestCase { $this->l, $this->config, $this->appManager, - $this->serverContainer + $this->serverContainer, + $this->userStatusManager, ])->setMethods(['formatShare']) ->getMock(); @@ -3447,6 +3460,7 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'status' => [], ], $share, [], false ]; // User backend up @@ -3480,6 +3494,7 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'status' => [], ], $share, [ ['owner', $owner], ['initiator', $initiator], @@ -3529,6 +3544,7 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'status' => [], ], $share, [], false ]; @@ -3574,6 +3590,7 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => true, 'can_delete' => true, + 'status' => [], ], $share, [], false ]; diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index d1f2935073..72368e5052 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -38,6 +38,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Share\IShare; +use OCP\UserStatus\IManager as IUserStatusManager; class UserPlugin implements ISearchPlugin { /* @var bool */ @@ -53,13 +54,29 @@ class UserPlugin implements ISearchPlugin { private $userSession; /** @var IUserManager */ private $userManager; + /** @var IUserStatusManager */ + private $userStatusManager; - public function __construct(IConfig $config, IUserManager $userManager, IGroupManager $groupManager, IUserSession $userSession) { + /** + * UserPlugin constructor. + * + * @param IConfig $config + * @param IUserManager $userManager + * @param IGroupManager $groupManager + * @param IUserSession $userSession + * @param IUserStatusManager $userStatusManager + */ + public function __construct(IConfig $config, + IUserManager $userManager, + IGroupManager $groupManager, + IUserSession $userSession, + IUserStatusManager $userStatusManager) { $this->config = $config; $this->groupManager = $groupManager; $this->userSession = $userSession; $this->userManager = $userManager; + $this->userStatusManager = $userStatusManager; $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; @@ -99,10 +116,26 @@ class UserPlugin implements ISearchPlugin { $foundUserById = false; $lowerSearch = strtolower($search); + $userStatuses = $this->userStatusManager->getUserStatuses(array_keys($users)); foreach ($users as $uid => $user) { $userDisplayName = $user->getDisplayName(); $userEmail = $user->getEMailAddress(); $uid = (string) $uid; + + $status = []; + if (array_key_exists($uid, $userStatuses)) { + $userStatus = $userStatuses[$uid]; + $status = [ + 'status' => $userStatus->getStatus(), + 'message' => $userStatus->getMessage(), + 'icon' => $userStatus->getIcon(), + 'clearAt' => $userStatus->getClearAt() + ? (int)$userStatus->getClearAt()->format('U') + : null, + ]; + } + + if ( strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch || @@ -117,6 +150,7 @@ class UserPlugin implements ISearchPlugin { 'shareType' => IShare::TYPE_USER, 'shareWith' => $uid, ], + 'status' => $status, ]; } else { $addToWideResults = false; @@ -138,6 +172,7 @@ class UserPlugin implements ISearchPlugin { 'shareType' => IShare::TYPE_USER, 'shareWith' => $uid, ], + 'status' => $status, ]; } } @@ -157,12 +192,26 @@ class UserPlugin implements ISearchPlugin { } if ($addUser) { + $status = []; + if (array_key_exists($user->getUID(), $userStatuses)) { + $userStatus = $userStatuses[$user->getUID()]; + $status = [ + 'status' => $userStatus->getStatus(), + 'message' => $userStatus->getMessage(), + 'icon' => $userStatus->getIcon(), + 'clearAt' => $userStatus->getClearAt() + ? (int)$userStatus->getClearAt()->format('U') + : null, + ]; + } + $result['exact'][] = [ 'label' => $user->getDisplayName(), 'value' => [ 'shareType' => IShare::TYPE_USER, 'shareWith' => $user->getUID(), ], + 'status' => $status, ]; } } diff --git a/tests/lib/Collaboration/Collaborators/UserPluginTest.php b/tests/lib/Collaboration/Collaborators/UserPluginTest.php index 6c4ffcc52d..0db370d68b 100644 --- a/tests/lib/Collaboration/Collaborators/UserPluginTest.php +++ b/tests/lib/Collaboration/Collaborators/UserPluginTest.php @@ -33,6 +33,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Share\IShare; +use OCP\UserStatus\IManager as IUserStatusManager; use Test\TestCase; class UserPluginTest extends TestCase { @@ -48,6 +49,9 @@ class UserPluginTest extends TestCase { /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ protected $session; + /** @var IUserStatusManager|\PHPUnit\Framework\MockObject\MockObject */ + protected $userStatusManager; + /** @var UserPlugin */ protected $plugin; @@ -74,6 +78,8 @@ class UserPluginTest extends TestCase { $this->session = $this->createMock(IUserSession::class); + $this->userStatusManager = $this->createMock(IUserStatusManager::class); + $this->searchResult = new SearchResult(); $this->user = $this->getUserMock('admin', 'Administrator'); @@ -86,7 +92,8 @@ class UserPluginTest extends TestCase { $this->config, $this->userManager, $this->groupManager, - $this->session + $this->session, + $this->userStatusManager ); } @@ -144,13 +151,13 @@ class UserPluginTest extends TestCase { [ 'test', false, true, [], [], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [], true, $this->getUserMock('test', 'Test'), ], [ 'test', false, false, [], [], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [], true, $this->getUserMock('test', 'Test'), ], [ @@ -164,13 +171,13 @@ class UserPluginTest extends TestCase { [ 'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [], true, $this->getUserMock('test', 'Test'), ], [ 'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [], true, $this->getUserMock('test', 'Test'), ], [ @@ -183,7 +190,7 @@ class UserPluginTest extends TestCase { ], [], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []], ], true, false, @@ -212,8 +219,8 @@ class UserPluginTest extends TestCase { ], [], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1']], - ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []], + ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []], ], false, false, @@ -243,11 +250,11 @@ class UserPluginTest extends TestCase { $this->getUserMock('test2', 'Test Two'), ], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test0']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test0'], 'status' => []], ], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1']], - ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []], + ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []], ], false, false, @@ -263,7 +270,7 @@ class UserPluginTest extends TestCase { $this->getUserMock('test2', 'Test Two'), ], [ - ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test0']], + ['label' => 'Test', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test0'], 'status' => []], ], [], true, @@ -280,7 +287,7 @@ class UserPluginTest extends TestCase { ], [], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []], ], true, false, @@ -318,8 +325,8 @@ class UserPluginTest extends TestCase { ], [], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1']], - ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []], + ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []], ], false, false, @@ -366,10 +373,10 @@ class UserPluginTest extends TestCase { ]], ], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [ - ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], + ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []], ], false, false, @@ -392,7 +399,7 @@ class UserPluginTest extends TestCase { ]], ], [ - ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test']], + ['label' => 'Test One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'status' => []], ], [], true, @@ -611,10 +618,10 @@ class UserPluginTest extends TestCase { }, $matchingUsers); $mappedResultExact = array_map(function ($user) { - return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user]]; + return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user], 'status' => []]; }, $result['exact']); $mappedResultWide = array_map(function ($user) { - return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user]]; + return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user], 'status' => []]; }, $result['wide']); $this->userManager->expects($this->once())