mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/OATHAuth
synced 2024-12-04 04:38:13 +00:00
6ef3d2418a
This adds new database tables to support storing multiple authentication factors for a single user. The current approach taken is to use a single database row per 2fa method and key. The current module/key abstraction will have to be updated to support having multiple module types for a single user (for example for having a separate module for recovery codes), but this patch does not address that and instead keeps the existing limitations, however the needed updates for that should be doable with this database schema. I've decided to add a new table instead of modifying the existing oathauth_users table. This is mainly because adding an auto_increment column to the existing table would be difficult, but also allows us to update the table definition to follow MW conventions (namely the column name prefixes). I've also used the opportunity to normalize the device types onto a separate table. The migration stage variable is set to SCHEMA_COMPAT_NEW so that third-party wikis can use update.php normally and don't have to adjust anything. This means that it needs to be manually set to _OLD on wmf-config before merging this patch. Since we're already working with the database schema, this add a new, currently unused column for the creation data, so that T242847 will not require a new schema change. Bug: T242031 Bug: T242847 Change-Id: I6aa69c089340434737b55201b80398708a70c355
128 lines
3.2 KiB
PHP
128 lines
3.2 KiB
PHP
<?php
|
|
/**
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
* @file
|
|
*/
|
|
|
|
namespace MediaWiki\Extension\OATHAuth\Maintenance;
|
|
|
|
use FormatJson;
|
|
use LoggedUpdateMaintenance;
|
|
use MediaWiki\Extension\OATHAuth\OATHAuthServices;
|
|
|
|
if ( getenv( 'MW_INSTALL_PATH' ) ) {
|
|
$IP = getenv( 'MW_INSTALL_PATH' );
|
|
} else {
|
|
$IP = __DIR__ . '/../../..';
|
|
}
|
|
require_once "$IP/maintenance/Maintenance.php";
|
|
|
|
/**
|
|
* @author Taavi Väänänen <hi@taavi.wtf>
|
|
*/
|
|
class UpdateForMultipleDevicesSupport extends LoggedUpdateMaintenance {
|
|
public function __construct() {
|
|
parent::__construct();
|
|
$this->requireExtension( 'OATHAuth' );
|
|
$this->setBatchSize( 500 );
|
|
}
|
|
|
|
protected function doDBUpdates() {
|
|
$database = OATHAuthServices::getInstance()->getDatabase();
|
|
$dbw = $database->getDB( DB_PRIMARY );
|
|
|
|
$maxId = $dbw->newSelectQueryBuilder()
|
|
->select( 'MAX(id)' )
|
|
->from( 'oathauth_users' )
|
|
->caller( __METHOD__ )
|
|
->fetchField();
|
|
|
|
$typeIds = OATHAuthServices::getInstance()->getModuleRegistry()->getModuleIds();
|
|
|
|
$updated = 0;
|
|
|
|
for ( $min = 0; $min <= $maxId; $min += $this->getBatchSize() ) {
|
|
$max = $min + $this->getBatchSize();
|
|
$this->output( "Now processing rows with id between $min and $max... (updated $updated users so far)\n" );
|
|
|
|
$res = $dbw->newSelectQueryBuilder()
|
|
->select( [
|
|
'id',
|
|
'module',
|
|
'data',
|
|
] )
|
|
->from( 'oathauth_users' )
|
|
->where( [
|
|
$dbw->buildComparison( '>=', [ 'id' => $min ] ),
|
|
$dbw->buildComparison( '<', [ 'id' => $max ] ),
|
|
] )
|
|
->caller( __METHOD__ )
|
|
->fetchResultSet();
|
|
|
|
$toDelete = [];
|
|
$toAdd = [];
|
|
|
|
foreach ( $res as $row ) {
|
|
$decodedData = FormatJson::decode( $row->data, true );
|
|
if ( isset( $decodedData['keys'] ) ) {
|
|
$toDelete[] = (int)$row->id;
|
|
|
|
$updated += 1;
|
|
|
|
foreach ( $decodedData['keys'] as $keyData ) {
|
|
$toAdd[] = [
|
|
'oad_user' => (int)$row->id,
|
|
'oad_type' => $typeIds[$row->module],
|
|
'oad_data' => FormatJson::encode( $keyData ),
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $toAdd ) {
|
|
$dbw->startAtomic( __METHOD__ );
|
|
$dbw->insert(
|
|
'oathauth_devices',
|
|
$toAdd,
|
|
__METHOD__
|
|
);
|
|
$dbw->delete(
|
|
'oathauth_users',
|
|
[ 'id' => $toDelete ],
|
|
__METHOD__
|
|
);
|
|
$dbw->endAtomic( __METHOD__ );
|
|
}
|
|
|
|
$database->waitForReplication();
|
|
}
|
|
|
|
$this->output( "Done, updated data for $updated users.\n" );
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
protected function getUpdateKey() {
|
|
return __CLASS__;
|
|
}
|
|
}
|
|
|
|
$maintClass = UpdateForMultipleDevicesSupport::class;
|
|
require_once RUN_MAINTENANCE_IF_MAIN;
|