summaryrefslogtreecommitdiff
blob: 31c7cf5bf65f196d7385aa1a1298ee9b6c934429 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php

use MediaWiki\MediaWikiServices;

$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
	$IP = __DIR__ . '/../../..';
}
require_once "$IP/maintenance/Maintenance.php";

/**
 * Script to migrate disabled accounts to blocked accounts. This will also remove these users
 * from the 'inactive' group. Note that these users will still need sysadmin help to restore
 * their account as their email and password is set to null when the account is disabled.
 */
class BlockDisabledAccounts extends Maintenance {
	public function __construct() {
		parent::__construct();
		$this->addOption( 'reason', 'Block reason', false, true );
		$this->setBatchSize( 10 );

		$this->requireExtension( 'Disable Account' );
	}

	public function execute() {
		$dbr = wfGetDB( DB_REPLICA );
		$inactive = $dbr->selectFieldValues(
			'user_groups',
			'ug_user',
			[
				'ug_group' => 'inactive',
				'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() )
			],
			__METHOD__
		);

		$nulledDetails = $dbr->selectFieldValues(
			'user',
			'user_id',
			[
				'user_password' => '',
				'user_email' => '',
			],
			__METHOD__
		);

		$ids = array_unique( array_merge( $inactive, $nulledDetails ) );

		$disabledCount = count( $ids );
		if ( $disabledCount === 0 ) {
			$this->output( "No users in 'inactive' group, or with a blank password and email.\n" );
			return;
		}

		$counter = 0;
		$success = 0;

		$lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();

		$users = UserArray::newFromIDs( $ids );

		$this->output( "Starting migration...\n" );
		foreach ( $users as $user ) {
			if ( $counter >= $this->mBatchSize ) {
				$counter = 0;
				$lbFactory->waitForReplication();
			}

			$counter++;
			if ( $this->doBlockAndLog( $user ) ) {
				$user->removeGroup( 'inactive' );
				$success++;
			}
		}

		$this->output( "Total $disabledCount users in 'inactive' group, or with " .
			"a blank password and email. Successfully migrated $success users\n" );
	}

	/*
	 * Attempt to block the given user. If user is already blocked, modify
	 * the existing block. If block was successful, insert log entry as well.
	 *
	 * @param User $user
	 *
	 * @return bool true on success, false on failure
	 */
	private function doBlockAndLog( User $user ) {
		$block = $user->getBlock();
		$alreadyBlocked = ( $block !== null );

		if ( $block === null ) {
			$block = new Block();
		}
		$reason = $this->getOption( 'reason', 'Convert disabled account to blocked account' );
		$scriptUser = User::newFromName( 'Maintenance script' );

		$block->setTarget( $user );
		$block->setBlocker( $scriptUser );
		$block->setReason( $reason );
		$block->mExpiry = 'infinity';
		$block->isEmailBlocked( true );
		$block->isUsertalkEditAllowed( false );

		// Try to update block if user is already blocked. Otherwise, attempt to insert a new one.
		$success = $alreadyBlocked ? $block->update() : $block->insert();

		if ( is_array( $success ) ) {
			$logAction = $alreadyBlocked ? 'reblock' : 'block';
			$logParams = [];
			$logParams['5::duration'] = 'infinity';
			$logParams['6::flags'] = 'noemail,nousertalk';

			$logEntry = new ManualLogEntry( 'block', $logAction );
			$logEntry->setTarget( Title::makeTitle( NS_USER, $user->getName() ) );
			$logEntry->setComment( $reason );
			$logEntry->setPerformer( $scriptUser );
			$logEntry->setParameters( $logParams );
			$logEntry->setRelations( [ 'ipb_id' => [ $success['id'] ] ] );
			$logId = $logEntry->insert();
			$logEntry->publish( $logId );
			return true;
		}

		return false;
	}
}

$maintClass = 'BlockDisabledAccounts';
require_once RUN_MAINTENANCE_IF_MAIN;