26require_once __DIR__ .
'/Maintenance.php';
37 private static $permitRoles = [
'sysop',
'bureaucrat',
'interface-admin',
'bot' ];
40 parent::__construct();
41 $this->
addDescription(
'Create a new user account and/or grant it additional rights' );
44 'If account exists already, just grant it rights or change password.'
46 foreach ( self::$permitRoles as $role ) {
47 $this->
addOption( $role,
"Add the account to the {$role} group" );
52 'Comma-separated list of groups to add the user to',
57 $this->
addArg(
"username",
"Username of new user" );
58 $this->
addArg(
"password",
"Password to set",
false );
62 $username = $this->
getArg( 0 );
63 $password = $this->
getArg( 1 );
66 $services = MediaWikiServices::getInstance();
68 $user = $services->getUserFactory()->newFromName( $username );
69 if ( !is_object( $user ) ) {
73 $exists = ( $user->idForName() !== 0 );
75 if ( $exists && !$force ) {
76 $this->
fatalError(
"Account exists. Perhaps you want the --force option?" );
77 } elseif ( !$exists && !$password ) {
78 $this->
error(
"Argument <password> required!" );
80 } elseif ( $exists ) {
81 $inGroups = $services->getUserGroupManager()->getUserGroups( $user );
84 $groups = array_filter( self::$permitRoles, [ $this,
'hasOption' ] );
85 if ( $this->
hasOption(
'custom-groups' ) ) {
86 $allGroups = array_fill_keys( $services->getUserGroupManager()->listAllGroups(),
true );
87 $customGroupsText = $this->
getOption(
'custom-groups' );
88 if ( $customGroupsText !==
'' ) {
89 $customGroups = explode(
',', $customGroupsText );
90 foreach ( $customGroups as $customGroup ) {
91 if ( isset( $allGroups[$customGroup] ) ) {
92 $groups[] = trim( $customGroup );
94 $this->
output(
"$customGroup is not a valid group, ignoring!\n" );
100 $promotions = array_diff(
105 if ( $exists && !$password && count( $promotions ) === 0 ) {
106 $this->
output(
"Account exists and nothing to do.\n" );
109 } elseif ( count( $promotions ) !== 0 ) {
110 $dbDomain = WikiMap::getCurrentWikiDbDomain()->getId();
111 $promoText =
"User:{$username} into " . implode(
', ', $promotions ) .
"...\n";
113 $this->
output(
"$dbDomain: Promoting $promoText" );
115 $this->
output(
"$dbDomain: Creating and promoting $promoText" );
122 $status = MediaWikiServices::getInstance()->getAuthManager()->autoCreateUser(
124 MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_MAINT,
127 if ( !$status->isGood() ) {
128 $this->
fatalError( $status->getMessage(
false,
false,
'en' )->text() );
133 # Try to set the password
135 $status = $user->changeAuthenticationData( [
136 'username' => $user->getName(),
137 'password' => $password,
138 'retype' => $password,
140 if ( !$status->isGood() ) {
141 throw new PasswordError( $status->getMessage(
false,
false,
'en' )->text() );
144 $this->
output(
"Password set.\n" );
145 $user->saveSettings();
152 $userGroupManager = $services->getUserGroupManager();
154 $userGroupManager->addUserToMultipleGroups( $user, $promotions );
157 # Increment site_stats.ss_users
158 $ssu = SiteStatsUpdate::factory( [
'users' => 1 ] );
162 $this->
output(
"done.\n" );
167require_once RUN_MAINTENANCE_IF_MAIN;
getText()
Format plain text message for the current exception object.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
error( $err, $die=0)
Throw an error to the user.
addArg( $arg, $description, $required=true, $multi=false)
Add some args that are needed.
output( $out, $channel=null)
Throw some output to the user.
hasOption( $name)
Checks to see if a particular option was set.
getArg( $argId=0, $default=null)
Get an argument.
addDescription( $text)
Set the description text.
maybeHelp( $force=false)
Maybe show the help.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Show an error when any operation involving passwords fails to run.