MediaWiki  master
createBotPassword.php
Go to the documentation of this file.
1 <?php
27 
28 require_once __DIR__ . '/Maintenance.php';
29 
34  private const SHOWGRANTS_COLUMN_WIDTH = 20;
35 
36  public function __construct() {
37  parent::__construct();
38  $this->addDescription(
39  'Create a bot password for a user. ' .
40  'See https://www.mediawiki.org/wiki/Manual:Bot_passwords for more information.'
41  );
42 
43  $this->addOption( "showgrants",
44  "Prints a description of available grants and exits."
45  );
46  $this->addOption( "appid",
47  "App id for the new bot password.", false, true
48  );
49  $this->addOption( "grants",
50  "CSV list of permissions to grant.", false, true
51  );
52  $this->addArg( "user",
53  "The username to create a bot password for.", false
54  );
55  $this->addArg( "password",
56  "A password will be generated if this is omitted." .
57  " If supplied, it must be exactly 32 characters.", false
58  );
59  }
60 
61  public function execute() {
62  if ( $this->hasOption( 'showgrants' ) ) {
63  $this->showGrants();
64  return;
65  }
66 
67  $username = $this->getArg( 0 );
68  $password = $this->getArg( 1 );
69  $appId = $this->getOption( 'appid' );
70  $grants = explode( ',', $this->getOption( 'grants' ) );
71 
72  $errors = [];
73  if ( $username === null ) {
74  $errors[] = "Argument <user> required!";
75  }
76  if ( $appId == null ) {
77  $errors[] = "Param appid required!";
78  }
79  if ( $this->getOption( 'grants' ) === null ) {
80  $errors[] = "Param grants required!";
81  }
82  if ( count( $errors ) > 0 ) {
83  $this->fatalError( implode( "\n", $errors ) );
84  }
85 
86  $services = $this->getServiceContainer();
87  $grantsInfo = $services->getGrantsInfo();
88  $invalidGrants = array_diff( $grants, $grantsInfo->getValidGrants() );
89  if ( count( $invalidGrants ) > 0 ) {
90  $this->fatalError(
91  "These grants are invalid: " . implode( ', ', $invalidGrants ) . "\n" .
92  "Use the --showgrants option for a full list of valid grant names."
93  );
94  }
95 
96  $passwordFactory = $services->getPasswordFactory();
97 
98  $userIdentity = $services->getUserIdentityLookup()->getUserIdentityByName( $username );
99  if ( !$userIdentity || !$userIdentity->isRegistered() ) {
100  $this->fatalError( "Cannot create bot password for non-existent user '$username'." );
101  }
102 
103  if ( $password === null ) {
104  $password = BotPassword::generatePassword( $this->getConfig() );
105  } else {
106  $passwordLength = strlen( $password );
107  if ( $passwordLength < BotPassword::PASSWORD_MINLENGTH ) {
108  $message = "Bot passwords must have at least " . BotPassword::PASSWORD_MINLENGTH .
109  " characters. Given password is $passwordLength characters.";
110  $this->fatalError( $message );
111  }
112  }
113 
114  $bp = BotPassword::newUnsaved( [
115  'username' => $username,
116  'appId' => $appId,
117  'grants' => $grants
118  ] );
119 
120  if ( $bp === null ) {
121  $this->fatalError( "Bot password creation failed." );
122  }
123 
124  $passwordInstance = $passwordFactory->newFromPlaintext( $password );
125  $status = $bp->save( 'insert', $passwordInstance );
126 
127  if ( $status->isGood() ) {
128  $this->output( "Success.\n" );
129  $this->output( "Log in using username:'{$username}@{$appId}' and password:'{$password}'.\n" );
130  } else {
131  $this->fatalError(
132  "Bot password creation failed. Does this appid already exist for the user perhaps?\n\nErrors:\n" .
133  print_r( $status->getErrors(), true )
134  );
135  }
136  }
137 
138  public function showGrants() {
139  $permissions = $this->getServiceContainer()->getGrantsInfo()->getValidGrants();
140  sort( $permissions );
141 
142  $this->output( str_pad( 'GRANT', self::SHOWGRANTS_COLUMN_WIDTH ) . " DESCRIPTION\n" );
143  foreach ( $permissions as $permission ) {
144  $this->output(
145  str_pad( $permission, self::SHOWGRANTS_COLUMN_WIDTH ) . " " .
146  User::getRightDescription( $permission ) . "\n"
147  );
148  }
149  }
150 }
151 
152 $maintClass = CreateBotPassword::class;
153 require_once RUN_MAINTENANCE_IF_MAIN;
__construct()
Default constructor.
execute()
Do the actual work.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:66
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.
getServiceContainer()
Returns the main service container.
getArg( $argId=0, $default=null)
Get an argument.
addDescription( $text)
Set the description text.
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.
Utility class for bot passwords.
Definition: BotPassword.php:50
internal since 1.36
Definition: User.php:98