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