Browse Source

Add setup check for missing UTF8MB4 on mysql

Signed-off-by: Morris Jobke <hey@morrisjobke.de>
Morris Jobke 5 năm trước cách đây
mục cha
commit
31fb0896a0

+ 12 - 0
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 <a target="_blank" rel="noreferrer noopener" href="{docLink}">the documentation page about this</a>.',
+								{
+									docLink: oc_defaults.docPlaceholderUrl.replace('PLACEHOLDER', 'admin-mysql-utf8mb4'),
+								}
+							),
+							type: OC.SetupChecks.MESSAGE_TYPE_WARNING
+						})
+					}
 
 				} else {
 					messages.push({

+ 75 - 13
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 <a href="https://docs.example.org/admin-mysql-utf8mb4" rel="noreferrer noopener">the documentation page about this</a>.',
+					type: OC.SetupChecks.MESSAGE_TYPE_WARNING
+				}]);
+				done();
+			});
+		});
 	});
 
 	describe('checkGeneric', function() {

+ 5 - 0
settings/Controller/CheckSetupController.php

@@ -605,6 +605,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 = [
@@ -679,6 +683,7 @@ Raw output
 				'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(),
 				'recommendedPHPModules' => $this->hasRecommendedPHPModules(),
 				'pendingBigIntConversionColumns' => $this->hasBigIntConversionPendingColumns(),
+				'isMysqlUsedWithoutUTF8MB4' => $this->isMysqlUsedWithoutUTF8MB4(),
 			]
 		);
 	}

+ 56 - 0
tests/Settings/Controller/CheckSetupControllerTest.php

@@ -160,6 +160,7 @@ class CheckSetupControllerTest extends TestCase {
 				'getAppDirsWithDifferentOwner',
 				'hasRecommendedPHPModules',
 				'hasBigIntConversionPendingColumns',
+				'isMysqlUsedWithoutUTF8MB4',
 			])->getMock();
 	}
 
@@ -499,6 +500,11 @@ class CheckSetupControllerTest extends TestCase {
 			->method('hasBigIntConversionPendingColumns')
 			->willReturn([]);
 
+		$this->checkSetupController
+			->expects($this->once())
+			->method('isMysqlUsedWithoutUTF8MB4')
+			->willReturn(false);
+
 		$expected = new DataResponse(
 			[
 				'isGetenvServerWorking' => true,
@@ -543,6 +549,7 @@ class CheckSetupControllerTest extends TestCase {
 				'appDirsWithDifferentOwner' => [],
 				'recommendedPHPModules' => [],
 				'pendingBigIntConversionColumns' => [],
+				'isMysqlUsedWithoutUTF8MB4' => false,
 			]
 		);
 		$this->assertEquals($expected, $this->checkSetupController->check());
@@ -1324,4 +1331,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'));
+	}
 }