r83029 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r83028‎ | r83029 | r83030 >
Date:18:46, 1 March 2011
Author:demon
Status:deferred
Tags:
Comment:
(bug 12070) After Installation MySQL was blocked. GRANT with IDENTIFIED BY will overwrite the password of an existing user silently, moving CREATE USER and GRANT to two separate operations so we can handle the different errors. Put in HISTORY, needs backporting with RELEASE-NOTES
Modified paths:
  • /trunk/phase3/HISTORY (modified) (history)
  • /trunk/phase3/includes/installer/DatabaseInstaller.php (modified) (history)
  • /trunk/phase3/includes/installer/Installer.i18n.php (modified) (history)
  • /trunk/phase3/includes/installer/MysqlInstaller.php (modified) (history)
  • /trunk/phase3/maintenance/users.sql (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/users.sql
@@ -1,12 +0,0 @@
2 -
3 -GRANT ALL PRIVILEGES ON `{$wgDBname}`.*
4 - TO '{$wgDBuser}'@'%' IDENTIFIED BY '{$wgDBpassword}';
5 -GRANT ALL PRIVILEGES ON `{$wgDBname}`.*
6 - TO '{$wgDBuser}'@localhost IDENTIFIED BY '{$wgDBpassword}';
7 -GRANT ALL PRIVILEGES ON `{$wgDBname}`.*
8 - TO '{$wgDBuser}'@localhost.localdomain IDENTIFIED BY '{$wgDBpassword}';
Index: trunk/phase3/HISTORY
@@ -454,6 +454,7 @@
455455 * (bug 25512) Subcategory list should not include category prefix for members.
456456 * (bug 20244) Installer does not validate SQLite database directory for stable path
457457 * (bug 1379) Installer directory conflicts with some hosts' configuration panel.
 458+* (bug 12070) After Installation MySQL was blocked
458459
459460 === API changes in 1.17 ===
460461 * (bug 22738) Allow filtering by action type on query=logevent.
Index: trunk/phase3/includes/installer/Installer.i18n.php
@@ -323,6 +323,8 @@
324324 This is more efficient than MySQL's UTF-8 mode, and allows you to use the full range of Unicode characters.
325325
326326 In '''UTF-8 mode''', MySQL will know what character set your data is in, and can present and convert it appropriately, but it will not let you store characters above the [http://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
 327+ 'config-connection-user-exists' => 'The database user "$1" already exists.
 328+Please choose a new username to create or do not try to create the user.',
327329 'config-site-name' => 'Name of wiki:',
328330 'config-site-name-help' => "This will appear in the title bar of the browser and in various other places.",
329331 'config-site-name-blank' => 'Enter a site name.',
@@ -475,7 +477,9 @@
476478 'config-pg-no-plpgsql' => 'You need to install the language PL/pgSQL in the database $1',
477479 'config-pg-no-create-privs' => 'The account you specified for installation does not have enough privileges to create an account.',
478480 'config-install-user' => 'Creating database user',
479 - 'config-install-user-failed' => 'Granting permission to user "$1" failed: $2',
 481+ 'config-install-user-create-failed' => 'User "$1" already exists',
 482+ 'config-install-user-create-failed' => 'Creating user "$1" failed: $2',
 483+ 'config-install-user-grant-failed' => 'Granting permission to user "$1" failed: $2',
480484 'config-install-tables' => 'Creating tables',
481485 'config-install-tables-exist' => "'''Warning''': MediaWiki tables seem to already exist.
482486 Skipping creation.",
Index: trunk/phase3/includes/installer/DatabaseInstaller.php
@@ -149,6 +149,7 @@
150150
151151 if( $this->db->tableExists( 'user' ) ) {
152152 $status->warning( 'config-install-tables-exist' );
 153+ $this->enableLB();
153154 return $status;
154155 }
155156
Index: trunk/phase3/includes/installer/MysqlInstaller.php
@@ -419,8 +419,6 @@
420420 }
421421
422422 public function setupUser() {
423 - global $IP;
424 -
425423 if ( !$this->getVar( '_CreateDBAccount' ) ) {
426424 return Status::newGood();
427425 }
@@ -430,18 +428,117 @@
431429 return $status;
432430 }
433431
434 - $db = $this->getVar( 'wgDBname' );
435 - $this->db->selectDB( $db );
436432 $this->setupSchemaVars();
437 - $error = $this->db->sourceFile( "$IP/maintenance/users.sql" );
438 - if ( $error !== true ) {
439 - $status->fatal( 'config-install-user-failed', $this->getVar( 'wgDBuser' ), $error );
 433+ $dbName = $this->getVar( 'wgDBname' );
 434+ $this->db->selectDB( $dbName );
 435+ $server = $this->getVar( 'wgDBserver' );
 436+ $dbUser = $this->getVar( 'wgDBuser' );
 437+ $password = $this->getVar( 'wgDBpassword' );
 438+ $grantableNames = array();
 439+
 440+ // Before we blindly try to create a user that already has access,
 441+ try { // first attempt to connect to the database
 442+ new DatabaseMysql(
 443+ $server,
 444+ $dbUser,
 445+ $password,
 446+ false,
 447+ false,
 448+ 0,
 449+ $this->getVar( 'wgDBprefix' )
 450+ );
 451+ $grantableNames[] = $this->buildFullUserName( $dbUser, $server );
 452+ $tryToCreate = false;
 453+ } catch ( DBConnectionError $e ) {
 454+ $tryToCreate = true;
440455 }
441456
 457+ if( $tryToCreate ) {
 458+ $createHostList = array($server,
 459+ 'localhost',
 460+ 'localhost.localdomain',
 461+ '%'
 462+ );
 463+
 464+ $createHostList = array_unique( $createHostList );
 465+ $escPass = $this->db->addQuotes( $password );
 466+
 467+ foreach( $createHostList as $host ) {
 468+ $fullName = $this->buildFullUserName( $dbUser, $host );
 469+ if( !$this->userDefinitelyExists( $dbUser, $host ) ) {
 470+ try{
 471+ $this->db->begin();
 472+ $this->db->query( "CREATE USER $fullName IDENTIFIED BY $escPass", __METHOD__ );
 473+ $this->db->commit();
 474+ $grantableNames[] = $fullName;
 475+ } catch( DBQueryError $dqe ) {
 476+ if( $this->db->lastErrno() == 1396 /* ER_CANNOT_USER */ ) {
 477+ // User (probably) already exists
 478+ $this->db->rollback();
 479+ $status->warning( 'config-install-user-alreadyexists', $dbUser );
 480+ $grantableNames[] = $fullName;
 481+ break;
 482+ } else {
 483+ // If we couldn't create for some bizzare reason and the
 484+ // user probably doesn't exist, skip the grant
 485+ $this->db->rollback();
 486+ $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
 487+ }
 488+ }
 489+ } else {
 490+ $status->warning( 'config-install-user-alreadyexists', $dbUser );
 491+ $grantableNames[] = $fullName;
 492+ break;
 493+ }
 494+ }
 495+ }
 496+
 497+ // Try to grant to all the users we know exist or we were able to create
 498+ $escPass = $this->db->addQuotes( $password );
 499+ $dbAllTables = $this->db->addIdentifierQuotes( $dbName ) . '.*';
 500+ foreach( $grantableNames as $name ) {
 501+ try {
 502+ $this->db->begin();
 503+ $this->db->query( "GRANT ALL PRIVILEGES ON $dbAllTables TO $name", __METHOD__ );
 504+ $this->db->commit();
 505+ } catch( DBQueryError $dqe ) {
 506+ $this->db->rollback();
 507+ $status->fatal( 'config-install-user-grant-failed', $dbUser, $dqe->getText() );
 508+ }
 509+ }
 510+
442511 return $status;
443512 }
444513
445514 /**
 515+ * Return a formal 'User'@'Host' username for use in queries
 516+ * @param $name String Username, quotes will be added
 517+ * @param $host String Hostname, quotes will be added
 518+ * @return String
 519+ */
 520+ private function buildFullUserName( $name, $host ) {
 521+ return $this->db->addQuotes( $name ) . '@' . $this->db->addQuotes( $host );
 522+ }
 523+
 524+ /**
 525+ * Try to see if the user account exists. Our "superuser" may not have
 526+ * access to mysql.user, so false means "no" or "maybe"
 527+ * @param $host String Hostname to check
 528+ * @param $user String Username to check
 529+ * @return boolean
 530+ */
 531+ private function userDefinitelyExists( $host, $user ) {
 532+ try {
 533+ $res = $this->db->selectRow( 'mysql.user', array( 'Host', 'User' ),
 534+ array( 'Host' => $host, 'User' => $user ), __METHOD__ );
 535+ return (bool)$res;
 536+ } catch( DBQueryError $dqe ) {
 537+ return false;
 538+ }
 539+
 540+ }
 541+
 542+ /**
446543 * Return any table options to be applied to all tables that don't
447544 * override them.
448545 *

Follow-up revisions

RevisionCommit summaryAuthorDate
r83030Followup r83029, message key fixesdemon18:49, 1 March 2011
r87306Remove empty files left by r16526, r29128 and r83029platonides22:36, 2 May 2011

Status & tagging log