Merge pull request #24486 from nextcloud/feature/noid/phone-number-validation
Phone number validation and search
This commit is contained in:
commit
86a3b7e7bf
2
3rdparty
2
3rdparty
|
@ -1 +1 @@
|
|||
Subproject commit e287243b8eeaf72443b841ace3b1788e85a5aacd
|
||||
Subproject commit 27a56c5bb9d0ec514a8fb22044fd5f03a51ea2a5
|
|
@ -26,6 +26,7 @@
|
|||
namespace OCA\DAV\CardDAV;
|
||||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IImage;
|
||||
use OCP\IUser;
|
||||
use Sabre\VObject\Component\VCard;
|
||||
|
@ -62,8 +63,8 @@ class Converter {
|
|||
|
||||
$publish = false;
|
||||
|
||||
if ($image !== null && isset($userData[AccountManager::PROPERTY_AVATAR])) {
|
||||
$userData[AccountManager::PROPERTY_AVATAR]['value'] = true;
|
||||
if ($image !== null && isset($userData[IAccountManager::PROPERTY_AVATAR])) {
|
||||
$userData[IAccountManager::PROPERTY_AVATAR]['value'] = true;
|
||||
}
|
||||
|
||||
foreach ($userData as $property => $value) {
|
||||
|
@ -76,28 +77,28 @@ class Converter {
|
|||
if ($shareWithTrustedServers && !$emptyValue) {
|
||||
$publish = true;
|
||||
switch ($property) {
|
||||
case AccountManager::PROPERTY_DISPLAYNAME:
|
||||
case IAccountManager::PROPERTY_DISPLAYNAME:
|
||||
$vCard->add(new Text($vCard, 'FN', $value['value']));
|
||||
$vCard->add(new Text($vCard, 'N', $this->splitFullName($value['value'])));
|
||||
break;
|
||||
case AccountManager::PROPERTY_AVATAR:
|
||||
case IAccountManager::PROPERTY_AVATAR:
|
||||
if ($image !== null) {
|
||||
$vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
|
||||
}
|
||||
break;
|
||||
case AccountManager::PROPERTY_EMAIL:
|
||||
case IAccountManager::PROPERTY_EMAIL:
|
||||
$vCard->add(new Text($vCard, 'EMAIL', $value['value'], ['TYPE' => 'OTHER']));
|
||||
break;
|
||||
case AccountManager::PROPERTY_WEBSITE:
|
||||
case IAccountManager::PROPERTY_WEBSITE:
|
||||
$vCard->add(new Text($vCard, 'URL', $value['value']));
|
||||
break;
|
||||
case AccountManager::PROPERTY_PHONE:
|
||||
case IAccountManager::PROPERTY_PHONE:
|
||||
$vCard->add(new Text($vCard, 'TEL', $value['value'], ['TYPE' => 'OTHER']));
|
||||
break;
|
||||
case AccountManager::PROPERTY_ADDRESS:
|
||||
case IAccountManager::PROPERTY_ADDRESS:
|
||||
$vCard->add(new Text($vCard, 'ADR', $value['value'], ['TYPE' => 'OTHER']));
|
||||
break;
|
||||
case AccountManager::PROPERTY_TWITTER:
|
||||
case IAccountManager::PROPERTY_TWITTER:
|
||||
$vCard->add(new Text($vCard, 'X-SOCIALPROFILE', $value['value'], ['TYPE' => 'TWITTER']));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,14 @@ namespace OCA\DAV\Tests\unit\CardDAV;
|
|||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OCA\DAV\CardDAV\Converter;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IImage;
|
||||
use OCP\IUser;
|
||||
use Test\TestCase;
|
||||
|
||||
class ConverterTest extends TestCase {
|
||||
|
||||
/** @var AccountManager | \PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var AccountManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $accountManager;
|
||||
|
||||
protected function setUp(): void {
|
||||
|
@ -49,36 +50,36 @@ class ConverterTest extends TestCase {
|
|||
->disableOriginalConstructor()->getMock();
|
||||
$accountManager->expects($this->any())->method('getUser')->willReturn(
|
||||
[
|
||||
AccountManager::PROPERTY_DISPLAYNAME =>
|
||||
IAccountManager::PROPERTY_DISPLAYNAME =>
|
||||
[
|
||||
'value' => $user->getDisplayName(),
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
],
|
||||
AccountManager::PROPERTY_ADDRESS =>
|
||||
IAccountManager::PROPERTY_ADDRESS =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_WEBSITE =>
|
||||
IAccountManager::PROPERTY_WEBSITE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_EMAIL =>
|
||||
IAccountManager::PROPERTY_EMAIL =>
|
||||
[
|
||||
'value' => $user->getEMailAddress(),
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
],
|
||||
AccountManager::PROPERTY_AVATAR =>
|
||||
IAccountManager::PROPERTY_AVATAR =>
|
||||
[
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY
|
||||
],
|
||||
AccountManager::PROPERTY_PHONE =>
|
||||
IAccountManager::PROPERTY_PHONE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_TWITTER =>
|
||||
IAccountManager::PROPERTY_TWITTER =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace OCA\DAV\Tests\unit\CardDAV;
|
|||
use OC\Accounts\AccountManager;
|
||||
use OCA\DAV\CardDAV\CardDavBackend;
|
||||
use OCA\DAV\CardDAV\SyncService;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\ILogger;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
|
@ -132,36 +133,36 @@ class SyncServiceTest extends TestCase {
|
|||
$accountManager = $this->getMockBuilder(AccountManager::class)->disableOriginalConstructor()->getMock();
|
||||
$accountManager->expects($this->any())->method('getUser')
|
||||
->willReturn([
|
||||
AccountManager::PROPERTY_DISPLAYNAME =>
|
||||
IAccountManager::PROPERTY_DISPLAYNAME =>
|
||||
[
|
||||
'value' => $user->getDisplayName(),
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
],
|
||||
AccountManager::PROPERTY_ADDRESS =>
|
||||
IAccountManager::PROPERTY_ADDRESS =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_WEBSITE =>
|
||||
IAccountManager::PROPERTY_WEBSITE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_EMAIL =>
|
||||
IAccountManager::PROPERTY_EMAIL =>
|
||||
[
|
||||
'value' => $user->getEMailAddress(),
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
],
|
||||
AccountManager::PROPERTY_AVATAR =>
|
||||
IAccountManager::PROPERTY_AVATAR =>
|
||||
[
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY
|
||||
],
|
||||
AccountManager::PROPERTY_PHONE =>
|
||||
IAccountManager::PROPERTY_PHONE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
],
|
||||
AccountManager::PROPERTY_TWITTER =>
|
||||
IAccountManager::PROPERTY_TWITTER =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
|
|
|
@ -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'],
|
||||
|
|
|
@ -35,6 +35,7 @@ use OC\Accounts\AccountManager;
|
|||
use OC\User\Backend;
|
||||
use OC\User\NoUserException;
|
||||
use OC_Helper;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\AppFramework\OCS\OCSException;
|
||||
use OCP\AppFramework\OCS\OCSNotFoundException;
|
||||
use OCP\AppFramework\OCSController;
|
||||
|
@ -135,12 +136,12 @@ abstract class AUserData extends OCSController {
|
|||
$data['backend'] = $targetUserObject->getBackendClassName();
|
||||
$data['subadmin'] = $this->getUserSubAdminGroupsData($targetUserObject->getUID());
|
||||
$data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
|
||||
$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
|
||||
$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
|
||||
$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
|
||||
$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
|
||||
$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
|
||||
$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
|
||||
$data[IAccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
|
||||
$data[IAccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
|
||||
$data[IAccountManager::PROPERTY_PHONE] = $userAccount[IAccountManager::PROPERTY_PHONE]['value'];
|
||||
$data[IAccountManager::PROPERTY_ADDRESS] = $userAccount[IAccountManager::PROPERTY_ADDRESS]['value'];
|
||||
$data[IAccountManager::PROPERTY_WEBSITE] = $userAccount[IAccountManager::PROPERTY_WEBSITE]['value'];
|
||||
$data[IAccountManager::PROPERTY_TWITTER] = $userAccount[IAccountManager::PROPERTY_TWITTER]['value'];
|
||||
$data['groups'] = $gids;
|
||||
$data['language'] = $this->l10nFactory->getUserLanguage($targetUserObject);
|
||||
$data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
|
||||
|
|
|
@ -41,12 +41,18 @@ 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;
|
||||
use OCA\Provisioning_API\FederatedShareProviderFactory;
|
||||
use OCA\Settings\Mailer\NewUserMailHelper;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCS\OCSException;
|
||||
use OCP\AppFramework\OCS\OCSForbiddenException;
|
||||
|
@ -55,6 +61,7 @@ use OCP\IGroup;
|
|||
use OCP\IGroupManager;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
|
@ -67,6 +74,8 @@ class UsersController extends AUserData {
|
|||
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
/** @var IURLGenerator */
|
||||
protected $urlGenerator;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
/** @var IFactory */
|
||||
|
@ -90,6 +99,7 @@ class UsersController extends AUserData {
|
|||
IGroupManager $groupManager,
|
||||
IUserSession $userSession,
|
||||
AccountManager $accountManager,
|
||||
IURLGenerator $urlGenerator,
|
||||
ILogger $logger,
|
||||
IFactory $l10nFactory,
|
||||
NewUserMailHelper $newUserMailHelper,
|
||||
|
@ -107,6 +117,7 @@ class UsersController extends AUserData {
|
|||
$l10nFactory);
|
||||
|
||||
$this->appManager = $appManager;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->logger = $logger;
|
||||
$this->l10nFactory = $l10nFactory;
|
||||
$this->newUserMailHelper = $newUserMailHelper;
|
||||
|
@ -201,6 +212,65 @@ 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();
|
||||
|
||||
if ($phoneUtil->getCountryCodeForRegion($location) === 0) {
|
||||
// Not a valid region code
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$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 = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
|
||||
if (strpos($cloudUrl, 'http://') === 0) {
|
||||
$cloudUrl = substr($cloudUrl, strlen('http://'));
|
||||
} elseif (strpos($cloudUrl, 'https://') === 0) {
|
||||
$cloudUrl = substr($cloudUrl, strlen('https://'));
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
foreach ($userMatches as $phone => $userId) {
|
||||
// Not using the ICloudIdManager as that would run a search for each contact to find the display name in the address book
|
||||
$matches[$normalizedNumberToKey[$phone]] = $userId . '@' . $cloudUrl;
|
||||
}
|
||||
|
||||
return new DataResponse($matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws OCSException
|
||||
*/
|
||||
|
@ -431,17 +501,17 @@ class UsersController extends AUserData {
|
|||
|
||||
// Editing self (display, email)
|
||||
if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
|
||||
$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = AccountManager::PROPERTY_EMAIL;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
|
||||
}
|
||||
|
||||
if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
|
||||
$shareProvider = $this->federatedShareProviderFactory->get();
|
||||
if ($shareProvider->isLookupServerUploadEnabled()) {
|
||||
$permittedFields[] = AccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,8 +544,8 @@ class UsersController extends AUserData {
|
|||
// Editing self (display, email)
|
||||
if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
|
||||
$permittedFields[] = 'display';
|
||||
$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = AccountManager::PROPERTY_EMAIL;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
|
||||
}
|
||||
|
||||
$permittedFields[] = 'password';
|
||||
|
@ -492,10 +562,10 @@ class UsersController extends AUserData {
|
|||
if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
|
||||
$shareProvider = $this->federatedShareProviderFactory->get();
|
||||
if ($shareProvider->isLookupServerUploadEnabled()) {
|
||||
$permittedFields[] = AccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,15 +580,15 @@ class UsersController extends AUserData {
|
|||
|| $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
|
||||
// They have permissions over the user
|
||||
$permittedFields[] = 'display';
|
||||
$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = AccountManager::PROPERTY_EMAIL;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
|
||||
$permittedFields[] = 'password';
|
||||
$permittedFields[] = 'language';
|
||||
$permittedFields[] = 'locale';
|
||||
$permittedFields[] = AccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = AccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = 'quota';
|
||||
} else {
|
||||
// No rights
|
||||
|
@ -532,7 +602,7 @@ class UsersController extends AUserData {
|
|||
// Process the edit
|
||||
switch ($key) {
|
||||
case 'display':
|
||||
case AccountManager::PROPERTY_DISPLAYNAME:
|
||||
case IAccountManager::PROPERTY_DISPLAYNAME:
|
||||
$targetUser->setDisplayName($value);
|
||||
break;
|
||||
case 'quota':
|
||||
|
@ -577,21 +647,25 @@ class UsersController extends AUserData {
|
|||
}
|
||||
$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
|
||||
break;
|
||||
case AccountManager::PROPERTY_EMAIL:
|
||||
case IAccountManager::PROPERTY_EMAIL:
|
||||
if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
|
||||
$targetUser->setEMailAddress($value);
|
||||
} else {
|
||||
throw new OCSException('', 102);
|
||||
}
|
||||
break;
|
||||
case AccountManager::PROPERTY_PHONE:
|
||||
case AccountManager::PROPERTY_ADDRESS:
|
||||
case AccountManager::PROPERTY_WEBSITE:
|
||||
case AccountManager::PROPERTY_TWITTER:
|
||||
case IAccountManager::PROPERTY_PHONE:
|
||||
case IAccountManager::PROPERTY_ADDRESS:
|
||||
case IAccountManager::PROPERTY_WEBSITE:
|
||||
case IAccountManager::PROPERTY_TWITTER:
|
||||
$userAccount = $this->accountManager->getUser($targetUser);
|
||||
if ($userAccount[$key]['value'] !== $value) {
|
||||
$userAccount[$key]['value'] = $value;
|
||||
$this->accountManager->updateUser($targetUser, $userAccount);
|
||||
try {
|
||||
$this->accountManager->updateUser($targetUser, $userAccount, true);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new OCSException('Invalid ' . $e->getMessage(), 102);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -35,6 +35,7 @@ use OC\Group\Manager;
|
|||
use OC\SubAdmin;
|
||||
use OC\User\NoUserException;
|
||||
use OCA\Provisioning_API\Controller\GroupsController;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
|
@ -185,10 +186,10 @@ class GroupsControllerTest extends \Test\TestCase {
|
|||
->method('getUser')
|
||||
->willReturnCallback(function (IUser $user) {
|
||||
return [
|
||||
AccountManager::PROPERTY_PHONE => ['value' => '0800-call-' . $user->getUID()],
|
||||
AccountManager::PROPERTY_ADDRESS => ['value' => 'Holzweg 99, 0601 Herrera, Panama'],
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'https://' . $user->getUid() . '.pa'],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => '@' . $user->getUID()],
|
||||
IAccountManager::PROPERTY_PHONE => ['value' => '0800-call-' . $user->getUID()],
|
||||
IAccountManager::PROPERTY_ADDRESS => ['value' => 'Holzweg 99, 0601 Herrera, Panama'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'https://' . $user->getUid() . '.pa'],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => '@' . $user->getUID()],
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ use OCA\FederatedFileSharing\FederatedShareProvider;
|
|||
use OCA\Provisioning_API\Controller\UsersController;
|
||||
use OCA\Provisioning_API\FederatedShareProviderFactory;
|
||||
use OCA\Settings\Mailer\NewUserMailHelper;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
@ -56,6 +57,7 @@ use OCP\IGroup;
|
|||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
|
@ -85,6 +87,8 @@ class UsersControllerTest extends TestCase {
|
|||
protected $api;
|
||||
/** @var AccountManager|MockObject */
|
||||
protected $accountManager;
|
||||
/** @var IURLGenerator|MockObject */
|
||||
protected $urlGenerator;
|
||||
/** @var IRequest|MockObject */
|
||||
protected $request;
|
||||
/** @var IFactory|MockObject */
|
||||
|
@ -111,6 +115,7 @@ class UsersControllerTest extends TestCase {
|
|||
$this->logger = $this->createMock(ILogger::class);
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
$this->accountManager = $this->createMock(AccountManager::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);
|
||||
|
@ -128,6 +133,7 @@ class UsersControllerTest extends TestCase {
|
|||
$this->groupManager,
|
||||
$this->userSession,
|
||||
$this->accountManager,
|
||||
$this->urlGenerator,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->newUserMailHelper,
|
||||
|
@ -381,7 +387,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,
|
||||
|
@ -391,6 +397,7 @@ class UsersControllerTest extends TestCase {
|
|||
$this->groupManager,
|
||||
$this->userSession,
|
||||
$this->accountManager,
|
||||
$this->urlGenerator,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->newUserMailHelper,
|
||||
|
@ -993,10 +1000,10 @@ class UsersControllerTest extends TestCase {
|
|||
->with($targetUser)
|
||||
->willReturn(
|
||||
[
|
||||
AccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
AccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
IAccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
]
|
||||
);
|
||||
$this->config
|
||||
|
@ -1162,10 +1169,10 @@ class UsersControllerTest extends TestCase {
|
|||
->with($targetUser)
|
||||
->willReturn(
|
||||
[
|
||||
AccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
AccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
IAccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -1333,10 +1340,10 @@ class UsersControllerTest extends TestCase {
|
|||
->with($targetUser)
|
||||
->willReturn(
|
||||
[
|
||||
AccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
AccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'],
|
||||
IAccountManager::PROPERTY_PHONE => ['value' => 'phone'],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'],
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -1370,6 +1377,47 @@ class UsersControllerTest extends TestCase {
|
|||
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
|
||||
}
|
||||
|
||||
public function dataSearchByPhoneNumbers(): array {
|
||||
return [
|
||||
'Invalid country' => ['Not a country code', ['12345' => ['NaN']], 400, null, null, []],
|
||||
'No number to search' => ['DE', ['12345' => ['NaN']], 200, null, null, []],
|
||||
'Valid number but no match' => ['DE', ['12345' => ['0711 / 25 24 28-90']], 200, ['+4971125242890'], [], []],
|
||||
'Invalid number' => ['FR', ['12345' => ['0711 / 25 24 28-90']], 200, null, null, []],
|
||||
'Invalid and valid number' => ['DE', ['12345' => ['NaN', '0711 / 25 24 28-90']], 200, ['+4971125242890'], [], []],
|
||||
'Valid and invalid number' => ['DE', ['12345' => ['0711 / 25 24 28-90', 'NaN']], 200, ['+4971125242890'], [], []],
|
||||
'Valid number and a match' => ['DE', ['12345' => ['0711 / 25 24 28-90']], 200, ['+4971125242890'], ['+4971125242890' => 'admin'], ['12345' => 'admin@localhost']],
|
||||
'Same number twice, later hits' => ['DE', ['12345' => ['0711 / 25 24 28-90'], '23456' => ['0711 / 25 24 28-90']], 200, ['+4971125242890'], ['+4971125242890' => 'admin'], ['23456' => 'admin@localhost']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataSearchByPhoneNumbers
|
||||
* @param string $location
|
||||
* @param array $search
|
||||
* @param int $status
|
||||
* @param array $expected
|
||||
*/
|
||||
public function testSearchByPhoneNumbers(string $location, array $search, int $status, ?array $searchUsers, ?array $userMatches, array $expected) {
|
||||
if ($searchUsers === null) {
|
||||
$this->accountManager->expects($this->never())
|
||||
->method('searchUsers');
|
||||
} else {
|
||||
$this->accountManager->expects($this->once())
|
||||
->method('searchUsers')
|
||||
->with(IAccountManager::PROPERTY_PHONE, $searchUsers)
|
||||
->willReturn($userMatches);
|
||||
}
|
||||
|
||||
$this->urlGenerator->method('getAbsoluteURL')
|
||||
->with('/')
|
||||
->willReturn('https://localhost/');
|
||||
|
||||
$response = $this->api->searchByPhoneNumbers($location, $search);
|
||||
|
||||
self::assertEquals($status, $response->getStatus());
|
||||
self::assertEquals($expected, $response->getData());
|
||||
}
|
||||
|
||||
public function testEditUserRegularUserSelfEditChangeDisplayName() {
|
||||
$loggedInUser = $this->getMockBuilder(IUser::class)
|
||||
->disableOriginalConstructor()
|
||||
|
@ -3162,7 +3210,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,
|
||||
|
@ -3172,6 +3220,7 @@ class UsersControllerTest extends TestCase {
|
|||
$this->groupManager,
|
||||
$this->userSession,
|
||||
$this->accountManager,
|
||||
$this->urlGenerator,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->newUserMailHelper,
|
||||
|
@ -3227,7 +3276,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,
|
||||
|
@ -3237,6 +3286,7 @@ class UsersControllerTest extends TestCase {
|
|||
$this->groupManager,
|
||||
$this->userSession,
|
||||
$this->accountManager,
|
||||
$this->urlGenerator,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->newUserMailHelper,
|
||||
|
@ -3566,22 +3616,22 @@ class UsersControllerTest extends TestCase {
|
|||
return [
|
||||
[false, false, []],
|
||||
[false, true, [
|
||||
AccountManager::PROPERTY_PHONE,
|
||||
AccountManager::PROPERTY_ADDRESS,
|
||||
AccountManager::PROPERTY_WEBSITE,
|
||||
AccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
]],
|
||||
[ true, false, [
|
||||
AccountManager::PROPERTY_DISPLAYNAME,
|
||||
AccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::PROPERTY_DISPLAYNAME,
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
]],
|
||||
[ true, true ,[
|
||||
AccountManager::PROPERTY_DISPLAYNAME,
|
||||
AccountManager::PROPERTY_EMAIL,
|
||||
AccountManager::PROPERTY_PHONE,
|
||||
AccountManager::PROPERTY_ADDRESS,
|
||||
AccountManager::PROPERTY_WEBSITE,
|
||||
AccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_DISPLAYNAME,
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
]]
|
||||
];
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
if (_.isUndefined(data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.status && data.status === 'error') {
|
||||
OC.Notification.show(data.data.message, { type: 'error' });
|
||||
}
|
||||
|
||||
if (_.isUndefined(data.data)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -47,4 +52,4 @@
|
|||
OC.Settings = OC.Settings || {};
|
||||
|
||||
OC.Settings.UserSettings = UserSettings;
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
namespace OCA\Settings\BackgroundJobs;
|
||||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\BackgroundJob\Job;
|
||||
|
@ -114,11 +115,11 @@ class VerifyUserData extends Job {
|
|||
$try = (int)$argument['try'] + 1;
|
||||
|
||||
switch ($argument['type']) {
|
||||
case AccountManager::PROPERTY_WEBSITE:
|
||||
case IAccountManager::PROPERTY_WEBSITE:
|
||||
$result = $this->verifyWebsite($argument);
|
||||
break;
|
||||
case AccountManager::PROPERTY_TWITTER:
|
||||
case AccountManager::PROPERTY_EMAIL:
|
||||
case IAccountManager::PROPERTY_TWITTER:
|
||||
case IAccountManager::PROPERTY_EMAIL:
|
||||
$result = $this->verifyViaLookupServer($argument, $argument['type']);
|
||||
break;
|
||||
default:
|
||||
|
@ -164,9 +165,9 @@ class VerifyUserData extends Job {
|
|||
$userData = $this->accountManager->getUser($user);
|
||||
|
||||
if ($publishedCodeSanitized === $argument['verificationCode']) {
|
||||
$userData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFIED;
|
||||
$userData[IAccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFIED;
|
||||
} else {
|
||||
$userData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::NOT_VERIFIED;
|
||||
$userData[IAccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::NOT_VERIFIED;
|
||||
}
|
||||
|
||||
$this->accountManager->updateUser($user, $userData);
|
||||
|
|
|
@ -752,6 +752,7 @@ Raw output
|
|||
PhpOutputBuffering::class => ['pass' => $phpOutputBuffering->run(), 'description' => $phpOutputBuffering->description(), 'severity' => $phpOutputBuffering->severity()],
|
||||
LegacySSEKeyFormat::class => ['pass' => $legacySSEKeyFormat->run(), 'description' => $legacySSEKeyFormat->description(), 'severity' => $legacySSEKeyFormat->severity(), 'linkToDocumentation' => $legacySSEKeyFormat->linkToDocumentation()],
|
||||
CheckUserCertificates::class => ['pass' => $checkUserCertificates->run(), 'description' => $checkUserCertificates->description(), 'severity' => $checkUserCertificates->severity(), 'elements' => $checkUserCertificates->elements()],
|
||||
'isDefaultPhoneRegionSet' => $this->config->getSystemValueString('default_phone_region', '') !== '',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
|
@ -30,7 +32,6 @@
|
|||
|
||||
// FIXME: disabled for now to be able to inject IGroupManager and also use
|
||||
// getSubAdmin()
|
||||
//declare(strict_types=1);
|
||||
|
||||
namespace OCA\Settings\Controller;
|
||||
|
||||
|
@ -46,6 +47,7 @@ use OCA\FederatedFileSharing\FederatedShareProvider;
|
|||
use OCA\Settings\BackgroundJobs\VerifyUserData;
|
||||
use OCA\Settings\Events\BeforeTemplateRenderedEvent;
|
||||
use OCA\User_LDAP\User_Proxy;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
|
@ -140,7 +142,7 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function usersListByGroup() {
|
||||
public function usersListByGroup(): TemplateResponse {
|
||||
return $this->usersList();
|
||||
}
|
||||
|
||||
|
@ -152,7 +154,7 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function usersList() {
|
||||
public function usersList(): TemplateResponse {
|
||||
$user = $this->userSession->getUser();
|
||||
$uid = $user->getUID();
|
||||
|
||||
|
@ -309,7 +311,7 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function canAdminChangeUserPasswords() {
|
||||
protected function canAdminChangeUserPasswords(): bool {
|
||||
$isEncryptionEnabled = $this->encryptionManager->isEnabled();
|
||||
try {
|
||||
$noUserSpecificEncryptionKeys = !$this->encryptionManager->getEncryptionModule()->needDetailedAccessList();
|
||||
|
@ -344,19 +346,19 @@ class UsersController extends Controller {
|
|||
* @param string $twitterScope
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function setUserSettings($avatarScope,
|
||||
$displayname,
|
||||
$displaynameScope,
|
||||
$phone,
|
||||
$phoneScope,
|
||||
$email,
|
||||
$emailScope,
|
||||
$website,
|
||||
$websiteScope,
|
||||
$address,
|
||||
$addressScope,
|
||||
$twitter,
|
||||
$twitterScope
|
||||
public function setUserSettings(string $avatarScope,
|
||||
string $displayname,
|
||||
string $displaynameScope,
|
||||
string $phone,
|
||||
string $phoneScope,
|
||||
string $email,
|
||||
string $emailScope,
|
||||
string $website,
|
||||
string $websiteScope,
|
||||
string $address,
|
||||
string $addressScope,
|
||||
string $twitter,
|
||||
string $twitterScope
|
||||
) {
|
||||
$email = strtolower($email);
|
||||
if (!empty($email) && !$this->mailer->validateMailAddress($email)) {
|
||||
|
@ -372,36 +374,40 @@ class UsersController extends Controller {
|
|||
}
|
||||
$user = $this->userSession->getUser();
|
||||
$data = $this->accountManager->getUser($user);
|
||||
$data[AccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
|
||||
$data[IAccountManager::PROPERTY_AVATAR] = ['scope' => $avatarScope];
|
||||
if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
|
||||
$data[AccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
|
||||
$data[AccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
|
||||
$data[IAccountManager::PROPERTY_DISPLAYNAME] = ['value' => $displayname, 'scope' => $displaynameScope];
|
||||
$data[IAccountManager::PROPERTY_EMAIL] = ['value' => $email, 'scope' => $emailScope];
|
||||
}
|
||||
if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
|
||||
$shareProvider = \OC::$server->query(FederatedShareProvider::class);
|
||||
if ($shareProvider->isLookupServerUploadEnabled()) {
|
||||
$data[AccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
|
||||
$data[AccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
|
||||
$data[AccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
|
||||
$data[AccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
|
||||
$data[IAccountManager::PROPERTY_WEBSITE] = ['value' => $website, 'scope' => $websiteScope];
|
||||
$data[IAccountManager::PROPERTY_ADDRESS] = ['value' => $address, 'scope' => $addressScope];
|
||||
$data[IAccountManager::PROPERTY_PHONE] = ['value' => $phone, 'scope' => $phoneScope];
|
||||
$data[IAccountManager::PROPERTY_TWITTER] = ['value' => $twitter, 'scope' => $twitterScope];
|
||||
}
|
||||
}
|
||||
try {
|
||||
$this->saveUserSettings($user, $data);
|
||||
$data = $this->saveUserSettings($user, $data);
|
||||
return new DataResponse(
|
||||
[
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'userId' => $user->getUID(),
|
||||
'avatarScope' => $data[AccountManager::PROPERTY_AVATAR]['scope'],
|
||||
'displayname' => $data[AccountManager::PROPERTY_DISPLAYNAME]['value'],
|
||||
'displaynameScope' => $data[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
|
||||
'email' => $data[AccountManager::PROPERTY_EMAIL]['value'],
|
||||
'emailScope' => $data[AccountManager::PROPERTY_EMAIL]['scope'],
|
||||
'website' => $data[AccountManager::PROPERTY_WEBSITE]['value'],
|
||||
'websiteScope' => $data[AccountManager::PROPERTY_WEBSITE]['scope'],
|
||||
'address' => $data[AccountManager::PROPERTY_ADDRESS]['value'],
|
||||
'addressScope' => $data[AccountManager::PROPERTY_ADDRESS]['scope'],
|
||||
'avatarScope' => $data[IAccountManager::PROPERTY_AVATAR]['scope'],
|
||||
'displayname' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['value'],
|
||||
'displaynameScope' => $data[IAccountManager::PROPERTY_DISPLAYNAME]['scope'],
|
||||
'phone' => $data[IAccountManager::PROPERTY_PHONE]['value'],
|
||||
'phoneScope' => $data[IAccountManager::PROPERTY_PHONE]['scope'],
|
||||
'email' => $data[IAccountManager::PROPERTY_EMAIL]['value'],
|
||||
'emailScope' => $data[IAccountManager::PROPERTY_EMAIL]['scope'],
|
||||
'website' => $data[IAccountManager::PROPERTY_WEBSITE]['value'],
|
||||
'websiteScope' => $data[IAccountManager::PROPERTY_WEBSITE]['scope'],
|
||||
'address' => $data[IAccountManager::PROPERTY_ADDRESS]['value'],
|
||||
'addressScope' => $data[IAccountManager::PROPERTY_ADDRESS]['scope'],
|
||||
'twitter' => $data[IAccountManager::PROPERTY_TWITTER]['value'],
|
||||
'twitterScope' => $data[IAccountManager::PROPERTY_TWITTER]['scope'],
|
||||
'message' => $this->l10n->t('Settings saved')
|
||||
]
|
||||
],
|
||||
|
@ -414,6 +420,13 @@ class UsersController extends Controller {
|
|||
'message' => $e->getMessage()
|
||||
],
|
||||
]);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return new DataResponse([
|
||||
'status' => 'error',
|
||||
'data' => [
|
||||
'message' => $e->getMessage()
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -421,34 +434,45 @@ class UsersController extends Controller {
|
|||
*
|
||||
* @param IUser $user
|
||||
* @param array $data
|
||||
* @return array
|
||||
* @throws ForbiddenException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function saveUserSettings(IUser $user, array $data) {
|
||||
protected function saveUserSettings(IUser $user, array $data): array {
|
||||
// keep the user back-end up-to-date with the latest display name and email
|
||||
// address
|
||||
$oldDisplayName = $user->getDisplayName();
|
||||
$oldDisplayName = is_null($oldDisplayName) ? '' : $oldDisplayName;
|
||||
if (isset($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
&& $oldDisplayName !== $data[AccountManager::PROPERTY_DISPLAYNAME]['value']
|
||||
if (isset($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
&& $oldDisplayName !== $data[IAccountManager::PROPERTY_DISPLAYNAME]['value']
|
||||
) {
|
||||
$result = $user->setDisplayName($data[AccountManager::PROPERTY_DISPLAYNAME]['value']);
|
||||
$result = $user->setDisplayName($data[IAccountManager::PROPERTY_DISPLAYNAME]['value']);
|
||||
if ($result === false) {
|
||||
throw new ForbiddenException($this->l10n->t('Unable to change full name'));
|
||||
}
|
||||
}
|
||||
|
||||
$oldEmailAddress = $user->getEMailAddress();
|
||||
$oldEmailAddress = is_null($oldEmailAddress) ? '' : strtolower($oldEmailAddress);
|
||||
if (isset($data[AccountManager::PROPERTY_EMAIL]['value'])
|
||||
&& $oldEmailAddress !== $data[AccountManager::PROPERTY_EMAIL]['value']
|
||||
if (isset($data[IAccountManager::PROPERTY_EMAIL]['value'])
|
||||
&& $oldEmailAddress !== $data[IAccountManager::PROPERTY_EMAIL]['value']
|
||||
) {
|
||||
// this is the only permission a backend provides and is also used
|
||||
// for the permission of setting a email address
|
||||
if (!$user->canChangeDisplayName()) {
|
||||
throw new ForbiddenException($this->l10n->t('Unable to change email address'));
|
||||
}
|
||||
$user->setEMailAddress($data[AccountManager::PROPERTY_EMAIL]['value']);
|
||||
$user->setEMailAddress($data[IAccountManager::PROPERTY_EMAIL]['value']);
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->accountManager->updateUser($user, $data, true);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
if ($e->getMessage() === IAccountManager::PROPERTY_PHONE) {
|
||||
throw new \InvalidArgumentException($this->l10n->t('Unable to set invalid phone number'));
|
||||
}
|
||||
throw new \InvalidArgumentException($this->l10n->t('Some account data was invalid'));
|
||||
}
|
||||
$this->accountManager->updateUser($user, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -479,26 +503,25 @@ class UsersController extends Controller {
|
|||
|
||||
switch ($account) {
|
||||
case 'verify-twitter':
|
||||
$accountData[AccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
||||
$accountData[IAccountManager::PROPERTY_TWITTER]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
||||
$msg = $this->l10n->t('In order to verify your Twitter account, post the following tweet on Twitter (please make sure to post it without any line breaks):');
|
||||
$code = $codeMd5;
|
||||
$type = AccountManager::PROPERTY_TWITTER;
|
||||
$data = $accountData[AccountManager::PROPERTY_TWITTER]['value'];
|
||||
$accountData[AccountManager::PROPERTY_TWITTER]['signature'] = $signature;
|
||||
$type = IAccountManager::PROPERTY_TWITTER;
|
||||
$accountData[IAccountManager::PROPERTY_TWITTER]['signature'] = $signature;
|
||||
break;
|
||||
case 'verify-website':
|
||||
$accountData[AccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
||||
$accountData[IAccountManager::PROPERTY_WEBSITE]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
||||
$msg = $this->l10n->t('In order to verify your Website, store the following content in your web-root at \'.well-known/CloudIdVerificationCode.txt\' (please make sure that the complete text is in one line):');
|
||||
$type = AccountManager::PROPERTY_WEBSITE;
|
||||
$data = $accountData[AccountManager::PROPERTY_WEBSITE]['value'];
|
||||
$accountData[AccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
|
||||
$type = IAccountManager::PROPERTY_WEBSITE;
|
||||
$accountData[IAccountManager::PROPERTY_WEBSITE]['signature'] = $signature;
|
||||
break;
|
||||
default:
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if ($onlyVerificationCode === false) {
|
||||
$this->accountManager->updateUser($user, $accountData);
|
||||
$accountData = $this->accountManager->updateUser($user, $accountData);
|
||||
$data = $accountData[$type]['value'];
|
||||
|
||||
$this->jobList->add(VerifyUserData::class,
|
||||
[
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
|
@ -33,6 +35,7 @@ namespace OCA\Settings\Settings\Personal;
|
|||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OCA\FederatedFileSharing\FederatedShareProvider;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\Files\FileInfo;
|
||||
|
@ -62,14 +65,6 @@ class PersonalInfo implements ISettings {
|
|||
/** @var IL10N */
|
||||
private $l;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param IUserManager $userManager
|
||||
* @param IGroupManager $groupManager
|
||||
* @param AccountManager $accountManager
|
||||
* @param IFactory $l10nFactory
|
||||
* @param IL10N $l
|
||||
*/
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
IUserManager $userManager,
|
||||
|
@ -88,11 +83,7 @@ class PersonalInfo implements ISettings {
|
|||
$this->l = $l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
|
||||
* @since 9.1
|
||||
*/
|
||||
public function getForm() {
|
||||
public function getForm(): TemplateResponse {
|
||||
$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
|
||||
$lookupServerUploadEnabled = false;
|
||||
if ($federatedFileSharingEnabled) {
|
||||
|
@ -126,23 +117,23 @@ class PersonalInfo implements ISettings {
|
|||
'quota' => $storageInfo['quota'],
|
||||
'avatarChangeSupported' => $user->canChangeAvatar(),
|
||||
'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
|
||||
'avatarScope' => $userData[AccountManager::PROPERTY_AVATAR]['scope'],
|
||||
'avatarScope' => $userData[IAccountManager::PROPERTY_AVATAR]['scope'],
|
||||
'displayNameChangeSupported' => $user->canChangeDisplayName(),
|
||||
'displayName' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'],
|
||||
'displayNameScope' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
|
||||
'email' => $userData[AccountManager::PROPERTY_EMAIL]['value'],
|
||||
'emailScope' => $userData[AccountManager::PROPERTY_EMAIL]['scope'],
|
||||
'emailVerification' => $userData[AccountManager::PROPERTY_EMAIL]['verified'],
|
||||
'phone' => $userData[AccountManager::PROPERTY_PHONE]['value'],
|
||||
'phoneScope' => $userData[AccountManager::PROPERTY_PHONE]['scope'],
|
||||
'address' => $userData[AccountManager::PROPERTY_ADDRESS]['value'],
|
||||
'addressScope' => $userData[AccountManager::PROPERTY_ADDRESS]['scope'],
|
||||
'website' => $userData[AccountManager::PROPERTY_WEBSITE]['value'],
|
||||
'websiteScope' => $userData[AccountManager::PROPERTY_WEBSITE]['scope'],
|
||||
'websiteVerification' => $userData[AccountManager::PROPERTY_WEBSITE]['verified'],
|
||||
'twitter' => $userData[AccountManager::PROPERTY_TWITTER]['value'],
|
||||
'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
|
||||
'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
|
||||
'displayName' => $userData[IAccountManager::PROPERTY_DISPLAYNAME]['value'],
|
||||
'displayNameScope' => $userData[IAccountManager::PROPERTY_DISPLAYNAME]['scope'],
|
||||
'email' => $userData[IAccountManager::PROPERTY_EMAIL]['value'],
|
||||
'emailScope' => $userData[IAccountManager::PROPERTY_EMAIL]['scope'],
|
||||
'emailVerification' => $userData[IAccountManager::PROPERTY_EMAIL]['verified'],
|
||||
'phone' => $userData[IAccountManager::PROPERTY_PHONE]['value'],
|
||||
'phoneScope' => $userData[IAccountManager::PROPERTY_PHONE]['scope'],
|
||||
'address' => $userData[IAccountManager::PROPERTY_ADDRESS]['value'],
|
||||
'addressScope' => $userData[IAccountManager::PROPERTY_ADDRESS]['scope'],
|
||||
'website' => $userData[IAccountManager::PROPERTY_WEBSITE]['value'],
|
||||
'websiteScope' => $userData[IAccountManager::PROPERTY_WEBSITE]['scope'],
|
||||
'websiteVerification' => $userData[IAccountManager::PROPERTY_WEBSITE]['verified'],
|
||||
'twitter' => $userData[IAccountManager::PROPERTY_TWITTER]['value'],
|
||||
'twitterScope' => $userData[IAccountManager::PROPERTY_TWITTER]['scope'],
|
||||
'twitterVerification' => $userData[IAccountManager::PROPERTY_TWITTER]['verified'],
|
||||
'groups' => $this->getGroups($user),
|
||||
] + $messageParameters + $languageParameters + $localeParameters;
|
||||
|
||||
|
@ -154,7 +145,7 @@ class PersonalInfo implements ISettings {
|
|||
* @return string the section ID, e.g. 'sharing'
|
||||
* @since 9.1
|
||||
*/
|
||||
public function getSection() {
|
||||
public function getSection(): string {
|
||||
return 'personal-info';
|
||||
}
|
||||
|
||||
|
@ -166,7 +157,7 @@ class PersonalInfo implements ISettings {
|
|||
* E.g.: 70
|
||||
* @since 9.1
|
||||
*/
|
||||
public function getPriority() {
|
||||
public function getPriority(): int {
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
@ -176,9 +167,9 @@ class PersonalInfo implements ISettings {
|
|||
* @param IUser $user
|
||||
* @return array
|
||||
*/
|
||||
private function getGroups(IUser $user) {
|
||||
private function getGroups(IUser $user): array {
|
||||
$groups = array_map(
|
||||
function (IGroup $group) {
|
||||
static function (IGroup $group) {
|
||||
return $group->getDisplayName();
|
||||
},
|
||||
$this->groupManager->getUserGroups($user)
|
||||
|
@ -195,7 +186,7 @@ class PersonalInfo implements ISettings {
|
|||
* @param IUser $user
|
||||
* @return array
|
||||
*/
|
||||
private function getLanguages(IUser $user) {
|
||||
private function getLanguages(IUser $user): array {
|
||||
$forceLanguage = $this->config->getSystemValue('force_language', false);
|
||||
if ($forceLanguage !== false) {
|
||||
return [];
|
||||
|
@ -228,7 +219,7 @@ class PersonalInfo implements ISettings {
|
|||
);
|
||||
}
|
||||
|
||||
private function getLocales(IUser $user) {
|
||||
private function getLocales(IUser $user): array {
|
||||
$forceLanguage = $this->config->getSystemValue('force_locale', false);
|
||||
if ($forceLanguage !== false) {
|
||||
return [];
|
||||
|
@ -273,8 +264,8 @@ class PersonalInfo implements ISettings {
|
|||
* @param array $userData
|
||||
* @return array
|
||||
*/
|
||||
private function getMessageParameters(array $userData) {
|
||||
$needVerifyMessage = [AccountManager::PROPERTY_EMAIL, AccountManager::PROPERTY_WEBSITE, AccountManager::PROPERTY_TWITTER];
|
||||
private function getMessageParameters(array $userData): array {
|
||||
$needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER];
|
||||
$messageParameters = [];
|
||||
foreach ($needVerifyMessage as $property) {
|
||||
switch ($userData[$property]['verified']) {
|
||||
|
|
|
@ -67,6 +67,7 @@ script('settings', [
|
|||
</div>
|
||||
</div>
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if ($_['lookupServerUploadEnabled']) { ?>
|
||||
<input type="hidden" id="avatarscope" value="<?php p($_['avatarScope']) ?>">
|
||||
<?php } ?>
|
||||
|
@ -161,7 +162,7 @@ script('settings', [
|
|||
} ?>
|
||||
placeholder="<?php p($l->t('Your email address')); ?>"
|
||||
autocomplete="on" autocapitalize="none" autocorrect="off" />
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if (!$_['displayNameChangeSupported']) { ?>
|
||||
<span><?php if (isset($_['email']) && !empty($_['email'])) {
|
||||
|
@ -196,6 +197,7 @@ script('settings', [
|
|||
placeholder="<?php p($l->t('Your phone number')); ?>"
|
||||
autocomplete="on" autocapitalize="none" autocorrect="off" />
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if ($_['lookupServerUploadEnabled']) { ?>
|
||||
<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>">
|
||||
<?php } ?>
|
||||
|
@ -220,6 +222,7 @@ script('settings', [
|
|||
value="<?php p($_['address']) ?>"
|
||||
autocomplete="on" autocapitalize="none" autocorrect="off" />
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if ($_['lookupServerUploadEnabled']) { ?>
|
||||
<input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>">
|
||||
<?php } ?>
|
||||
|
@ -275,6 +278,7 @@ script('settings', [
|
|||
} ?>
|
||||
/>
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if ($_['lookupServerUploadEnabled']) { ?>
|
||||
<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>">
|
||||
<?php } ?>
|
||||
|
@ -330,6 +334,7 @@ script('settings', [
|
|||
} ?>
|
||||
/>
|
||||
<span class="icon-checkmark hidden"></span>
|
||||
<span class="icon-error hidden" ></span>
|
||||
<?php if ($_['lookupServerUploadEnabled']) { ?>
|
||||
<input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>">
|
||||
<?php } ?>
|
||||
|
|
|
@ -605,6 +605,7 @@ class CheckSetupControllerTest extends TestCase {
|
|||
'OCA\Settings\SetupChecks\LegacySSEKeyFormat' => ['pass' => true, 'description' => 'The old server-side-encryption format is enabled. We recommend disabling this.', 'severity' => 'warning', 'linkToDocumentation' => ''],
|
||||
'OCA\Settings\SetupChecks\CheckUserCertificates' => ['pass' => false, 'description' => 'There are some user imported SSL certificates present, that are not used anymore with Nextcloud 21. They can be imported on the command line via "occ security:certificates:import" command. Their paths inside the data directory are shown below.', 'severity' => 'warning', 'elements' => ['a', 'b']],
|
||||
'imageMagickLacksSVGSupport' => false,
|
||||
'isDefaultPhoneRegionSet' => false,
|
||||
]
|
||||
);
|
||||
$this->assertEquals($expected, $this->checkSetupController->check());
|
||||
|
|
|
@ -31,6 +31,7 @@ use OC\Accounts\AccountManager;
|
|||
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
|
||||
use OC\Group\Manager;
|
||||
use OCA\Settings\Controller\UsersController;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
|
@ -196,41 +197,41 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
->method('getUser')
|
||||
->with($user)
|
||||
->willReturn([
|
||||
AccountManager::PROPERTY_DISPLAYNAME =>
|
||||
IAccountManager::PROPERTY_DISPLAYNAME =>
|
||||
[
|
||||
'value' => 'Display name',
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
'verified' => AccountManager::NOT_VERIFIED,
|
||||
],
|
||||
AccountManager::PROPERTY_ADDRESS =>
|
||||
IAccountManager::PROPERTY_ADDRESS =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
'verified' => AccountManager::NOT_VERIFIED,
|
||||
],
|
||||
AccountManager::PROPERTY_WEBSITE =>
|
||||
IAccountManager::PROPERTY_WEBSITE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
'verified' => AccountManager::NOT_VERIFIED,
|
||||
],
|
||||
AccountManager::PROPERTY_EMAIL =>
|
||||
IAccountManager::PROPERTY_EMAIL =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
'verified' => AccountManager::NOT_VERIFIED,
|
||||
],
|
||||
AccountManager::PROPERTY_AVATAR =>
|
||||
IAccountManager::PROPERTY_AVATAR =>
|
||||
[
|
||||
'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY
|
||||
],
|
||||
AccountManager::PROPERTY_PHONE =>
|
||||
IAccountManager::PROPERTY_PHONE =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
'verified' => AccountManager::NOT_VERIFIED,
|
||||
],
|
||||
AccountManager::PROPERTY_TWITTER =>
|
||||
IAccountManager::PROPERTY_TWITTER =>
|
||||
[
|
||||
'value' => '',
|
||||
'scope' => AccountManager::VISIBILITY_PRIVATE,
|
||||
|
@ -238,12 +239,14 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
],
|
||||
]);
|
||||
|
||||
$controller->expects($this->once())->method('saveUserSettings');
|
||||
$controller->expects($this->once())
|
||||
->method('saveUserSettings')
|
||||
->willReturnArgument(1);
|
||||
} else {
|
||||
$controller->expects($this->never())->method('saveUserSettings');
|
||||
}
|
||||
|
||||
$result = $controller->setUserSettings(
|
||||
$result = $controller->setUserSettings(//
|
||||
AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
'displayName',
|
||||
AccountManager::VISIBILITY_CONTACTS_ONLY,
|
||||
|
@ -289,21 +292,21 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$user->method('getEMailAddress')->willReturn($oldEmailAddress);
|
||||
$user->method('canChangeDisplayName')->willReturn(true);
|
||||
|
||||
if ($data[AccountManager::PROPERTY_EMAIL]['value'] === $oldEmailAddress ||
|
||||
($oldEmailAddress === null && $data[AccountManager::PROPERTY_EMAIL]['value'] === '')) {
|
||||
if ($data[IAccountManager::PROPERTY_EMAIL]['value'] === $oldEmailAddress ||
|
||||
($oldEmailAddress === null && $data[IAccountManager::PROPERTY_EMAIL]['value'] === '')) {
|
||||
$user->expects($this->never())->method('setEMailAddress');
|
||||
} else {
|
||||
$user->expects($this->once())->method('setEMailAddress')
|
||||
->with($data[AccountManager::PROPERTY_EMAIL]['value'])
|
||||
->with($data[IAccountManager::PROPERTY_EMAIL]['value'])
|
||||
->willReturn(true);
|
||||
}
|
||||
|
||||
if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === $oldDisplayName ||
|
||||
($oldDisplayName === null && $data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === '')) {
|
||||
if ($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'] === $oldDisplayName ||
|
||||
($oldDisplayName === null && $data[IAccountManager::PROPERTY_DISPLAYNAME]['value'] === '')) {
|
||||
$user->expects($this->never())->method('setDisplayName');
|
||||
} else {
|
||||
$user->expects($this->once())->method('setDisplayName')
|
||||
->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
->with($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
->willReturn(true);
|
||||
}
|
||||
|
||||
|
@ -317,48 +320,48 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
return [
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'john@example.com',
|
||||
'john doe'
|
||||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'johnNew@example.com',
|
||||
'john New doe'
|
||||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'johnNew@example.com',
|
||||
'john doe'
|
||||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'john@example.com',
|
||||
'john New doe'
|
||||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
null,
|
||||
'john New doe'
|
||||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'john@example.com',
|
||||
null
|
||||
|
@ -391,14 +394,14 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$user->method('getDisplayName')->willReturn($oldDisplayName);
|
||||
$user->method('getEMailAddress')->willReturn($oldEmailAddress);
|
||||
|
||||
if ($data[AccountManager::PROPERTY_EMAIL]['value'] !== $oldEmailAddress) {
|
||||
if ($data[IAccountManager::PROPERTY_EMAIL]['value'] !== $oldEmailAddress) {
|
||||
$user->method('canChangeDisplayName')
|
||||
->willReturn($canChangeEmail);
|
||||
}
|
||||
|
||||
if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] !== $oldDisplayName) {
|
||||
if ($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'] !== $oldDisplayName) {
|
||||
$user->method('setDisplayName')
|
||||
->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
->with($data[IAccountManager::PROPERTY_DISPLAYNAME]['value'])
|
||||
->willReturn($setDisplayNameResult);
|
||||
}
|
||||
|
||||
|
@ -410,8 +413,8 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
return [
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'johnNew@example.com',
|
||||
'john New doe',
|
||||
|
@ -420,8 +423,8 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'johnNew@example.com',
|
||||
'john New doe',
|
||||
|
@ -430,8 +433,8 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
],
|
||||
[
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
|
||||
],
|
||||
'johnNew@example.com',
|
||||
'john New doe',
|
||||
|
@ -455,7 +458,7 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$signature = 'theSignature';
|
||||
|
||||
$code = $message . ' ' . $signature;
|
||||
if ($type === AccountManager::PROPERTY_TWITTER) {
|
||||
if ($type === IAccountManager::PROPERTY_TWITTER) {
|
||||
$code = $message . ' ' . md5($signature);
|
||||
}
|
||||
|
||||
|
@ -470,7 +473,7 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$controller->expects($this->any())->method('getCurrentTime')->willReturn(1234567);
|
||||
|
||||
if ($onlyVerificationCode === false) {
|
||||
$this->accountManager->expects($this->once())->method('updateUser')->with($user, $expectedData);
|
||||
$this->accountManager->expects($this->once())->method('updateUser')->with($user, $expectedData)->willReturnArgument(1);
|
||||
$this->jobList->expects($this->once())->method('add')
|
||||
->with('OCA\Settings\BackgroundJobs\VerifyUserData',
|
||||
[
|
||||
|
@ -492,25 +495,25 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
|
||||
public function dataTestGetVerificationCode() {
|
||||
$accountDataBefore = [
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
|
||||
];
|
||||
|
||||
$accountDataAfterWebsite = [
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
|
||||
];
|
||||
|
||||
$accountDataAfterTwitter = [
|
||||
AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
|
||||
AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
|
||||
IAccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
|
||||
IAccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
|
||||
];
|
||||
|
||||
return [
|
||||
['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, false],
|
||||
['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, false],
|
||||
['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, true],
|
||||
['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, true],
|
||||
['verify-twitter', IAccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, false],
|
||||
['verify-website', IAccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, false],
|
||||
['verify-twitter', IAccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, true],
|
||||
['verify-website', IAccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, true],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -173,6 +173,37 @@ trait Provisioning {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^search users by phone for region "([^"]*)" with$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param \Behat\Gherkin\Node\TableNode|null $settings
|
||||
*/
|
||||
public function searchUserByPhone($region, \Behat\Gherkin\Node\TableNode $searchTable) {
|
||||
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/search/by-phone";
|
||||
$client = new Client();
|
||||
$options = [];
|
||||
$options['auth'] = $this->adminUser;
|
||||
$options['headers'] = [
|
||||
'OCS-APIREQUEST' => 'true',
|
||||
];
|
||||
|
||||
$search = [];
|
||||
foreach ($searchTable->getRows() as $row) {
|
||||
if (!isset($search[$row[0]])) {
|
||||
$search[$row[0]] = [];
|
||||
}
|
||||
$search[$row[0]][] = $row[1];
|
||||
}
|
||||
|
||||
$options['form_params'] = [
|
||||
'location' => $region,
|
||||
'search' => $search,
|
||||
];
|
||||
|
||||
$this->response = $client->post($fullUrl, $options);
|
||||
}
|
||||
|
||||
public function createUser($user) {
|
||||
$previous_user = $this->currentUser;
|
||||
$this->currentUser = "admin";
|
||||
|
@ -560,6 +591,19 @@ trait Provisioning {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^phone matches returned are$/
|
||||
* @param \Behat\Gherkin\Node\TableNode|null $usersList
|
||||
*/
|
||||
public function thePhoneUsersShouldBe($usersList) {
|
||||
if ($usersList instanceof \Behat\Gherkin\Node\TableNode) {
|
||||
$users = $usersList->getRowsHash();
|
||||
$listCheckedElements = simplexml_load_string($this->response->getBody())->data;
|
||||
$respondedArray = json_decode(json_encode($listCheckedElements), true);
|
||||
Assert::assertEquals($users, $respondedArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^detailed users returned are$/
|
||||
* @param \Behat\Gherkin\Node\TableNode|null $usersList
|
||||
|
|
|
@ -71,12 +71,12 @@ Feature: provisioning
|
|||
And the HTTP status code should be "200"
|
||||
And sending "PUT" to "/cloud/users/brand-new-user" with
|
||||
| key | email |
|
||||
| value | brand-new-user@gmail.com |
|
||||
| value | no-reply@nextcloud.com |
|
||||
And the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And sending "PUT" to "/cloud/users/brand-new-user" with
|
||||
| key | phone |
|
||||
| value | 0123 456 789 |
|
||||
| value | +49 711 / 25 24 28-90 |
|
||||
And the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And sending "PUT" to "/cloud/users/brand-new-user" with
|
||||
|
@ -97,12 +97,29 @@ Feature: provisioning
|
|||
Then user "brand-new-user" has
|
||||
| id | brand-new-user |
|
||||
| displayname | Brand New User |
|
||||
| email | brand-new-user@gmail.com |
|
||||
| phone | 0123 456 789 |
|
||||
| email | no-reply@nextcloud.com |
|
||||
| phone | +4971125242890 |
|
||||
| address | Foo Bar Town |
|
||||
| website | https://nextcloud.com |
|
||||
| twitter | Nextcloud |
|
||||
|
||||
Scenario: Search by phone number
|
||||
Given As an "admin"
|
||||
And user "phone-user" exists
|
||||
And sending "PUT" to "/cloud/users/phone-user" with
|
||||
| key | phone |
|
||||
| value | +49 711 / 25 24 28-90 |
|
||||
And the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
Then search users by phone for region "DE" with
|
||||
| random-string1 | 0711 / 123 456 78 |
|
||||
| random-string1 | 0711 / 252 428-90 |
|
||||
| random-string2 | 0711 / 90-824 252 |
|
||||
And the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
Then phone matches returned are
|
||||
| random-string1 | phone-user@localhost:8080 |
|
||||
|
||||
Scenario: Create a group
|
||||
Given As an "admin"
|
||||
And group "new-group" does not exist
|
||||
|
|
|
@ -194,6 +194,16 @@ $CONFIG = [
|
|||
*/
|
||||
'default_locale' => 'en_US',
|
||||
|
||||
/**
|
||||
* This sets the default region for phone numbers on your Nextcloud server,
|
||||
* using ISO 3166-1 country codes such as ``DE`` for Germany, ``FR`` for France, …
|
||||
* It is required to allow inserting phone numbers in the user profiles starting
|
||||
* without the country code (e.g. +49 for Germany).
|
||||
*
|
||||
* No default value!
|
||||
*/
|
||||
'default_phone_region' => 'EN',
|
||||
|
||||
/**
|
||||
* With this setting a locale can be forced for all users. If a locale is
|
||||
* forced, the users are also unable to change their locale in the personal
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Core\Migrations;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
class Version21000Date20201202095923 extends SimpleMigrationStep {
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if (!$schema->hasTable('accounts_data')) {
|
||||
$table = $schema->createTable('accounts_data');
|
||||
$table->addColumn('id', Types::BIGINT, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
'length' => 20,
|
||||
]);
|
||||
$table->addColumn('uid', Types::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('name', Types::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('value', Types::STRING, [
|
||||
'notnull' => false,
|
||||
'length' => 255,
|
||||
'default' => '',
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
$table->addIndex(['uid'], 'accounts_data_uid');
|
||||
$table->addIndex(['name'], 'accounts_data_name');
|
||||
$table->addIndex(['value'], 'accounts_data_value');
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -216,6 +216,12 @@
|
|||
type: OC.SetupChecks.MESSAGE_TYPE_WARNING
|
||||
});
|
||||
}
|
||||
if (!data.isDefaultPhoneRegionSet) {
|
||||
messages.push({
|
||||
msg: t('core', 'Your installation has no default phone region set. This is required to be able to validate phone numbers in the profile settings without a country code. To allow numbers without a country code, please add "default_phone_region" with the respective ISO 3166-1 code of the wished region.'),
|
||||
type: OC.SetupChecks.MESSAGE_TYPE_INFO
|
||||
});
|
||||
}
|
||||
if (data.cronErrors.length > 0) {
|
||||
var listOfCronErrors = "";
|
||||
data.cronErrors.forEach(function(element){
|
||||
|
|
|
@ -251,6 +251,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -306,6 +307,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -362,6 +364,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -416,6 +419,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -468,6 +472,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -522,6 +527,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -574,6 +580,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -626,6 +633,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -678,6 +686,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -751,6 +760,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -804,6 +814,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -857,6 +868,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -910,6 +922,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -962,6 +975,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: true,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -1014,6 +1028,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
|
||||
reverseProxyGeneratedURL: 'http://server',
|
||||
|
@ -1067,6 +1082,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: true,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: false,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
|
@ -1080,6 +1096,59 @@ describe('OC.SetupChecks tests', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an info if there is no default phone region', function(done) {
|
||||
var async = OC.SetupChecks.checkSetup();
|
||||
|
||||
suite.server.requests[0].respond(
|
||||
200,
|
||||
{
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
JSON.stringify({
|
||||
hasFileinfoInstalled: true,
|
||||
isGetenvServerWorking: true,
|
||||
isReadOnlyConfig: false,
|
||||
hasWorkingFileLocking: true,
|
||||
hasValidTransactionIsolationLevel: true,
|
||||
suggestedOverwriteCliURL: '',
|
||||
isRandomnessSecure: true,
|
||||
securityDocs: 'https://docs.owncloud.org/myDocs.html',
|
||||
serverHasInternetConnectionProblems: false,
|
||||
isMemcacheConfigured: true,
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
isOpcacheProperlySetup: true,
|
||||
hasOpcacheLoaded: true,
|
||||
isSettimelimitAvailable: true,
|
||||
hasFreeTypeSupport: true,
|
||||
missingIndexes: [],
|
||||
missingPrimaryKeys: [],
|
||||
missingColumns: [],
|
||||
cronErrors: [],
|
||||
cronInfo: {
|
||||
diffInSeconds: 0
|
||||
},
|
||||
isMemoryLimitSufficient: true,
|
||||
appDirsWithDifferentOwner: [],
|
||||
recommendedPHPModules: [],
|
||||
pendingBigIntConversionColumns: [],
|
||||
isMysqlUsedWithoutUTF8MB4: false,
|
||||
isDefaultPhoneRegionSet: false,
|
||||
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
|
||||
reverseProxyGeneratedURL: 'https://server',
|
||||
})
|
||||
);
|
||||
|
||||
async.done(function( data, s, x ){
|
||||
expect(data).toEqual([{
|
||||
msg: 'Your installation has no default phone region set. This is required to be able to validate phone numbers in the profile settings without a country code. To allow numbers without a country code, please add "default_phone_region" with the respective ISO 3166-1 code of the wished region.',
|
||||
type: OC.SetupChecks.MESSAGE_TYPE_INFO
|
||||
}]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkGeneric', function() {
|
||||
|
|
|
@ -930,6 +930,7 @@ return array(
|
|||
'OC\\Core\\Migrations\\Version20000Date20201109081918' => $baseDir . '/core/Migrations/Version20000Date20201109081918.php',
|
||||
'OC\\Core\\Migrations\\Version20000Date20201109081919' => $baseDir . '/core/Migrations/Version20000Date20201109081919.php',
|
||||
'OC\\Core\\Migrations\\Version20000Date20201111081915' => $baseDir . '/core/Migrations/Version20000Date20201111081915.php',
|
||||
'OC\\Core\\Migrations\\Version21000Date20201202095923' => $baseDir . '/core/Migrations/Version21000Date20201202095923.php',
|
||||
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
|
||||
'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php',
|
||||
'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php',
|
||||
|
@ -1266,6 +1267,7 @@ return array(
|
|||
'OC\\Repair\\NC20\\EncryptionMigration' => $baseDir . '/lib/private/Repair/NC20/EncryptionMigration.php',
|
||||
'OC\\Repair\\NC20\\ShippedDashboardEnable' => $baseDir . '/lib/private/Repair/NC20/ShippedDashboardEnable.php',
|
||||
'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => $baseDir . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php',
|
||||
'OC\\Repair\\NC21\\ValidatePhoneNumber' => $baseDir . '/lib/private/Repair/NC21/ValidatePhoneNumber.php',
|
||||
'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php',
|
||||
'OC\\Repair\\Owncloud\\DropAccountTermsTable' => $baseDir . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php',
|
||||
'OC\\Repair\\Owncloud\\SaveAccountsTableData' => $baseDir . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php',
|
||||
|
|
|
@ -959,6 +959,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Core\\Migrations\\Version20000Date20201109081918' => __DIR__ . '/../../..' . '/core/Migrations/Version20000Date20201109081918.php',
|
||||
'OC\\Core\\Migrations\\Version20000Date20201109081919' => __DIR__ . '/../../..' . '/core/Migrations/Version20000Date20201109081919.php',
|
||||
'OC\\Core\\Migrations\\Version20000Date20201111081915' => __DIR__ . '/../../..' . '/core/Migrations/Version20000Date20201111081915.php',
|
||||
'OC\\Core\\Migrations\\Version21000Date20201202095923' => __DIR__ . '/../../..' . '/core/Migrations/Version21000Date20201202095923.php',
|
||||
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
|
||||
'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php',
|
||||
'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php',
|
||||
|
@ -1295,6 +1296,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Repair\\NC20\\EncryptionMigration' => __DIR__ . '/../../..' . '/lib/private/Repair/NC20/EncryptionMigration.php',
|
||||
'OC\\Repair\\NC20\\ShippedDashboardEnable' => __DIR__ . '/../../..' . '/lib/private/Repair/NC20/ShippedDashboardEnable.php',
|
||||
'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php',
|
||||
'OC\\Repair\\NC21\\ValidatePhoneNumber' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/ValidatePhoneNumber.php',
|
||||
'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php',
|
||||
'OC\\Repair\\Owncloud\\DropAccountTermsTable' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php',
|
||||
'OC\\Repair\\Owncloud\\SaveAccountsTableData' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php',
|
||||
|
|
|
@ -30,10 +30,16 @@
|
|||
|
||||
namespace OC\Accounts;
|
||||
|
||||
use libphonenumber\NumberParseException;
|
||||
use libphonenumber\PhoneNumber;
|
||||
use libphonenumber\PhoneNumberFormat;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use OCA\Settings\BackgroundJobs\VerifyUserData;
|
||||
use OCP\Accounts\IAccount;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -55,9 +61,15 @@ class AccountManager implements IAccountManager {
|
|||
/** @var IDBConnection database connection */
|
||||
private $connection;
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var string table name */
|
||||
private $table = 'accounts';
|
||||
|
||||
/** @var string table name */
|
||||
private $dataTable = 'accounts_data';
|
||||
|
||||
/** @var EventDispatcherInterface */
|
||||
private $eventDispatcher;
|
||||
|
||||
|
@ -68,24 +80,70 @@ class AccountManager implements IAccountManager {
|
|||
private $logger;
|
||||
|
||||
public function __construct(IDBConnection $connection,
|
||||
IConfig $config,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
IJobList $jobList,
|
||||
LoggerInterface $logger) {
|
||||
$this->connection = $connection;
|
||||
$this->config = $config;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->jobList = $jobList;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $input
|
||||
* @return string Provided phone number in E.164 format when it was a valid number
|
||||
* @throws \InvalidArgumentException When the phone number was invalid or no default region is set and the number doesn't start with a country code
|
||||
*/
|
||||
protected function parsePhoneNumber(string $input): string {
|
||||
$defaultRegion = $this->config->getSystemValueString('default_phone_region', '');
|
||||
|
||||
if ($defaultRegion === '') {
|
||||
// When no default region is set, only +49… numbers are valid
|
||||
if (strpos($input, '+') !== 0) {
|
||||
throw new \InvalidArgumentException(self::PROPERTY_PHONE);
|
||||
}
|
||||
|
||||
$defaultRegion = 'EN';
|
||||
}
|
||||
|
||||
$phoneUtil = PhoneNumberUtil::getInstance();
|
||||
try {
|
||||
$phoneNumber = $phoneUtil->parse($input, $defaultRegion);
|
||||
if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
|
||||
return $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
|
||||
}
|
||||
} catch (NumberParseException $e) {
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(self::PROPERTY_PHONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* update user record
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param $data
|
||||
* @param array $data
|
||||
* @param bool $throwOnData Set to true if you can inform the user about invalid data
|
||||
* @return array The potentially modified data (e.g. phone numbers are converted to E.164 format)
|
||||
* @throws \InvalidArgumentException Message is the property that was invalid
|
||||
*/
|
||||
public function updateUser(IUser $user, $data) {
|
||||
public function updateUser(IUser $user, array $data, bool $throwOnData = false): array {
|
||||
$userData = $this->getUser($user);
|
||||
$updated = true;
|
||||
|
||||
if (isset($data[self::PROPERTY_PHONE]) && $data[self::PROPERTY_PHONE]['value'] !== '') {
|
||||
try {
|
||||
$data[self::PROPERTY_PHONE]['value'] = $this->parsePhoneNumber($data[self::PROPERTY_PHONE]['value']);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
if ($throwOnData) {
|
||||
throw $e;
|
||||
}
|
||||
$data[self::PROPERTY_PHONE]['value'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($userData)) {
|
||||
$this->insertNewUser($user, $data);
|
||||
} elseif ($userData !== $data) {
|
||||
|
@ -103,6 +161,8 @@ class AccountManager implements IAccountManager {
|
|||
new GenericEvent($user, $data)
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,6 +176,21 @@ class AccountManager implements IAccountManager {
|
|||
$query->delete($this->table)
|
||||
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
|
||||
->execute();
|
||||
|
||||
$this->deleteUserData($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete user from accounts table
|
||||
*
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function deleteUserData(IUser $user): void {
|
||||
$uid = $user->getUID();
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->delete($this->dataTable)
|
||||
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,6 +228,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
|
||||
*
|
||||
|
@ -173,7 +266,7 @@ class AccountManager implements IAccountManager {
|
|||
'lastRun' => time()
|
||||
]
|
||||
);
|
||||
$newData[AccountManager::PROPERTY_EMAIL]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
||||
$newData[self::PROPERTY_EMAIL]['verified'] = self::VERIFICATION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return $newData;
|
||||
|
@ -256,7 +349,7 @@ class AccountManager implements IAccountManager {
|
|||
* @param IUser $user
|
||||
* @param array $data
|
||||
*/
|
||||
protected function insertNewUser(IUser $user, $data) {
|
||||
protected function insertNewUser(IUser $user, array $data): void {
|
||||
$uid = $user->getUID();
|
||||
$jsonEncodedData = json_encode($data);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
|
@ -268,6 +361,9 @@ class AccountManager implements IAccountManager {
|
|||
]
|
||||
)
|
||||
->execute();
|
||||
|
||||
$this->deleteUserData($user);
|
||||
$this->writeUserData($user, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,7 +372,7 @@ class AccountManager implements IAccountManager {
|
|||
* @param IUser $user
|
||||
* @param array $data
|
||||
*/
|
||||
protected function updateExistingUser(IUser $user, $data) {
|
||||
protected function updateExistingUser(IUser $user, array $data): void {
|
||||
$uid = $user->getUID();
|
||||
$jsonEncodedData = json_encode($data);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
|
@ -284,6 +380,30 @@ class AccountManager implements IAccountManager {
|
|||
->set('data', $query->createNamedParameter($jsonEncodedData))
|
||||
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
|
||||
->execute();
|
||||
|
||||
$this->deleteUserData($user);
|
||||
$this->writeUserData($user, $data);
|
||||
}
|
||||
|
||||
protected function writeUserData(IUser $user, array $data): void {
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->insert($this->dataTable)
|
||||
->values(
|
||||
[
|
||||
'uid' => $query->createNamedParameter($user->getUID()),
|
||||
'name' => $query->createParameter('name'),
|
||||
'value' => $query->createParameter('value'),
|
||||
]
|
||||
);
|
||||
foreach ($data as $propertyName => $property) {
|
||||
if ($propertyName === self::PROPERTY_AVATAR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$query->setParameter('name', $propertyName)
|
||||
->setParameter('value', $property['value']);
|
||||
$query->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
namespace OC\Accounts;
|
||||
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IUser;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
@ -61,14 +62,14 @@ class Hooks {
|
|||
|
||||
switch ($feature) {
|
||||
case 'eMailAddress':
|
||||
if ($accountData[AccountManager::PROPERTY_EMAIL]['value'] !== $newValue) {
|
||||
$accountData[AccountManager::PROPERTY_EMAIL]['value'] = $newValue;
|
||||
if ($accountData[IAccountManager::PROPERTY_EMAIL]['value'] !== $newValue) {
|
||||
$accountData[IAccountManager::PROPERTY_EMAIL]['value'] = $newValue;
|
||||
$accountManager->updateUser($user, $accountData);
|
||||
}
|
||||
break;
|
||||
case 'displayName':
|
||||
if ($accountData[AccountManager::PROPERTY_DISPLAYNAME]['value'] !== $newValue) {
|
||||
$accountData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $newValue;
|
||||
if ($accountData[IAccountManager::PROPERTY_DISPLAYNAME]['value'] !== $newValue) {
|
||||
$accountData[IAccountManager::PROPERTY_DISPLAYNAME]['value'] = $newValue;
|
||||
$accountManager->updateUser($user, $accountData);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -53,6 +53,7 @@ use OC\Repair\NC20\EncryptionLegacyCipher;
|
|||
use OC\Repair\NC20\EncryptionMigration;
|
||||
use OC\Repair\NC20\ShippedDashboardEnable;
|
||||
use OC\Repair\NC21\AddCheckForUserCertificatesJob;
|
||||
use OC\Repair\NC21\ValidatePhoneNumber;
|
||||
use OC\Repair\OldGroupMembershipShares;
|
||||
use OC\Repair\Owncloud\DropAccountTermsTable;
|
||||
use OC\Repair\Owncloud\SaveAccountsTableData;
|
||||
|
@ -177,7 +178,8 @@ class Repair implements IOutput {
|
|||
*/
|
||||
public static function getExpensiveRepairSteps() {
|
||||
return [
|
||||
new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager())
|
||||
new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
|
||||
\OC::$server->get(ValidatePhoneNumber::class),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Repair\NC21;
|
||||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\IRepairStep;
|
||||
|
||||
class ValidatePhoneNumber implements IRepairStep {
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
/** @var IUserManager */
|
||||
protected $userManager;
|
||||
/** @var AccountManager */
|
||||
private $accountManager;
|
||||
|
||||
public function __construct(IUserManager $userManager,
|
||||
AccountManager $accountManager,
|
||||
IConfig $config) {
|
||||
$this->config = $config;
|
||||
$this->userManager = $userManager;
|
||||
$this->accountManager = $accountManager;
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return 'Validate the phone number and store it in a known format for search';
|
||||
}
|
||||
|
||||
private function shouldRun(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function run(IOutput $output): void {
|
||||
if ($this->config->getSystemValueString('default_phone_region', '') === '') {
|
||||
throw new \Exception('Can not validate phone numbers without `default_phone_region` being set in the config file');
|
||||
}
|
||||
|
||||
$numUpdated = 0;
|
||||
$numRemoved = 0;
|
||||
|
||||
$this->userManager->callForSeenUsers(function (IUser $user) use (&$numUpdated, &$numRemoved) {
|
||||
$account = $this->accountManager->getUser($user);
|
||||
|
||||
if ($account[IAccountManager::PROPERTY_PHONE]['value'] !== '') {
|
||||
$updated = $this->accountManager->updateUser($user, $account);
|
||||
|
||||
if ($account[IAccountManager::PROPERTY_PHONE]['value'] !== $updated[IAccountManager::PROPERTY_PHONE]['value']) {
|
||||
if ($updated[IAccountManager::PROPERTY_PHONE]['value'] === '') {
|
||||
$numRemoved++;
|
||||
} else {
|
||||
$numUpdated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ($numRemoved > 0 || $numUpdated > 0) {
|
||||
$output->info('Updated ' . $numUpdated . ' entries and cleaned ' . $numRemoved . ' invalid phone numbers');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ use OC\Accounts\Account;
|
|||
use OC\Accounts\AccountManager;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -43,6 +44,9 @@ class AccountsManagerTest extends TestCase {
|
|||
/** @var \OCP\IDBConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var IConfig|MockObject */
|
||||
private $config;
|
||||
|
||||
/** @var EventDispatcherInterface|MockObject */
|
||||
private $eventDispatcher;
|
||||
|
||||
|
@ -59,6 +63,7 @@ class AccountsManagerTest extends TestCase {
|
|||
parent::setUp();
|
||||
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->connection = \OC::$server->getDatabaseConnection();
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->jobList = $this->createMock(IJobList::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
}
|
||||
|
@ -77,7 +82,13 @@ class AccountsManagerTest extends TestCase {
|
|||
*/
|
||||
public function getInstance($mockedMethods = null) {
|
||||
return $this->getMockBuilder(AccountManager::class)
|
||||
->setConstructorArgs([$this->connection, $this->eventDispatcher, $this->jobList, $this->logger])
|
||||
->setConstructorArgs([
|
||||
$this->connection,
|
||||
$this->config,
|
||||
$this->eventDispatcher,
|
||||
$this->jobList,
|
||||
$this->logger,
|
||||
])
|
||||
->setMethods($mockedMethods)
|
||||
->getMock();
|
||||
}
|
||||
|
@ -187,9 +198,9 @@ class AccountsManagerTest extends TestCase {
|
|||
|
||||
public function testUpdateExistingUser() {
|
||||
$user = $this->getMockBuilder(IUser::class)->getMock();
|
||||
$user->expects($this->once())->method('getUID')->willReturn('uid');
|
||||
$oldData = ['key' => 'value'];
|
||||
$newData = ['newKey' => 'newValue'];
|
||||
$user->expects($this->atLeastOnce())->method('getUID')->willReturn('uid');
|
||||
$oldData = ['key' => ['value' => 'value']];
|
||||
$newData = ['newKey' => ['value' => 'newValue']];
|
||||
|
||||
$accountManager = $this->getInstance();
|
||||
$this->addDummyValuesToTable('uid', $oldData);
|
||||
|
@ -201,10 +212,10 @@ class AccountsManagerTest extends TestCase {
|
|||
public function testInsertNewUser() {
|
||||
$user = $this->getMockBuilder(IUser::class)->getMock();
|
||||
$uid = 'uid';
|
||||
$data = ['key' => 'value'];
|
||||
$data = ['key' => ['value' => 'value']];
|
||||
|
||||
$accountManager = $this->getInstance();
|
||||
$user->expects($this->once())->method('getUID')->willReturn($uid);
|
||||
$user->expects($this->atLeastOnce())->method('getUID')->willReturn($uid);
|
||||
$this->assertNull($this->getDataFromTable($uid));
|
||||
$this->invokePrivate($accountManager, 'insertNewUser', [$user, $data]);
|
||||
|
||||
|
@ -293,4 +304,32 @@ class AccountsManagerTest extends TestCase {
|
|||
->willReturn($data);
|
||||
$this->assertEquals($expected, $accountManager->getAccount($user));
|
||||
}
|
||||
|
||||
public function dataParsePhoneNumber(): array {
|
||||
return [
|
||||
['0711 / 25 24 28-90', 'DE', '+4971125242890'],
|
||||
['0711 / 25 24 28-90', '', null],
|
||||
['+49 711 / 25 24 28-90', '', '+4971125242890'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataParsePhoneNumber
|
||||
* @param string $phoneInput
|
||||
* @param string $defaultRegion
|
||||
* @param string|null $phoneNumber
|
||||
*/
|
||||
public function testParsePhoneNumber(string $phoneInput, string $defaultRegion, ?string $phoneNumber): void {
|
||||
$this->config->method('getSystemValueString')
|
||||
->willReturn($defaultRegion);
|
||||
|
||||
$instance = $this->getInstance();
|
||||
|
||||
if ($phoneNumber === null) {
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
self::invokePrivate($instance, 'parsePhoneNumber', [$phoneInput]);
|
||||
} else {
|
||||
self::assertEquals($phoneNumber, self::invokePrivate($instance, 'parsePhoneNumber', [$phoneInput]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Test\Accounts;
|
|||
|
||||
use OC\Accounts\AccountManager;
|
||||
use OC\Accounts\Hooks;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IUser;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -77,11 +78,11 @@ class HooksTest extends TestCase {
|
|||
$this->accountManager->expects($this->once())->method('getUser')->willReturn($data);
|
||||
$newData = $data;
|
||||
if ($setEmail) {
|
||||
$newData[AccountManager::PROPERTY_EMAIL]['value'] = $params['value'];
|
||||
$newData[IAccountManager::PROPERTY_EMAIL]['value'] = $params['value'];
|
||||
$this->accountManager->expects($this->once())->method('updateUser')
|
||||
->with($params['user'], $newData);
|
||||
} elseif ($setDisplayName) {
|
||||
$newData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $params['value'];
|
||||
$newData[IAccountManager::PROPERTY_DISPLAYNAME]['value'] = $params['value'];
|
||||
$this->accountManager->expects($this->once())->method('updateUser')
|
||||
->with($params['user'], $newData);
|
||||
} else {
|
||||
|
@ -98,48 +99,48 @@ class HooksTest extends TestCase {
|
|||
[
|
||||
['feature' => '', 'value' => ''],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
],
|
||||
false, false, true
|
||||
],
|
||||
[
|
||||
['user' => $user, 'value' => ''],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
],
|
||||
false, false, true
|
||||
],
|
||||
[
|
||||
['user' => $user, 'feature' => ''],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => ''],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => '']
|
||||
],
|
||||
false, false, true
|
||||
],
|
||||
[
|
||||
['user' => $user, 'feature' => 'foo', 'value' => 'bar'],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
],
|
||||
false, false, false
|
||||
],
|
||||
[
|
||||
['user' => $user, 'feature' => 'eMailAddress', 'value' => 'newMail@example.com'],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
],
|
||||
true, false, false
|
||||
],
|
||||
[
|
||||
['user' => $user, 'feature' => 'displayName', 'value' => 'newDisplayName'],
|
||||
[
|
||||
AccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
IAccountManager::PROPERTY_EMAIL => ['value' => 'oldMail@example.com'],
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => ['value' => 'oldDisplayName']
|
||||
],
|
||||
false, true, false
|
||||
],
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
||||
// when updating major/minor version number.
|
||||
|
||||
$OC_Version = [21, 0, 0, 7];
|
||||
$OC_Version = [21, 0, 0, 8];
|
||||
|
||||
// The human readable string
|
||||
$OC_VersionString = '21.0.0 alpha';
|
||||
|
|
Loading…
Reference in New Issue