Add an endpoint to search for accounts based on phone number

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2020-12-02 14:11:47 +01:00
parent eaba155a09
commit fe9c46e595
No known key found for this signature in database
GPG Key ID: 7076EA9751AACDDA
5 changed files with 112 additions and 3 deletions

View File

@ -48,6 +48,7 @@ return [
// Users
['root' => '/cloud', 'name' => 'Users#getUsers', 'url' => '/users', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getUsersDetails', 'url' => '/users/details', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#searchByPhoneNumbers', 'url' => '/users/search/by-phone', 'verb' => 'POST'],
['root' => '/cloud', 'name' => 'Users#addUser', 'url' => '/users', 'verb' => 'POST'],
['root' => '/cloud', 'name' => 'Users#getUser', 'url' => '/users/{userId}', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getCurrentUser', 'url' => '/user', 'verb' => 'GET'],

View File

@ -41,6 +41,10 @@ declare(strict_types=1);
namespace OCA\Provisioning_API\Controller;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use OC\Accounts\AccountManager;
use OC\Authentication\Token\RemoteWipe;
use OC\HintException;
@ -51,11 +55,13 @@ use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\Federation\ICloudIdManager;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
@ -68,6 +74,10 @@ class UsersController extends AUserData {
/** @var IAppManager */
private $appManager;
/** @var ICloudIdManager */
protected $cloudIdManager;
/** @var IURLGenerator */
protected $urlGenerator;
/** @var ILogger */
private $logger;
/** @var IFactory */
@ -91,6 +101,8 @@ class UsersController extends AUserData {
IGroupManager $groupManager,
IUserSession $userSession,
AccountManager $accountManager,
ICloudIdManager $cloudIdManager,
IURLGenerator $urlGenerator,
ILogger $logger,
IFactory $l10nFactory,
NewUserMailHelper $newUserMailHelper,
@ -108,6 +120,8 @@ class UsersController extends AUserData {
$l10nFactory);
$this->appManager = $appManager;
$this->cloudIdManager = $cloudIdManager;
$this->urlGenerator = $urlGenerator;
$this->logger = $logger;
$this->l10nFactory = $l10nFactory;
$this->newUserMailHelper = $newUserMailHelper;
@ -202,6 +216,54 @@ class UsersController extends AUserData {
]);
}
/**
* @NoAdminRequired
* @NoSubAdminRequired
*
* @param string $location
* @param array $search
* @return DataResponse
*/
public function searchByPhoneNumbers(string $location, array $search): DataResponse {
$phoneUtil = PhoneNumberUtil::getInstance();
$normalizedNumberToKey = [];
foreach ($search as $key => $phoneNumbers) {
foreach ($phoneNumbers as $phone) {
try {
$phoneNumber = $phoneUtil->parse($phone, $location);
if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
$normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
$normalizedNumberToKey[$normalizedNumber] = (string) $key;
}
} catch (NumberParseException $e) {
}
}
}
$phoneNumbers = array_keys($normalizedNumberToKey);
if (empty($phoneNumbers)) {
return new DataResponse();
}
$userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers);
if (empty($userMatches)) {
return new DataResponse();
}
$cloudUrl = $this->urlGenerator->getAbsoluteURL('/');
$matches = [];
foreach ($userMatches as $phone => $userId) {
$matches[$normalizedNumberToKey[$phone]] = $this->cloudIdManager->getCloudId($userId, $cloudUrl)->getId();
}
return new DataResponse($matches);
}
/**
* @throws OCSException
*/

View File

@ -52,11 +52,13 @@ use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudIdManager;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
@ -86,6 +88,10 @@ class UsersControllerTest extends TestCase {
protected $api;
/** @var AccountManager|MockObject */
protected $accountManager;
/** @var ICloudIdManager|MockObject */
protected $cloudIdManager;
/** @var IURLGenerator|MockObject */
protected $urlGenerator;
/** @var IRequest|MockObject */
protected $request;
/** @var IFactory|MockObject */
@ -112,6 +118,8 @@ class UsersControllerTest extends TestCase {
$this->logger = $this->createMock(ILogger::class);
$this->request = $this->createMock(IRequest::class);
$this->accountManager = $this->createMock(AccountManager::class);
$this->cloudIdManager = $this->createMock(ICloudIdManager::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->l10nFactory = $this->createMock(IFactory::class);
$this->newUserMailHelper = $this->createMock(NewUserMailHelper::class);
$this->federatedShareProviderFactory = $this->createMock(FederatedShareProviderFactory::class);
@ -129,6 +137,8 @@ class UsersControllerTest extends TestCase {
$this->groupManager,
$this->userSession,
$this->accountManager,
$this->cloudIdManager,
$this->urlGenerator,
$this->logger,
$this->l10nFactory,
$this->newUserMailHelper,
@ -382,7 +392,7 @@ class UsersControllerTest extends TestCase {
}
public function testAddUserSuccessfulWithDisplayName() {
$api = $this->getMockBuilder('OCA\Provisioning_API\Controller\UsersController')
$api = $this->getMockBuilder(UsersController::class)
->setConstructorArgs([
'provisioning_api',
$this->request,
@ -392,6 +402,8 @@ class UsersControllerTest extends TestCase {
$this->groupManager,
$this->userSession,
$this->accountManager,
$this->cloudIdManager,
$this->urlGenerator,
$this->logger,
$this->l10nFactory,
$this->newUserMailHelper,
@ -3163,7 +3175,7 @@ class UsersControllerTest extends TestCase {
->willReturn($user);
/** @var UsersController | MockObject $api */
$api = $this->getMockBuilder('OCA\Provisioning_API\Controller\UsersController')
$api = $this->getMockBuilder(UsersController::class)
->setConstructorArgs([
'provisioning_api',
$this->request,
@ -3173,6 +3185,8 @@ class UsersControllerTest extends TestCase {
$this->groupManager,
$this->userSession,
$this->accountManager,
$this->cloudIdManager,
$this->urlGenerator,
$this->logger,
$this->l10nFactory,
$this->newUserMailHelper,
@ -3228,7 +3242,7 @@ class UsersControllerTest extends TestCase {
public function testGetUser() {
/** @var UsersController | MockObject $api */
$api = $this->getMockBuilder('OCA\Provisioning_API\Controller\UsersController')
$api = $this->getMockBuilder(UsersController::class)
->setConstructorArgs([
'provisioning_api',
$this->request,
@ -3238,6 +3252,8 @@ class UsersControllerTest extends TestCase {
$this->groupManager,
$this->userSession,
$this->accountManager,
$this->cloudIdManager,
$this->urlGenerator,
$this->logger,
$this->l10nFactory,
$this->newUserMailHelper,

View File

@ -34,6 +34,7 @@ use OCA\Settings\BackgroundJobs\VerifyUserData;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\BackgroundJob\IJobList;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
use Psr\Log\LoggerInterface;
@ -171,6 +172,24 @@ class AccountManager implements IAccountManager {
return $userDataArray;
}
public function searchUsers(string $property, array $values): array {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from($this->dataTable)
->where($query->expr()->eq('name', $query->createNamedParameter($property)))
->andWhere($query->expr()->in('value', $query->createNamedParameter($values, IQueryBuilder::PARAM_STR_ARRAY)));
$result = $query->execute();
$matches = [];
while ($row = $result->fetch()) {
$matches[$row['value']] = $row['uid'];
}
$result->closeCursor();
return $matches;
}
/**
* check if we need to ask the server for email verification, if yes we create a cronjob
*

View File

@ -65,4 +65,15 @@ interface IAccountManager {
* @return IAccount
*/
public function getAccount(IUser $user): IAccount;
/**
* Search for users based on account data
*
* @param string $property
* @param string[] $values
* @return array
*
* @since 21.0.0
*/
public function searchUsers(string $property, array $values): array;
}