Add a config for default region of phone numbers

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2020-12-03 11:12:41 +01:00
parent 689e3a502d
commit 46b073d7ce
No known key found for this signature in database
GPG Key ID: 7076EA9751AACDDA
7 changed files with 125 additions and 14 deletions

View File

@ -752,6 +752,7 @@ Raw output
PhpOutputBuffering::class => ['pass' => $phpOutputBuffering->run(), 'description' => $phpOutputBuffering->description(), 'severity' => $phpOutputBuffering->severity()], 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()], 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()], CheckUserCertificates::class => ['pass' => $checkUserCertificates->run(), 'description' => $checkUserCertificates->description(), 'severity' => $checkUserCertificates->severity(), 'elements' => $checkUserCertificates->elements()],
'isDefaultPhoneRegionSet' => $this->config->getSystemValueString('default_phone_region', '') !== '',
] ]
); );
} }

View File

@ -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\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']], '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, 'imageMagickLacksSVGSupport' => false,
'isDefaultPhoneRegionSet' => false,
] ]
); );
$this->assertEquals($expected, $this->checkSetupController->check()); $this->assertEquals($expected, $this->checkSetupController->check());

View File

@ -76,7 +76,7 @@ Feature: provisioning
And the HTTP status code should be "200" And the HTTP status code should be "200"
And sending "PUT" to "/cloud/users/brand-new-user" with And sending "PUT" to "/cloud/users/brand-new-user" with
| key | phone | | key | phone |
| value | 0711 / 25 24 28-90 | | value | +49 711 / 25 24 28-90 |
And the OCS status code should be "100" And the OCS status code should be "100"
And the HTTP status code should be "200" And the HTTP status code should be "200"
And sending "PUT" to "/cloud/users/brand-new-user" with And sending "PUT" to "/cloud/users/brand-new-user" with
@ -108,7 +108,7 @@ Feature: provisioning
And user "phone-user" exists And user "phone-user" exists
And sending "PUT" to "/cloud/users/phone-user" with And sending "PUT" to "/cloud/users/phone-user" with
| key | phone | | key | phone |
| value | 0711 / 25 24 28-90 | | value | +49 711 / 25 24 28-90 |
And the OCS status code should be "100" And the OCS status code should be "100"
And the HTTP status code should be "200" And the HTTP status code should be "200"
Then search users by phone for region "DE" with Then search users by phone for region "DE" with

View File

@ -194,6 +194,16 @@ $CONFIG = [
*/ */
'default_locale' => 'en_US', '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 * 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 * forced, the users are also unable to change their locale in the personal

View File

@ -216,6 +216,12 @@
type: OC.SetupChecks.MESSAGE_TYPE_WARNING 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) { if (data.cronErrors.length > 0) {
var listOfCronErrors = ""; var listOfCronErrors = "";
data.cronErrors.forEach(function(element){ data.cronErrors.forEach(function(element){

View File

@ -251,6 +251,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -306,6 +307,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -362,6 +364,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -416,6 +419,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -468,6 +472,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -522,6 +527,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -574,6 +580,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -626,6 +633,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -678,6 +686,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -751,6 +760,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -804,6 +814,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -857,6 +868,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -910,6 +922,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -962,6 +975,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: true, isMysqlUsedWithoutUTF8MB4: true,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -1014,6 +1028,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
reverseProxyGeneratedURL: 'http://server', reverseProxyGeneratedURL: 'http://server',
@ -1067,6 +1082,7 @@ describe('OC.SetupChecks tests', function() {
recommendedPHPModules: [], recommendedPHPModules: [],
pendingBigIntConversionColumns: [], pendingBigIntConversionColumns: [],
isMysqlUsedWithoutUTF8MB4: false, isMysqlUsedWithoutUTF8MB4: false,
isDefaultPhoneRegionSet: true,
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: false, isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: false,
reverseProxyGeneratedURL: 'https://server', reverseProxyGeneratedURL: 'https://server',
}) })
@ -1080,6 +1096,59 @@ describe('OC.SetupChecks tests', function() {
done(); 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() { describe('checkGeneric', function() {

View File

@ -39,6 +39,7 @@ use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountManager;
use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\IJobList;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\IUser; use OCP\IUser;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -60,6 +61,9 @@ class AccountManager implements IAccountManager {
/** @var IDBConnection database connection */ /** @var IDBConnection database connection */
private $connection; private $connection;
/** @var IConfig */
private $config;
/** @var string table name */ /** @var string table name */
private $table = 'accounts'; private $table = 'accounts';
@ -76,15 +80,46 @@ class AccountManager implements IAccountManager {
private $logger; private $logger;
public function __construct(IDBConnection $connection, public function __construct(IDBConnection $connection,
IConfig $config,
EventDispatcherInterface $eventDispatcher, EventDispatcherInterface $eventDispatcher,
IJobList $jobList, IJobList $jobList,
LoggerInterface $logger) { LoggerInterface $logger) {
$this->connection = $connection; $this->connection = $connection;
$this->config = $config;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->jobList = $jobList; $this->jobList = $jobList;
$this->logger = $logger; $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 * update user record
* *
@ -98,18 +133,7 @@ class AccountManager implements IAccountManager {
$updated = true; $updated = true;
if (isset($data[self::PROPERTY_PHONE])) { if (isset($data[self::PROPERTY_PHONE])) {
$phoneUtil = PhoneNumberUtil::getInstance(); $data[self::PROPERTY_PHONE]['value'] = $this->parsePhoneNumber($data[self::PROPERTY_PHONE]['value']);
try {
$phoneValue = $data[self::PROPERTY_PHONE]['value'];
$phoneNumber = $phoneUtil->parse($phoneValue, 'DE'); // FIXME need a reasonable default
if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
$data[self::PROPERTY_PHONE]['value'] = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
} else {
throw new \InvalidArgumentException(self::PROPERTY_PHONE);
}
} catch (NumberParseException $e) {
throw new \InvalidArgumentException(self::PROPERTY_PHONE);
}
} }
if (empty($userData)) { if (empty($userData)) {