*/ require_once __DIR__ . '/Maintenance.php'; class CreateBotPassword extends Maintenance { /** * width of initial column of --showgrants output */ private const SHOWGRANTS_COLUMN_WIDTH = 20; public function __construct() { parent::__construct(); $this->addDescription( 'Create a bot password for a user. ' . 'See https://www.mediawiki.org/wiki/Manual:Bot_passwords for more information.' ); $this->addOption( "showgrants", "Prints a description of available grants and exits." ); $this->addOption( "appid", "App id for the new bot password.", false, true ); $this->addOption( "grants", "CSV list of permissions to grant.", false, true ); $this->addArg( "user", "The username to create a bot password for.", false ); $this->addArg( "password", "A password will be generated if this is omitted." . " If supplied, it must be exactly 32 characters.", false ); } public function execute() { if ( $this->hasOption( 'showgrants' ) ) { $this->showGrants(); exit; } $username = $this->getArg( 0 ); $password = $this->getArg( 1 ); $appId = $this->getOption( 'appid' ); $grants = explode( ',', $this->getOption( 'grants' ) ); $errors = []; if ( $username === null ) { $errors[] = "Argument required!"; } if ( $appId == null ) { $errors[] = "Param appid required!"; } if ( $this->getOption( 'grants' ) === null ) { $errors[] = "Param grants required!"; } if ( count( $errors ) > 0 ) { $this->fatalError( implode( "\n", $errors ) ); } $invalidGrants = array_diff( $grants, MWGrants::getValidGrants() ); if ( count( $invalidGrants ) > 0 ) { $this->fatalError( "These grants are invalid: " . implode( ', ', $invalidGrants ) . "\n" . "Use the --showgrants option for a full list of valid grant names." ); } $passwordFactory = MediaWiki\MediaWikiServices::getInstance()->getPasswordFactory(); $userId = User::idFromName( $username ); if ( $userId === null ) { $this->fatalError( "Cannot create bot password for non-existent user '$username'." ); } if ( $password === null ) { $password = BotPassword::generatePassword( $this->getConfig() ); } else { $passwordLength = strlen( $password ); if ( $passwordLength < BotPassword::PASSWORD_MINLENGTH ) { $message = "Bot passwords must have at least " . BotPassword::PASSWORD_MINLENGTH . " characters. Given password is $passwordLength characters."; $this->fatalError( $message ); } } $bp = BotPassword::newUnsaved( [ 'username' => $username, 'appId' => $appId, 'grants' => $grants ] ); $passwordInstance = $passwordFactory->newFromPlaintext( $password ); $success = $bp->save( 'insert', $passwordInstance ); if ( $success ) { $this->output( "Success.\n" ); $this->output( "Log in using username:'${username}@${appId}' and password:'${password}'.\n" ); } else { $this->fatalError( "Bot password creation failed. Does this appid already exist for the user perhaps?" ); } } public function showGrants() { $permissions = MWGrants::getValidGrants(); sort( $permissions ); $this->output( str_pad( 'GRANT', self::SHOWGRANTS_COLUMN_WIDTH ) . " DESCRIPTION\n" ); foreach ( $permissions as $permission ) { $this->output( str_pad( $permission, self::SHOWGRANTS_COLUMN_WIDTH ) . " " . User::getRightDescription( $permission ) . "\n" ); } } } $maintClass = CreateBotPassword::class; require_once RUN_MAINTENANCE_IF_MAIN;