From 6c7ccbecbf6af5037a6c7bf2046bbf4d3bf91e2f Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 27 Feb 2019 10:47:57 +0100 Subject: [PATCH] Add setup check for missing UTF8MB4 on mysql Signed-off-by: Morris Jobke --- core/js/setupchecks.js | 12 +++ core/js/tests/specs/setupchecksSpec.js | 87 ++++++++++++++++--- settings/Controller/CheckSetupController.php | 5 ++ .../Controller/CheckSetupControllerTest.php | 56 ++++++++++++ 4 files changed, 147 insertions(+), 13 deletions(-) diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index 7582b062d5..3e82e07799 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -438,6 +438,18 @@ type: OC.SetupChecks.MESSAGE_TYPE_WARNING }); } + if (data.isMysqlUsedWithoutUTF8MB4) { + messages.push({ + msg: t( + 'core', + 'MySQL is used as database but does not support 4-byte characters. To be able to handle 4-byte characters (like emojis) without issues in filenames or comments for example it is recommended to enable the 4-byte support in MySQL. For further details read the documentation page about this.', + { + docLink: oc_defaults.docPlaceholderUrl.replace('PLACEHOLDER', 'admin-mysql-utf8mb4'), + } + ), + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + }) + } } else { messages.push({ diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js index e2c0053aa7..aa9006d0ab 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -247,7 +247,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -297,7 +298,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -348,7 +350,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -397,7 +400,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -444,7 +448,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -493,7 +498,8 @@ describe('OC.SetupChecks tests', function() { '/some/path' ], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -540,7 +546,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -587,7 +594,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -634,7 +642,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: false, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -702,7 +711,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -750,7 +760,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -798,7 +809,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -846,7 +858,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -858,6 +871,54 @@ describe('OC.SetupChecks tests', function() { done(); }); }); + + it('should return an error if the php version is no longer supported', 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', + serverHasInternetConnection: true, + isMemcacheConfigured: true, + forwardedForHeadersWorking: true, + isCorrectMemcachedPHPModuleInstalled: true, + hasPassedCodeIntegrityCheck: true, + isOpcacheProperlySetup: true, + hasOpcacheLoaded: true, + isSettimelimitAvailable: true, + hasFreeTypeSupport: true, + missingIndexes: [], + cronErrors: [], + cronInfo: { + diffInSeconds: 0 + }, + isMemoryLimitSufficient: true, + appDirsWithDifferentOwner: [], + recommendedPHPModules: [], + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: true + }) + ); + + async.done(function( data, s, x ){ + expect(data).toEqual([{ + msg: 'MySQL is used as database but does not support 4-byte characters. To be able to handle 4-byte characters (like emojis) without issues in filenames or comments for example it is recommended to enable the 4-byte support in MySQL. For further details read the documentation page about this.', + type: OC.SetupChecks.MESSAGE_TYPE_WARNING + }]); + done(); + }); + }); }); describe('checkGeneric', function() { diff --git a/settings/Controller/CheckSetupController.php b/settings/Controller/CheckSetupController.php index 920bf59ea5..ba84762196 100644 --- a/settings/Controller/CheckSetupController.php +++ b/settings/Controller/CheckSetupController.php @@ -591,6 +591,10 @@ Raw output return $recommendedPHPModules; } + protected function isMysqlUsedWithoutUTF8MB4(): bool { + return ($this->config->getSystemValue('dbtype', 'sqlite') === 'mysql') && ($this->config->getSystemValue('mysql.utf8mb4', false) === false); + } + protected function hasBigIntConversionPendingColumns(): array { // copy of ConvertFilecacheBigInt::getColumnsByTable() $tables = [ @@ -664,6 +668,7 @@ Raw output 'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(), 'recommendedPHPModules' => $this->hasRecommendedPHPModules(), 'pendingBigIntConversionColumns' => $this->hasBigIntConversionPendingColumns(), + 'isMysqlUsedWithoutUTF8MB4' => $this->isMysqlUsedWithoutUTF8MB4(), ] ); } diff --git a/tests/Settings/Controller/CheckSetupControllerTest.php b/tests/Settings/Controller/CheckSetupControllerTest.php index b1b451aa9e..dd13b29697 100644 --- a/tests/Settings/Controller/CheckSetupControllerTest.php +++ b/tests/Settings/Controller/CheckSetupControllerTest.php @@ -159,6 +159,7 @@ class CheckSetupControllerTest extends TestCase { 'getAppDirsWithDifferentOwner', 'hasRecommendedPHPModules', 'hasBigIntConversionPendingColumns', + 'isMysqlUsedWithoutUTF8MB4', ])->getMock(); } @@ -520,6 +521,11 @@ class CheckSetupControllerTest extends TestCase { ->method('hasBigIntConversionPendingColumns') ->willReturn([]); + $this->checkSetupController + ->expects($this->once()) + ->method('isMysqlUsedWithoutUTF8MB4') + ->willReturn(false); + $expected = new DataResponse( [ 'isGetenvServerWorking' => true, @@ -563,6 +569,7 @@ class CheckSetupControllerTest extends TestCase { 'appDirsWithDifferentOwner' => [], 'recommendedPHPModules' => [], 'pendingBigIntConversionColumns' => [], + 'isMysqlUsedWithoutUTF8MB4' => false, ] ); $this->assertEquals($expected, $this->checkSetupController->check()); @@ -1344,4 +1351,53 @@ Array ); $this->assertEquals($expected, $this->checkSetupController->getFailedIntegrityCheckFiles()); } + + public function dataForIsMysqlUsedWithoutUTF8MB4() { + return [ + ['sqlite', false, false], + ['sqlite', true, false], + ['postgres', false, false], + ['postgres', true, false], + ['oci', false, false], + ['oci', true, false], + ['mysql', false, true], + ['mysql', true, false], + ]; + } + + /** + * @dataProvider dataForIsMysqlUsedWithoutUTF8MB4 + */ + public function testIsMysqlUsedWithoutUTF8MB4(string $db, bool $useUTF8MB4, bool $expected) { + $this->config->method('getSystemValue') + ->will($this->returnCallback(function($key, $default) use ($db, $useUTF8MB4) { + if ($key === 'dbtype') { + return $db; + } + if ($key === 'mysql.utf8mb4') { + return $useUTF8MB4; + } + return $default; + })); + + $checkSetupController = new CheckSetupController( + 'settings', + $this->request, + $this->config, + $this->clientService, + $this->urlGenerator, + $this->util, + $this->l10n, + $this->checker, + $this->logger, + $this->dispatcher, + $this->db, + $this->lockingProvider, + $this->dateTimeFormatter, + $this->memoryInfo, + $this->secureRandom + ); + + $this->assertSame($expected, $this->invokePrivate($checkSetupController, 'isMysqlUsedWithoutUTF8MB4')); + } }