Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 46 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
| Send2FAWarningNotifications | |
0.00% |
0 / 45 |
|
0.00% |
0 / 2 |
156 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| execute | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
132 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace MediaWiki\Extension\WikimediaMessages\Maintenance; |
| 4 | |
| 5 | use MediaWiki\Maintenance\Maintenance; |
| 6 | use MediaWiki\Notification\Notification; |
| 7 | use MediaWiki\Notification\RecipientSet; |
| 8 | use MediaWiki\WikiMap\WikiMap; |
| 9 | |
| 10 | class Send2FAWarningNotifications extends Maintenance { |
| 11 | |
| 12 | public function __construct() { |
| 13 | parent::__construct(); |
| 14 | $this->requireExtension( 'WikimediaMessages' ); |
| 15 | $this->addDescription( 'Send notifications about mandatory 2FA to users (read from stdin)' ); |
| 16 | $this->addOption( 'deadline', 'Deadline for 2FA compliance in YYYYMMDD format', true, true ); |
| 17 | $this->addOption( 'input-file', 'Name of file with users to notify. If absent, use stdin', false, true ); |
| 18 | $this->setBatchSize( 100 ); |
| 19 | } |
| 20 | |
| 21 | public function execute() { |
| 22 | $services = $this->getServiceContainer(); |
| 23 | $userIdentityLookup = $services->getUserIdentityLookup(); |
| 24 | $notifications = $services->getNotificationService(); |
| 25 | |
| 26 | $deadline = $this->getOption( 'deadline' ); |
| 27 | if ( !preg_match( '/^\d{8}$/', $deadline ) ) { |
| 28 | $this->error( "Invalid deadline format, expected YYYYMMDD: $deadline" ); |
| 29 | return; |
| 30 | } |
| 31 | // Notifications expect a timestamp, so append time to the date and convert to timestamp |
| 32 | $deadline .= '000000'; |
| 33 | |
| 34 | if ( $this->hasOption( 'input-file' ) ) { |
| 35 | $fileName = $this->getOption( 'input-file' ); |
| 36 | if ( !file_exists( $fileName ) || !is_readable( $fileName ) ) { |
| 37 | $this->error( "Input file does not exist or is not readable: $fileName" ); |
| 38 | return; |
| 39 | } |
| 40 | $text = file_get_contents( $fileName ); |
| 41 | } else { |
| 42 | $text = $this->getStdin( Maintenance::STDIN_ALL ); |
| 43 | } |
| 44 | $success = 0; |
| 45 | foreach ( explode( "\n", $text ) as $i => $userName ) { |
| 46 | $userName = trim( $userName ); |
| 47 | if ( $userName === '' ) { |
| 48 | continue; |
| 49 | } |
| 50 | if ( str_contains( $userName, '@' ) ) { |
| 51 | [ $userName, $wikiId ] = explode( '@', $userName, 2 ); |
| 52 | $userName = trim( $userName ); |
| 53 | $wikiId = trim( $wikiId ); |
| 54 | if ( !WikiMap::isCurrentWikiId( $wikiId ) ) { |
| 55 | continue; |
| 56 | } |
| 57 | } |
| 58 | $userIdentity = $userIdentityLookup->getUserIdentityByName( $userName ); |
| 59 | if ( !$userIdentity ) { |
| 60 | $this->error( ( $i + 1 ) . ": User is invalid or not registered: $userName" ); |
| 61 | continue; |
| 62 | } |
| 63 | $notifications->notify( |
| 64 | new Notification( '2fa-warning', [ 'deadline' => $deadline ] ), |
| 65 | new RecipientSet( $userIdentity ) |
| 66 | ); |
| 67 | $this->output( ( $i + 1 ) . ": $userName\n" ); |
| 68 | $success++; |
| 69 | if ( $success % $this->getBatchSize() === 0 ) { |
| 70 | $this->waitForReplication(); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | $this->output( "Notified $success users.\n" ); |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | $maintClass = Send2FAWarningNotifications::class; |