Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 66 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
CentralAuthDeleteLocalPasswords | |
0.00% |
0 / 60 |
|
0.00% |
0 / 6 |
272 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
initialize | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
getUserBatches | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
getUserDB | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
getWikis | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
12 | |||
getUsers | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | use MediaWiki\Extension\CentralAuth\CentralAuthServices; |
4 | use MediaWiki\MediaWikiServices; |
5 | use MediaWiki\WikiMap\WikiMap; |
6 | use Wikimedia\Rdbms\SelectQueryBuilder; |
7 | |
8 | $IP = getenv( 'MW_INSTALL_PATH' ); |
9 | if ( $IP === false ) { |
10 | $IP = __DIR__ . '/../../..'; |
11 | } |
12 | require_once "$IP/maintenance/includes/DeleteLocalPasswords.php"; |
13 | |
14 | // @phpcs:ignore MediaWiki.Files.ClassMatchesFilename.NotMatch |
15 | class CentralAuthDeleteLocalPasswords extends DeleteLocalPasswords { |
16 | /** @var string|null Wiki to run on, or null for all. */ |
17 | protected $wiki; |
18 | |
19 | /** @var string|null The wiki being currently processed */ |
20 | protected $currentWiki; |
21 | |
22 | public function __construct() { |
23 | parent::__construct(); |
24 | $this->requireExtension( 'CentralAuth' ); |
25 | $this->addDescription( 'Deletes local password for users with a central account.' ); |
26 | |
27 | $this->addOption( 'wiki', 'If specified, only runs against local names from this wiki', |
28 | false, true ); |
29 | $this->addOption( 'allwikis', 'If specified, checks all wikis. This is for the benefit ' |
30 | . "of frameworks which always add a 'wiki' parameter.", false, false ); |
31 | } |
32 | |
33 | protected function initialize() { |
34 | parent::initialize(); |
35 | $wiki = $this->getOption( 'wiki', false ); |
36 | if ( $wiki !== false && !$this->getOption( 'allwikis' ) ) { |
37 | $this->wiki = $wiki; |
38 | } |
39 | } |
40 | |
41 | /** @inheritDoc */ |
42 | protected function getUserBatches() { |
43 | // since the keys on localnames are not conducive to batch operations and |
44 | // because of the database shards, grab a list of the wikis and we will |
45 | // iterate from there |
46 | foreach ( $this->getWikis() as $wiki ) { |
47 | $this->output( "Processing users for $wiki ...\n" ); |
48 | |
49 | if ( !WikiMap::getWiki( $wiki ) ) { |
50 | $this->error( "$wiki does not exist, use checkLocalUser.php to delete invalid records\n" ); |
51 | continue; |
52 | } |
53 | |
54 | $this->currentWiki = $wiki; |
55 | foreach ( $this->getUsers( $wiki ) as $users ) { |
56 | yield $users; |
57 | } |
58 | } |
59 | } |
60 | |
61 | /** @inheritDoc */ |
62 | protected function getUserDB() { |
63 | if ( $this->currentWiki === null ) { |
64 | throw new LogicException( 'Tried to get wiki DB before wiki was selected' ); |
65 | } |
66 | return MediaWikiServices::getInstance()->getDBLoadBalancerFactory() |
67 | ->getMainLB( $this->currentWiki ) |
68 | ->getMaintenanceConnectionRef( DB_PRIMARY, [], $this->currentWiki ); |
69 | } |
70 | |
71 | /** |
72 | * @return array|null[]|string[] |
73 | */ |
74 | protected function getWikis() { |
75 | $centralReplica = CentralAuthServices::getDatabaseManager()->getCentralReplicaDB(); |
76 | |
77 | if ( $this->wiki !== null ) { |
78 | return [ $this->wiki ]; |
79 | } else { |
80 | $conds = []; |
81 | if ( $this->user !== null ) { |
82 | $conds['lu_name'] = $this->user; |
83 | } |
84 | return $centralReplica->newSelectQueryBuilder() |
85 | ->select( 'lu_wiki' ) |
86 | ->distinct() |
87 | ->from( 'localuser' ) |
88 | ->where( $conds ) |
89 | ->orderBy( 'lu_wiki', SelectQueryBuilder::SORT_ASC ) |
90 | ->caller( __METHOD__ ) |
91 | ->fetchFieldValues(); |
92 | } |
93 | } |
94 | |
95 | /** |
96 | * @param string $wiki |
97 | * |
98 | * @return Generator |
99 | */ |
100 | protected function getUsers( $wiki ) { |
101 | if ( $this->user !== null ) { |
102 | $this->output( "\t ... querying '$this->user'\n" ); |
103 | yield [ $this->user ]; |
104 | return; |
105 | } |
106 | |
107 | $centralReplica = CentralAuthServices::getDatabaseManager()->getCentralReplicaDB(); |
108 | $lastUsername = ''; |
109 | do { |
110 | $this->output( "\t ... querying from '$lastUsername'\n" ); |
111 | $users = $centralReplica->newSelectQueryBuilder() |
112 | ->select( 'lu_name' ) |
113 | ->from( 'localuser' ) |
114 | ->where( [ |
115 | 'lu_wiki' => $wiki, |
116 | $centralReplica->expr( 'lu_name', '>', $lastUsername ), |
117 | ] ) |
118 | ->orderBy( 'lu_name', SelectQueryBuilder::SORT_ASC ) |
119 | ->limit( $this->getBatchSize() ) |
120 | ->caller( __METHOD__ ) |
121 | ->fetchFieldValues(); |
122 | |
123 | if ( $users ) { |
124 | yield $users; |
125 | $lastUsername = end( $users ); |
126 | } |
127 | } while ( count( $users ) === $this->getBatchSize() ); |
128 | } |
129 | } |
130 | |
131 | $maintClass = CentralAuthDeleteLocalPasswords::class; |
132 | require_once RUN_MAINTENANCE_IF_MAIN; |