From 31fb0896a0881c34fa4d3989248e42d3bb806ab5 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 | 88 ++++++++++++++++--- settings/Controller/CheckSetupController.php | 5 ++ .../Controller/CheckSetupControllerTest.php | 56 ++++++++++++ 4 files changed, 148 insertions(+), 13 deletions(-) diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index b1213c2c0421e..67f75c8206f4c 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -450,6 +450,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 55122eda0f024..ffa7aaec3ea69 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -248,7 +248,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -299,7 +300,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -351,7 +353,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -401,7 +404,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -449,7 +453,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -499,7 +504,8 @@ describe('OC.SetupChecks tests', function() { '/some/path' ], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -547,7 +553,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -595,7 +602,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -643,7 +651,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: false, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -712,7 +721,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -761,7 +771,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -810,7 +821,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -859,7 +871,8 @@ describe('OC.SetupChecks tests', function() { isMemoryLimitSufficient: true, appDirsWithDifferentOwner: [], recommendedPHPModules: [], - pendingBigIntConversionColumns: [] + pendingBigIntConversionColumns: [], + isMysqlUsedWithoutUTF8MB4: false }) ); @@ -871,6 +884,55 @@ 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: [], + outdatedCaches: [], + 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 92c2b1b47dba6..b86f25a7fea28 100644 --- a/settings/Controller/CheckSetupController.php +++ b/settings/Controller/CheckSetupController.php @@ -605,6 +605,10 @@ protected function hasRecommendedPHPModules(): array { 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 = [ @@ -679,6 +683,7 @@ public function check() { '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 01d2178fd7f30..8a491d0d047ff 100644 --- a/tests/Settings/Controller/CheckSetupControllerTest.php +++ b/tests/Settings/Controller/CheckSetupControllerTest.php @@ -160,6 +160,7 @@ public function setUp() { 'getAppDirsWithDifferentOwner', 'hasRecommendedPHPModules', 'hasBigIntConversionPendingColumns', + 'isMysqlUsedWithoutUTF8MB4', ])->getMock(); } @@ -499,6 +500,11 @@ public function testCheck() { ->method('hasBigIntConversionPendingColumns') ->willReturn([]); + $this->checkSetupController + ->expects($this->once()) + ->method('isMysqlUsedWithoutUTF8MB4') + ->willReturn(false); + $expected = new DataResponse( [ 'isGetenvServerWorking' => true, @@ -543,6 +549,7 @@ public function testCheck() { 'appDirsWithDifferentOwner' => [], 'recommendedPHPModules' => [], 'pendingBigIntConversionColumns' => [], + 'isMysqlUsedWithoutUTF8MB4' => false, ] ); $this->assertEquals($expected, $this->checkSetupController->check()); @@ -1324,4 +1331,53 @@ public function testGetFailedIntegrityCheckFilesWithSomeErrorsFound() { ); $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')); + } }