Expose status via Collaborators API

Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
Georg Ehrke 2020-08-05 10:37:20 +02:00
parent b13aa660c9
commit 5b26487f14
No known key found for this signature in database
GPG Key ID: 9D98FD9380A1CB43
5 changed files with 126 additions and 30 deletions

View File

@ -70,6 +70,7 @@ use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager; use OCP\Share\IManager;
use OCP\Share\IShare; use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
/** /**
* Class Share20OCS * Class Share20OCS
@ -100,6 +101,8 @@ class ShareAPIController extends OCSController {
private $appManager; private $appManager;
/** @var IServerContainer */ /** @var IServerContainer */
private $serverContainer; private $serverContainer;
/** @var IUserStatusManager */
private $userStatusManager;
/** /**
* Share20OCS constructor. * Share20OCS constructor.
@ -116,6 +119,7 @@ class ShareAPIController extends OCSController {
* @param IConfig $config * @param IConfig $config
* @param IAppManager $appManager * @param IAppManager $appManager
* @param IServerContainer $serverContainer * @param IServerContainer $serverContainer
* @param IUserStatusManager $userStatusManager
*/ */
public function __construct( public function __construct(
string $appName, string $appName,
@ -129,7 +133,8 @@ class ShareAPIController extends OCSController {
IL10N $l10n, IL10N $l10n,
IConfig $config, IConfig $config,
IAppManager $appManager, IAppManager $appManager,
IServerContainer $serverContainer IServerContainer $serverContainer,
IUserStatusManager $userStatusManager
) { ) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
@ -144,6 +149,7 @@ class ShareAPIController extends OCSController {
$this->config = $config; $this->config = $config;
$this->appManager = $appManager; $this->appManager = $appManager;
$this->serverContainer = $serverContainer; $this->serverContainer = $serverContainer;
$this->userStatusManager = $userStatusManager;
} }
/** /**
@ -220,6 +226,20 @@ class ShareAPIController extends OCSController {
$sharedWith = $this->userManager->get($share->getSharedWith()); $sharedWith = $this->userManager->get($share->getSharedWith());
$result['share_with'] = $share->getSharedWith(); $result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $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) { } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
$group = $this->groupManager->get($share->getSharedWith()); $group = $this->groupManager->get($share->getSharedWith());
$result['share_with'] = $share->getSharedWith(); $result['share_with'] = $share->getSharedWith();

View File

@ -46,6 +46,7 @@ use OCP\IL10N;
use OCP\IRequest; use OCP\IRequest;
use OCP\IServerContainer; use OCP\IServerContainer;
use OCP\Share\IShare; use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
/** /**
* Class ApiTest * Class ApiTest
@ -114,6 +115,7 @@ class ApiTest extends TestCase {
$config = $this->createMock(IConfig::class); $config = $this->createMock(IConfig::class);
$appManager = $this->createMock(IAppManager::class); $appManager = $this->createMock(IAppManager::class);
$serverContainer = $this->createMock(IServerContainer::class); $serverContainer = $this->createMock(IServerContainer::class);
$userStatusManager = $this->createMock(IUserStatusManager::class);
return new ShareAPIController( return new ShareAPIController(
self::APP_NAME, self::APP_NAME,
@ -127,7 +129,8 @@ class ApiTest extends TestCase {
$l, $l,
$config, $config,
$appManager, $appManager,
$serverContainer $serverContainer,
$userStatusManager
); );
} }

View File

@ -56,6 +56,7 @@ use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\IManager; use OCP\Share\IManager;
use OCP\Share\IShare; use OCP\Share\IShare;
use Test\TestCase; use Test\TestCase;
use OCP\UserStatus\IManager as IUserStatusManager;
/** /**
* Class ShareAPIControllerTest * Class ShareAPIControllerTest
@ -104,6 +105,9 @@ class ShareAPIControllerTest extends TestCase {
/** @var IServerContainer|\PHPUnit\Framework\MockObject\MockObject */ /** @var IServerContainer|\PHPUnit\Framework\MockObject\MockObject */
private $serverContainer; private $serverContainer;
/** @var IUserStatusManager|\PHPUnit\Framework\MockObject\MockObject */
private $userStatusManager;
protected function setUp(): void { protected function setUp(): void {
$this->shareManager = $this->createMock(IManager::class); $this->shareManager = $this->createMock(IManager::class);
$this->shareManager $this->shareManager
@ -128,6 +132,7 @@ class ShareAPIControllerTest extends TestCase {
$this->config = $this->createMock(IConfig::class); $this->config = $this->createMock(IConfig::class);
$this->appManager = $this->createMock(IAppManager::class); $this->appManager = $this->createMock(IAppManager::class);
$this->serverContainer = $this->createMock(IServerContainer::class); $this->serverContainer = $this->createMock(IServerContainer::class);
$this->userStatusManager = $this->createMock(IUserStatusManager::class);
$this->ocs = new ShareAPIController( $this->ocs = new ShareAPIController(
$this->appName, $this->appName,
@ -141,7 +146,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager
); );
} }
@ -162,7 +168,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['formatShare']) ])->setMethods(['formatShare'])
->getMock(); ->getMock();
} }
@ -588,6 +595,7 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0, 'hide_download' => 0,
'can_edit' => false, 'can_edit' => false,
'can_delete' => false, 'can_delete' => false,
'status' => [],
]; ];
$data[] = [$share, $expected]; $data[] = [$share, $expected];
@ -715,7 +723,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['canAccessShare']) ])->setMethods(['canAccessShare'])
->getMock(); ->getMock();
@ -1334,7 +1343,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['formatShare']) ])->setMethods(['formatShare'])
->getMock(); ->getMock();
@ -1677,7 +1687,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['formatShare']) ])->setMethods(['formatShare'])
->getMock(); ->getMock();
@ -1777,7 +1788,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['formatShare']) ])->setMethods(['formatShare'])
->getMock(); ->getMock();
@ -2340,7 +2352,8 @@ class ShareAPIControllerTest extends TestCase {
$this->l, $this->l,
$this->config, $this->config,
$this->appManager, $this->appManager,
$this->serverContainer $this->serverContainer,
$this->userStatusManager,
])->setMethods(['formatShare']) ])->setMethods(['formatShare'])
->getMock(); ->getMock();
@ -3447,6 +3460,7 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0, 'hide_download' => 0,
'can_edit' => false, 'can_edit' => false,
'can_delete' => false, 'can_delete' => false,
'status' => [],
], $share, [], false ], $share, [], false
]; ];
// User backend up // User backend up
@ -3480,6 +3494,7 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0, 'hide_download' => 0,
'can_edit' => false, 'can_edit' => false,
'can_delete' => false, 'can_delete' => false,
'status' => [],
], $share, [ ], $share, [
['owner', $owner], ['owner', $owner],
['initiator', $initiator], ['initiator', $initiator],
@ -3529,6 +3544,7 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0, 'hide_download' => 0,
'can_edit' => false, 'can_edit' => false,
'can_delete' => false, 'can_delete' => false,
'status' => [],
], $share, [], false ], $share, [], false
]; ];
@ -3574,6 +3590,7 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0, 'hide_download' => 0,
'can_edit' => true, 'can_edit' => true,
'can_delete' => true, 'can_delete' => true,
'status' => [],
], $share, [], false ], $share, [], false
]; ];

View File

@ -38,6 +38,7 @@ use OCP\IUser;
use OCP\IUserManager; use OCP\IUserManager;
use OCP\IUserSession; use OCP\IUserSession;
use OCP\Share\IShare; use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
class UserPlugin implements ISearchPlugin { class UserPlugin implements ISearchPlugin {
/* @var bool */ /* @var bool */
@ -53,13 +54,29 @@ class UserPlugin implements ISearchPlugin {
private $userSession; private $userSession;
/** @var IUserManager */ /** @var IUserManager */
private $userManager; 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->config = $config;
$this->groupManager = $groupManager; $this->groupManager = $groupManager;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->userManager = $userManager; $this->userManager = $userManager;
$this->userStatusManager = $userStatusManager;
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; $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'; $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
@ -99,10 +116,26 @@ class UserPlugin implements ISearchPlugin {
$foundUserById = false; $foundUserById = false;
$lowerSearch = strtolower($search); $lowerSearch = strtolower($search);
$userStatuses = $this->userStatusManager->getUserStatuses(array_keys($users));
foreach ($users as $uid => $user) { foreach ($users as $uid => $user) {
$userDisplayName = $user->getDisplayName(); $userDisplayName = $user->getDisplayName();
$userEmail = $user->getEMailAddress(); $userEmail = $user->getEMailAddress();
$uid = (string) $uid; $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 ( if (
strtolower($uid) === $lowerSearch || strtolower($uid) === $lowerSearch ||
strtolower($userDisplayName) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch ||
@ -117,6 +150,7 @@ class UserPlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_USER, 'shareType' => IShare::TYPE_USER,
'shareWith' => $uid, 'shareWith' => $uid,
], ],
'status' => $status,
]; ];
} else { } else {
$addToWideResults = false; $addToWideResults = false;
@ -138,6 +172,7 @@ class UserPlugin implements ISearchPlugin {
'shareType' => IShare::TYPE_USER, 'shareType' => IShare::TYPE_USER,
'shareWith' => $uid, 'shareWith' => $uid,
], ],
'status' => $status,
]; ];
} }
} }
@ -157,12 +192,26 @@ class UserPlugin implements ISearchPlugin {
} }
if ($addUser) { 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'][] = [ $result['exact'][] = [
'label' => $user->getDisplayName(), 'label' => $user->getDisplayName(),
'value' => [ 'value' => [
'shareType' => IShare::TYPE_USER, 'shareType' => IShare::TYPE_USER,
'shareWith' => $user->getUID(), 'shareWith' => $user->getUID(),
], ],
'status' => $status,
]; ];
} }
} }

View File

@ -33,6 +33,7 @@ use OCP\IUser;
use OCP\IUserManager; use OCP\IUserManager;
use OCP\IUserSession; use OCP\IUserSession;
use OCP\Share\IShare; use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
use Test\TestCase; use Test\TestCase;
class UserPluginTest extends TestCase { class UserPluginTest extends TestCase {
@ -48,6 +49,9 @@ class UserPluginTest extends TestCase {
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
protected $session; protected $session;
/** @var IUserStatusManager|\PHPUnit\Framework\MockObject\MockObject */
protected $userStatusManager;
/** @var UserPlugin */ /** @var UserPlugin */
protected $plugin; protected $plugin;
@ -74,6 +78,8 @@ class UserPluginTest extends TestCase {
$this->session = $this->createMock(IUserSession::class); $this->session = $this->createMock(IUserSession::class);
$this->userStatusManager = $this->createMock(IUserStatusManager::class);
$this->searchResult = new SearchResult(); $this->searchResult = new SearchResult();
$this->user = $this->getUserMock('admin', 'Administrator'); $this->user = $this->getUserMock('admin', 'Administrator');
@ -86,7 +92,8 @@ class UserPluginTest extends TestCase {
$this->config, $this->config,
$this->userManager, $this->userManager,
$this->groupManager, $this->groupManager,
$this->session $this->session,
$this->userStatusManager
); );
} }
@ -144,13 +151,13 @@ class UserPluginTest extends TestCase {
[ [
'test', false, true, [], [], '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'), ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', false, false, [], [], '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'), ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
@ -164,13 +171,13 @@ class UserPluginTest extends TestCase {
[ [
'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]], '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'), ], [], true, $this->getUserMock('test', 'Test'),
], ],
[ [
'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]], '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'), ], [], 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, true,
false, false,
@ -212,8 +219,8 @@ 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' => []],
['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []],
], ],
false, false,
false, false,
@ -243,11 +250,11 @@ class UserPluginTest extends TestCase {
$this->getUserMock('test2', 'Test Two'), $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 One', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test1'], 'status' => []],
['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []],
], ],
false, false,
false, false,
@ -263,7 +270,7 @@ class UserPluginTest extends TestCase {
$this->getUserMock('test2', 'Test Two'), $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, 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, true,
false, false,
@ -318,8 +325,8 @@ 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' => []],
['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2']], ['label' => 'Test Two', 'value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test2'], 'status' => []],
], ],
false, false,
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,
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, true,
@ -611,10 +618,10 @@ class UserPluginTest extends TestCase {
}, $matchingUsers); }, $matchingUsers);
$mappedResultExact = array_map(function ($user) { $mappedResultExact = array_map(function ($user) {
return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user]]; return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user], 'status' => []];
}, $result['exact']); }, $result['exact']);
$mappedResultWide = array_map(function ($user) { $mappedResultWide = array_map(function ($user) {
return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user]]; return ['label' => $user, 'value' => ['shareType' => 0, 'shareWith' => $user], 'status' => []];
}, $result['wide']); }, $result['wide']);
$this->userManager->expects($this->once()) $this->userManager->expects($this->once())