MediaWiki  master
ApiUserrights.php
Go to the documentation of this file.
1 <?php
2 
30 
34 class ApiUserrights extends ApiBase {
35 
36  private $mUser = null;
37 
39  private $userGroupManager;
40 
46  public function __construct(
47  ApiMain $mainModule,
48  $moduleName,
49  UserGroupManager $userGroupManager
50  ) {
51  parent::__construct( $mainModule, $moduleName );
52  $this->userGroupManager = $userGroupManager;
53  }
54 
55  public function execute() {
56  $pUser = $this->getUser();
57 
58  // Deny if the user is blocked and doesn't have the full 'userrights' permission.
59  // This matches what Special:UserRights does for the web UI.
60  if ( !$this->getAuthority()->isAllowed( 'userrights' ) ) {
61  $block = $pUser->getBlock( Authority::READ_LATEST );
62  if ( $block && $block->isSitewide() ) {
63  $this->dieBlocked( $block );
64  }
65  }
66 
67  $params = $this->extractRequestParams();
68 
69  // Figure out expiry times from the input
70  // $params['expiry'] is not set in CentralAuth's ApiGlobalUserRights subclass
71  if ( isset( $params['expiry'] ) ) {
72  $expiry = (array)$params['expiry'];
73  } else {
74  $expiry = [ 'infinity' ];
75  }
76  $add = (array)$params['add'];
77  if ( !$add ) {
78  $expiry = [];
79  } elseif ( count( $expiry ) !== count( $add ) ) {
80  if ( count( $expiry ) === 1 ) {
81  $expiry = array_fill( 0, count( $add ), $expiry[0] );
82  } else {
83  $this->dieWithError( [
84  'apierror-toofewexpiries',
85  count( $expiry ),
86  count( $add )
87  ] );
88  }
89  }
90 
91  // Validate the expiries
92  $groupExpiries = [];
93  foreach ( $expiry as $index => $expiryValue ) {
94  $group = $add[$index];
95  $groupExpiries[$group] = UserrightsPage::expiryToTimestamp( $expiryValue );
96 
97  if ( $groupExpiries[$group] === false ) {
98  $this->dieWithError( [ 'apierror-invalidexpiry', wfEscapeWikiText( $expiryValue ) ] );
99  }
100 
101  // not allowed to have things expiring in the past
102  if ( $groupExpiries[$group] && $groupExpiries[$group] < wfTimestampNow() ) {
103  $this->dieWithError( [ 'apierror-pastexpiry', wfEscapeWikiText( $expiryValue ) ] );
104  }
105  }
106 
107  $user = $this->getUrUser( $params );
108 
109  $tags = $params['tags'];
110 
111  // Check if user can add tags
112  if ( $tags !== null ) {
113  $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $this->getAuthority() );
114  if ( !$ableToTag->isOK() ) {
115  $this->dieStatus( $ableToTag );
116  }
117  }
118 
119  $form = new UserrightsPage();
120  $form->setContext( $this->getContext() );
121  $r = [];
122  $r['user'] = $user->getName();
123  $r['userid'] = $user->getId();
124  list( $r['added'], $r['removed'] ) = $form->doSaveUserGroups(
125  // Don't pass null to doSaveUserGroups() for array params, cast to empty array
126  $user, $add, (array)$params['remove'],
127  $params['reason'], (array)$tags, $groupExpiries
128  );
129 
130  $result = $this->getResult();
131  ApiResult::setIndexedTagName( $r['added'], 'group' );
132  ApiResult::setIndexedTagName( $r['removed'], 'group' );
133  $result->addValue( null, $this->getModuleName(), $r );
134  }
135 
140  private function getUrUser( array $params ) {
141  if ( $this->mUser !== null ) {
142  return $this->mUser;
143  }
144 
145  $this->requireOnlyOneParameter( $params, 'user', 'userid' );
146 
147  $user = $params['user'] ?? '#' . $params['userid'];
148 
149  $form = new UserrightsPage();
150  $form->setContext( $this->getContext() );
151  $status = $form->fetchUser( $user );
152  if ( !$status->isOK() ) {
153  $this->dieStatus( $status );
154  }
155 
156  $this->mUser = $status->value;
157 
158  return $status->value;
159  }
160 
161  public function mustBePosted() {
162  return true;
163  }
164 
165  public function isWriteMode() {
166  return true;
167  }
168 
169  public function getAllowedParams( $flags = 0 ) {
170  $allGroups = $this->userGroupManager->listAllGroups();
171 
172  if ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
173  sort( $allGroups );
174  }
175 
176  return [
177  'user' => [
178  ParamValidator::PARAM_TYPE => 'user',
179  UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'id' ],
180  ],
181  'userid' => [
182  ParamValidator::PARAM_TYPE => 'integer',
183  ParamValidator::PARAM_DEPRECATED => true,
184  ],
185  'add' => [
186  ParamValidator::PARAM_TYPE => $allGroups,
187  ParamValidator::PARAM_ISMULTI => true
188  ],
189  'expiry' => [
190  ParamValidator::PARAM_ISMULTI => true,
191  ParamValidator::PARAM_ALLOW_DUPLICATES => true,
192  ParamValidator::PARAM_DEFAULT => 'infinite',
193  ],
194  'remove' => [
195  ParamValidator::PARAM_TYPE => $allGroups,
196  ParamValidator::PARAM_ISMULTI => true
197  ],
198  'reason' => [
199  ParamValidator::PARAM_DEFAULT => ''
200  ],
201  'token' => [
202  // Standard definition automatically inserted
203  ApiBase::PARAM_HELP_MSG_APPEND => [ 'api-help-param-token-webui' ],
204  ],
205  'tags' => [
206  ParamValidator::PARAM_TYPE => 'tags',
207  ParamValidator::PARAM_ISMULTI => true
208  ],
209  ];
210  }
211 
212  public function needsToken() {
213  return 'userrights';
214  }
215 
216  protected function getWebUITokenSalt( array $params ) {
217  return $this->getUrUser( $params )->getName();
218  }
219 
220  protected function getExamplesMessages() {
221  return [
222  'action=userrights&user=FooBot&add=bot&remove=sysop|bureaucrat&token=123ABC'
223  => 'apihelp-userrights-example-user',
224  'action=userrights&userid=123&add=bot&remove=sysop|bureaucrat&token=123ABC'
225  => 'apihelp-userrights-example-userid',
226  'action=userrights&user=SometimeSysop&add=sysop&expiry=1%20month&token=123ABC'
227  => 'apihelp-userrights-example-expiry',
228  ];
229  }
230 
231  public function getHelpUrls() {
232  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:User_group_membership';
233  }
234 }
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:56
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition: ApiBase.php:1453
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition: ApiBase.php:170
requireOnlyOneParameter( $params,... $required)
Die if none or more than one of a certain set of parameters is set and not false.
Definition: ApiBase.php:903
getResult()
Get the result object.
Definition: ApiBase.php:629
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:765
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition: ApiBase.php:234
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:498
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:1516
dieBlocked(Block $block)
Throw an ApiUsageException, which will (if uncaught) call the main module's error handler and die wit...
Definition: ApiBase.php:1483
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:52
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:604
getHelpUrls()
Return links to more detailed help pages about the module.
getAllowedParams( $flags=0)
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
mustBePosted()
Indicates whether this module must be called with a POST request.
needsToken()
Returns the token type this module requires in order to execute.
isWriteMode()
Indicates whether this module requires write mode.
__construct(ApiMain $mainModule, $moduleName, UserGroupManager $userGroupManager)
getExamplesMessages()
Returns usage examples for this module.
getWebUITokenSalt(array $params)
Fetch the salt used in the Web UI corresponding to this module.
static canAddTagsAccompanyingChange(array $tags, Authority $performer=null, $checkBlock=true)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Definition: ChangeTags.php:635
getContext()
Get the base IContextSource object.
Special page to allow managing user group membership.
static expiryToTimestamp( $expiry)
Converts a user group membership expiry string into a timestamp.
Service for formatting and validating API parameters.
This interface represents the authority associated the current execution context, such as a web reque...
Definition: Authority.php:37
return true
Definition: router.php:90