Split user table into two parts: user and user_rights, for single login. BUG#57
authorJens Frank <jeluf@users.mediawiki.org>
Tue, 24 Aug 2004 20:41:07 +0000 (20:41 +0000)
committerJens Frank <jeluf@users.mediawiki.org>
Tue, 24 Aug 2004 20:41:07 +0000 (20:41 +0000)
config/index.php
includes/SpecialListadmins.php
includes/SpecialListusers.php
includes/SpecialMakesysop.php
includes/SpecialStatistics.php
includes/User.php
maintenance/archives/patch-user_rights.sql [new file with mode: 0644]
maintenance/tables.sql
maintenance/updaters.inc
maintenance/users.sql

index 3df6ad8..0f6f235 100644 (file)
@@ -479,6 +479,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                        do_categorylinks_update(); flush();
                        do_image_name_unique_update(); flush();
                        do_logging_update(); flush();
+                       do_user_rights_update(); flush();
 
                        if ( isTemplateInitialised() ) {
                                print "Template namespace already initialised\n";
index 41588d9..39d86fd 100644 (file)
@@ -18,11 +18,11 @@ class ListAdminsPage extends PageQueryPage {
        function getSQL() {
                $dbr =& wfGetDB( DB_SLAVE );
                $user = $dbr->tableName( 'user' );
+               $user_rights = $dbr->tableName( 'user_rights' );
                $userspace = Namespace::getUser();
-               return 'SELECT user_rights as type,'.$userspace.' as namespace,'.
-                      'user_name as title, user_name as value '.
-                      "FROM $user ".
-                          'WHERE user_rights LIKE "%sysop%"';
+               return "SELECT r.user_rights as type,{$userspace} as namespace,".
+                      "u.user_name as title, u.user_name as value ".
+                      "FROM {$user} u,{$user_rights} r WHERE r.user_id=u.user_id AND r.user_rights LIKE \"%sysop%\"";
        }
 }
 
index 0d8aa61..1e32ade 100644 (file)
@@ -14,10 +14,11 @@ class ListUsersPage extends QueryPage {
 
        function getSQL() {
                $dbr =& wfGetDB( DB_SLAVE );
-               $usertable = $dbr->tableName( 'user' );
+               $user = $dbr->tableName( 'user' );
+               $user_rights = $dbr->tableName( 'user_rights' );
                $userspace = Namespace::getUser();
-               return "SELECT user_rights as type, $userspace as namespace, user_name as title, " .
-                       "user_name as value FROM $usertable";
+               return "SELECT r.user_rights as type, $userspace as namespace, u.user_name as title, " .
+                       "u.user_name as value FROM $user u LEFT JOIN $user_rights r ON u.user_id = r.user_id";
        }
        
        function sortDescending() {
index cc3cbf8..15fa120 100644 (file)
@@ -123,16 +123,20 @@ class MakesysopForm {
        {
                global $wgOut, $wgUser, $wgLang;
                global $wgDBname, $wgMemc, $wgLocalDatabases;
+
+               $fname = 'MakesysopForm::doSubmit';
                
                $dbw =& wfGetDB( DB_MASTER );
-               $parts = explode( "@", $this->mUser );
-               $usertable = $dbw->tableName( 'user' );
+               $parts = explode( '@', $this->mUser );
+               $user_rights = $dbw->tableName( 'user_rights' );
+               $usertable   = $dbw->tableName( 'user' );
 
-               if( count( $parts ) == 2 && $wgUser->isDeveloper() && strpos( '.', $usertable ) === false ){
+               if( count( $parts ) == 2 && $wgUser->isDeveloper() && strpos( '.', $user_rights ) === false ){
                        $username = $dbw->strencode( $parts[0] );
                        if ( array_key_exists( $parts[1], $wgLocalDatabases ) ) {
                                $dbName = $wgLocalDatabases[$parts[1]];
-                               $usertable = $dbName . "." . $usertable;
+                               $user_rights = $dbName . '.' . $user_rights;
+                               $usertable   = $usertable . '.' . $usertable;
                        } else {
                                $this->showFail();
                                return;
@@ -143,10 +147,10 @@ class MakesysopForm {
                }
                if ( $username{0} == "#" ) {
                        $id = intval( substr( $username, 1 ) );
-                       $sql = "SELECT user_id,user_rights FROM $usertable WHERE user_id=$id FOR UPDATE";
+                       $sql = "SELECT user_id,user_rights FROM $user_rights WHERE user_id=$id FOR UPDATE";
                } else {
                        $encName = $dbw->strencode( $username );
-                       $sql = "SELECT user_id, user_rights FROM $usertable WHERE user_name = '{$username}' FOR UPDATE";
+                       $sql = "SELECT u.user_id, user_rights FROM $usertable u LEFT JOIN $user_rights r ON u.user_id=r.user_id WHERE user_name = '{$username}' FOR UPDATE";
                }
                
                $prev = $dbw->ignoreErrors( TRUE );
@@ -190,8 +194,10 @@ class MakesysopForm {
                if ( count( $rightsNotation ) == 0 ) {
                        $this->showFail();
                } else {
-                       $sql = "UPDATE $usertable SET user_rights = '{$newrights}' WHERE user_id = $id LIMIT 1";
-                       $dbw->query($sql);
+                       #$sql = "UPDATE $user_rights SET user_rights = '{$newrights}' WHERE user_id = $id LIMIT 1";
+                       #$dbw->query($sql);
+                       $dbw->replace( $user_rights, array( array( 'user_id', 'user_rights' )),
+                               array( 'user_id' => $id, 'user_rights' => $newrights ) , $fname );
                        $wgMemc->delete( "$dbName:user:id:$id" );
                        
                        $log = new LogPage( 'rights' );
index 6995c03..67fcc61 100644 (file)
@@ -8,7 +8,7 @@ function wfSpecialStatistics()
        $wgOut->addHTML( "<h2>" . wfMsg( "sitestats" ) . "</h2>\n" );
        
        $dbr =& wfGetDB( DB_SLAVE );
-       extract( $dbr->tableNames( 'cur', 'site_stats', 'user' ) );
+       extract( $dbr->tableNames( 'cur', 'site_stats', 'user', 'user_rights' ) );
 
        $sql = "SELECT COUNT(cur_id) AS total FROM $cur";
        $res = $dbr->query( $sql, $fname );
@@ -39,8 +39,7 @@ function wfSpecialStatistics()
        $row = $dbr->fetchObject( $res );
        $total = $row->total;
 
-       $sql = "SELECT COUNT(user_id) AS total FROM $user " .
-         "WHERE user_rights LIKE '%sysop%'";
+       $sql = "SELECT COUNT(user_id) AS total FROM $user_rights WHERE user_rights LIKE '%sysop%'";
        $res = $dbr->query( $sql, $fname );
        $row = $dbr->fetchObject( $res );
        $admins = $row->total;
index 294923d..7c3fb2f 100644 (file)
@@ -266,7 +266,7 @@ class User {
                } # the following stuff is for non-anonymous users only
 
                $s = $dbr->getArray( 'user', array( 'user_name','user_password','user_newpassword','user_email',
-                 'user_real_name','user_options','user_rights','user_touched' ),
+                 'user_real_name','user_options','user_touched' ),
                  array( 'user_id' => $this->mId ), $fname );
 
                if ( $s !== false ) {
@@ -276,8 +276,10 @@ class User {
                        $this->mPassword = $s->user_password;
                        $this->mNewpassword = $s->user_newpassword;
                        $this->decodeOptions( $s->user_options );
-                       $this->mRights = explode( ",", strtolower( $s->user_rights ) );
                        $this->mTouched = wfTimestamp(TS_MW,$s->user_touched);
+                       $this->mRights = explode( ",", strtolower( 
+                               $dbr->getField( 'user_rights', 'user_rights', array( 'user_id' => $this->mId ) )
+                       ) );
                }
 
                $this->mDataLoaded = true;
@@ -573,12 +575,13 @@ class User {
                                'user_real_name' => $this->mRealName,
                                'user_email' => $this->mEmail,
                                'user_options' => $this->encodeOptions(),
-                               'user_rights' => implode( ",", $this->mRights ),
                                'user_touched' => $dbw->timestamp($this->mTouched)
                        ), array( /* WHERE */
                                'user_id' => $this->mId
                        ), $fname
                );
+               $dbw->set( 'user_rights', 'user_rights', implode( ",", $this->mRights ),
+                       'user_id='. $this->mId, $fname ); 
                $wgMemc->delete( "$wgDBname:user:id:$this->mId" );
        }
 
@@ -611,11 +614,17 @@ class User {
                                'user_newpassword' => $this->mNewpassword,
                                'user_email' => $this->mEmail,
                                'user_real_name' => $this->mRealName,
-                               'user_rights' => implode( ',', $this->mRights ),
                                'user_options' => $this->encodeOptions()
                        ), $fname
                );
                $this->mId = $dbw->insertId();
+               $dbw->insert( 'user_rights',
+                       array(
+                               'user_id' => $this->mId,
+                               'user_rights' => implode( ',', $this->mRights )
+                       ), $fname
+               );
+                               
        }
 
        function spreadBlock()
diff --git a/maintenance/archives/patch-user_rights.sql b/maintenance/archives/patch-user_rights.sql
new file mode 100644 (file)
index 0000000..5d799de
--- /dev/null
@@ -0,0 +1,16 @@
+-- Split user table into two parts:
+--   user
+--   user_rights
+-- The later contains only the permissions of the user. This way,
+-- you can store the accounts for several wikis in one central
+-- database but keep user rights local to the wiki.
+
+CREATE TABLE user_rights (
+       user_id int(5) unsigned NOT NULL,
+       user_rights tinyblob NOT NULL default '',
+       UNIQUE KEY user_id (user_id)
+) PACK_KEYS=1;
+
+INSERT INTO user_rights SELECT user_id,user_rights FROM user;
+
+ALTER TABLE user DROP COLUMN user_rights;
index 892c271..2eb8520 100644 (file)
@@ -8,7 +8,6 @@ CREATE TABLE user (
   user_id int(5) unsigned NOT NULL auto_increment,
   user_name varchar(255) binary NOT NULL default '',
   user_real_name varchar(255) binary NOT NULL default '',
-  user_rights tinyblob NOT NULL default '',
   user_password tinyblob NOT NULL default '',
   user_newpassword tinyblob NOT NULL default '',
   user_email tinytext NOT NULL default '',
@@ -17,6 +16,12 @@ CREATE TABLE user (
   UNIQUE KEY user_id (user_id)
 ) PACK_KEYS=1;
 
+CREATE TABLE user_rights (
+  user_id int(5) unsigned NOT NULL,
+  user_rights tinyblob NOT NULL default '',
+  UNIQUE KEY user_id (user_id)
+) PACK_KEYS=1;
+
 CREATE TABLE user_newtalk (
   user_id int(5) NOT NULL default '0',
   user_ip varchar(40) NOT NULL default ''
index 54b3f04..dcfab0b 100644 (file)
@@ -217,4 +217,15 @@ function do_logging_update() {
        }
 }
 
+function do_user_rights_update() {
+       global $wgDatabase;
+       if ( $wgDatabase->tableExists( 'user_rights' ) ) {
+               echo "...user_rights table already exists.\n";
+       } else {
+               echo 'Creating user rights table...';
+               dbsource( 'maintenance/archives/patch-user_rights.sql', $wgDatabase );
+               echo "ok\n";
+       }
+}
+
 ?>
index 0c2ce7c..dc23ed3 100644 (file)
@@ -18,7 +18,9 @@ GRANT DELETE,INSERT,SELECT,UPDATE ON `{$wgDBname}`.*
 GRANT DELETE,INSERT,SELECT,UPDATE ON `{$wgDBname}`.*
  TO {$wgDBuser}@localhost.localdomain IDENTIFIED BY '{$wgDBpassword}';
 
-GRANT SELECT (user_id,user_name,user_rights,user_options) ON `{$wgDBname}`.user
+GRANT SELECT (user_id,user_name,user_options) ON `{$wgDBname}`.user
+ TO {$wgDBsqluser}@'%' IDENTIFIED BY '{$wgDBsqlpassword}';
+GRANT SELECT ON `{$wgDBname}`.user_rights
  TO {$wgDBsqluser}@'%' IDENTIFIED BY '{$wgDBsqlpassword}';
 GRANT SELECT ON `{$wgDBname}`.cur
  TO {$wgDBsqluser}@'%' IDENTIFIED BY '{$wgDBsqlpassword}';
@@ -47,9 +49,11 @@ GRANT SELECT ON `{$wgDBname}`.watchlist
 GRANT SELECT ON `{$wgDBname}`.math
  TO {$wgDBsqluser}@'%' IDENTIFIED BY '{$wgDBsqlpassword}';
 
-GRANT SELECT (user_id,user_name,user_rights,user_options)
+GRANT SELECT (user_id,user_name,user_options)
  ON `{$wgDBname}`.user
  TO {$wgDBsqluser}@localhost IDENTIFIED BY '{$wgDBsqlpassword}';
+GRANT SELECT ON `{$wgDBname}`.user_rights
+ TO {$wgDBsqluser}@localhost IDENTIFIED BY '{$wgDBsqlpassword}';
 GRANT SELECT ON `{$wgDBname}`.cur
  TO {$wgDBsqluser}@localhost IDENTIFIED BY '{$wgDBsqlpassword}';
 GRANT SELECT ON `{$wgDBname}`.old
@@ -77,9 +81,11 @@ GRANT SELECT ON `{$wgDBname}`.watchlist
 GRANT SELECT ON `{$wgDBname}`.math
  TO {$wgDBsqluser}@localhost IDENTIFIED BY '{$wgDBsqlpassword}';
 
-GRANT SELECT (user_id,user_name,user_rights,user_options)
+GRANT SELECT (user_id,user_name,user_options)
  ON `{$wgDBname}`.user
  TO {$wgDBsqluser}@localhost.localdomain IDENTIFIED BY '{$wgDBsqlpassword}';
+GRANT SELECT ON `{$wgDBname}`.user_rights
+ TO {$wgDBsqluser}@localhost.localdomain IDENTIFIED BY '{$wgDBsqlpassword}';
 GRANT SELECT ON `{$wgDBname}`.cur
  TO {$wgDBsqluser}@localhost.localdomain IDENTIFIED BY '{$wgDBsqlpassword}';
 GRANT SELECT ON `{$wgDBname}`.old