MediaWiki REL1_34
UpdateTables.php
Go to the documentation of this file.
1<?php
2
4
8use Wikimedia;
9use FormatJson;
11
16 protected $updater;
17
21 protected $base;
22
27 public static function callback( $updater ) {
28 $dir = dirname( dirname( dirname( __DIR__ ) ) );
29 $handler = new static( $updater, $dir );
30 return $handler->execute();
31 }
32
37 protected function __construct( $updater, $base ) {
38 $this->updater = $updater;
39 $this->base = $base;
40 }
41
42 protected function execute() {
43 switch ( $this->updater->getDB()->getType() ) {
44 case 'mysql':
45 case 'sqlite':
46 $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/mysql/tables.sql" );
47 $this->updater->addExtensionUpdate( [ [ $this, 'schemaUpdateOldUsersFromInstaller' ] ] );
48 $this->updater->dropExtensionField(
49 'oathauth_users',
50 'secret_reset',
51 "{$this->base}/sql/mysql/patch-remove_reset.sql"
52 );
53 $this->updater->addExtensionField(
54 'oathauth_users',
55 'module',
56 "{$this->base}/sql/mysql/patch-add_generic_fields.sql"
57 );
58
59 $this->updater->addExtensionUpdate(
60 [ [ __CLASS__, 'schemaUpdateSubstituteForGenericFields' ] ]
61 );
62 $this->updater->dropExtensionField(
63 'oathauth_users',
64 'secret',
65 "{$this->base}/sql/mysql/patch-remove_module_specific_fields.sql"
66 );
67
68 $this->updater->addExtensionUpdate(
69 [ [ __CLASS__, 'schemaUpdateTOTPToMultipleKeys' ] ]
70 );
71
72 break;
73
74 case 'oracle':
75 $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/oracle/tables.sql" );
76 break;
77
78 case 'postgres':
79 $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/postgres/tables.sql" );
80 break;
81 }
82
83 return true;
84 }
85
94 global $wgOATHAuthDatabase;
95 $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
96 ->getMainLB( $wgOATHAuthDatabase );
97 $dbw = $lb->getConnectionRef( DB_MASTER, [], $wgOATHAuthDatabase );
98 return self::schemaUpdateOldUsers( $dbw );
99 }
100
108 global $wgOATHAuthDatabase;
109 $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
110 ->getMainLB( $wgOATHAuthDatabase );
111 $dbw = $lb->getConnectionRef( DB_MASTER, [], $wgOATHAuthDatabase );
112 return self::convertToGenericFields( $dbw );
113 }
114
122 global $wgOATHAuthDatabase;
123 $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
124 ->getMainLB( $wgOATHAuthDatabase );
125 $dbw = $lb->getConnectionRef( DB_MASTER, [], $wgOATHAuthDatabase );
126 return self::switchTOTPToMultipleKeys( $dbw );
127 }
128
135 public static function convertToGenericFields( IDatabase $db ) {
136 if ( !$db->fieldExists( 'oathauth_users', 'secret' ) ) {
137 return true;
138 }
139
140 $services = MediaWikiServices::getInstance();
141 $batchSize = $services->getMainConfig()->get( 'UpdateRowsPerQuery' );
142 $lbFactory = $services->getDBLoadBalancerFactory();
143 while ( true ) {
144 $lbFactory->waitForReplication();
145
146 $res = $db->select(
147 'oathauth_users',
148 [ 'id', 'secret', 'scratch_tokens' ],
149 [
150 'module' => '',
151 'data IS NULL',
152 'secret IS NOT NULL'
153 ],
154 __METHOD__,
155 [ 'LIMIT' => $batchSize ]
156 );
157
158 if ( $res->numRows() === 0 ) {
159 return true;
160 }
161
162 foreach ( $res as $row ) {
163 $db->update(
164 'oathauth_users',
165 [
166 'module' => 'totp',
167 'data' => FormatJson::encode( [
168 'keys' => [ [
169 'secret' => $row->secret,
170 'scratch_tokens' => $row->scratch_tokens
171 ] ]
172 ] )
173 ],
174 [ 'id' => $row->id ],
175 __METHOD__
176 );
177 }
178 }
179
180 return true;
181 }
182
190 public static function switchTOTPToMultipleKeys( IDatabase $db ) {
191 if ( !$db->fieldExists( 'oathauth_users', 'data' ) ) {
192 return true;
193 }
194
195 $res = $db->select(
196 'oathauth_users',
197 [ 'id', 'data' ],
198 [
199 'module' => 'totp'
200 ],
201 __METHOD__
202 );
203
204 foreach ( $res as $row ) {
205 $data = FormatJson::decode( $row->data, true );
206 if ( isset( $data['keys'] ) ) {
207 continue;
208 }
209 $db->update(
210 'oathauth_users',
211 [
212 'data' => FormatJson::encode( [
213 'keys' => [ $data ]
214 ] )
215 ],
216 [ 'id' => $row->id ],
217 __METHOD__
218 );
219 }
220
221 return true;
222 }
223
230 public static function schemaUpdateOldUsers( IDatabase $db ) {
231 if ( !$db->fieldExists( 'oathauth_users', 'secret_reset' ) ) {
232 return true;
233 }
234
235 $res = $db->select(
236 'oathauth_users',
237 [ 'id', 'scratch_tokens' ],
238 [ 'is_validated != 0' ],
239 __METHOD__
240 );
241
242 foreach ( $res as $row ) {
243 Wikimedia\suppressWarnings();
244 $scratchTokens = unserialize( base64_decode( $row->scratch_tokens ) );
245 Wikimedia\restoreWarnings();
246 if ( $scratchTokens ) {
247 $db->update(
248 'oathauth_users',
249 [ 'scratch_tokens' => implode( ',', $scratchTokens ) ],
250 [ 'id' => $row->id ],
251 __METHOD__
252 );
253 }
254 }
255
256 // Remove rows from the table where user never completed the setup process
257 $db->delete( 'oathauth_users', [ 'is_validated' => 0 ], __METHOD__ );
258
259 return true;
260 }
261}
unserialize( $serialized)
Exceptions for config failures.
Class for handling database updates.
JSON formatter wrapper class.
static convertToGenericFields(IDatabase $db)
Converts old, TOTP specific, column values to new structure.
schemaUpdateOldUsersFromInstaller(DatabaseUpdater $updater)
Helper function for converting old users to the new schema.
static schemaUpdateOldUsers(IDatabase $db)
Helper function for converting old users to the new schema.
static switchTOTPToMultipleKeys(IDatabase $db)
Switch from using single keys to multi-key support.
static schemaUpdateTOTPToMultipleKeys(DatabaseUpdater $updater)
Helper function for converting single TOTP keys to multi-key system.
static schemaUpdateSubstituteForGenericFields(DatabaseUpdater $updater)
Helper function for converting old, TOTP specific, column values to new structure.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static getInstance()
Returns the global default instance of the top level service locator.
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:38
select( $table, $vars, $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
Execute a SELECT query constructed using the various parameters provided.
delete( $table, $conds, $fname=__METHOD__)
DELETE query wrapper.
update( $table, $values, $conds, $fname=__METHOD__, $options=[])
UPDATE wrapper.
fieldExists( $table, $field, $fname=__METHOD__)
Determines whether a field exists in a table.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
const DB_MASTER
Definition defines.php:26