MediaWiki  master
ApiUserrights.php
Go to the documentation of this file.
1 <?php
2 
29 class ApiUserrights extends ApiBase {
30 
31  private $mUser = null;
32 
37  protected function getUserRightsPage() {
38  return new UserrightsPage;
39  }
40 
45  protected function getAllGroups() {
46  return User::getAllGroups();
47  }
48 
49  public function execute() {
50  $pUser = $this->getUser();
51 
52  // Deny if the user is blocked and doesn't have the full 'userrights' permission.
53  // This matches what Special:UserRights does for the web UI.
54  if ( !$this->getPermissionManager()->userHasRight( $pUser, 'userrights' ) ) {
55  $block = $pUser->getBlock();
56  if ( $block && $block->isSitewide() ) {
57  $this->dieBlocked( $block );
58  }
59  }
60 
61  $params = $this->extractRequestParams();
62 
63  // Figure out expiry times from the input
64  // $params['expiry'] is not set in CentralAuth's ApiGlobalUserRights subclass
65  if ( isset( $params['expiry'] ) ) {
66  $expiry = (array)$params['expiry'];
67  } else {
68  $expiry = [ 'infinity' ];
69  }
70  $add = (array)$params['add'];
71  if ( !$add ) {
72  $expiry = [];
73  } elseif ( count( $expiry ) !== count( $add ) ) {
74  if ( count( $expiry ) === 1 ) {
75  $expiry = array_fill( 0, count( $add ), $expiry[0] );
76  } else {
77  $this->dieWithError( [
78  'apierror-toofewexpiries',
79  count( $expiry ),
80  count( $add )
81  ] );
82  }
83  }
84 
85  // Validate the expiries
86  $groupExpiries = [];
87  foreach ( $expiry as $index => $expiryValue ) {
88  $group = $add[$index];
89  $groupExpiries[$group] = UserrightsPage::expiryToTimestamp( $expiryValue );
90 
91  if ( $groupExpiries[$group] === false ) {
92  $this->dieWithError( [ 'apierror-invalidexpiry', wfEscapeWikiText( $expiryValue ) ] );
93  }
94 
95  // not allowed to have things expiring in the past
96  if ( $groupExpiries[$group] && $groupExpiries[$group] < wfTimestampNow() ) {
97  $this->dieWithError( [ 'apierror-pastexpiry', wfEscapeWikiText( $expiryValue ) ] );
98  }
99  }
100 
101  $user = $this->getUrUser( $params );
102 
103  $tags = $params['tags'];
104 
105  // Check if user can add tags
106  if ( $tags !== null ) {
107  $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $pUser );
108  if ( !$ableToTag->isOK() ) {
109  $this->dieStatus( $ableToTag );
110  }
111  }
112 
113  $form = $this->getUserRightsPage();
114  $form->setContext( $this->getContext() );
115  $r = [];
116  $r['user'] = $user->getName();
117  $r['userid'] = $user->getId();
118  list( $r['added'], $r['removed'] ) = $form->doSaveUserGroups(
119  // Don't pass null to doSaveUserGroups() for array params, cast to empty array
120  $user, (array)$add, (array)$params['remove'],
121  $params['reason'], (array)$tags, $groupExpiries
122  );
123 
124  $result = $this->getResult();
125  ApiResult::setIndexedTagName( $r['added'], 'group' );
126  ApiResult::setIndexedTagName( $r['removed'], 'group' );
127  $result->addValue( null, $this->getModuleName(), $r );
128  }
129 
134  private function getUrUser( array $params ) {
135  if ( $this->mUser !== null ) {
136  return $this->mUser;
137  }
138 
139  $this->requireOnlyOneParameter( $params, 'user', 'userid' );
140 
141  $user = $params['user'] ?? '#' . $params['userid'];
142 
143  $form = $this->getUserRightsPage();
144  $form->setContext( $this->getContext() );
145  $status = $form->fetchUser( $user );
146  if ( !$status->isOK() ) {
147  $this->dieStatus( $status );
148  }
149 
150  $this->mUser = $status->value;
151 
152  return $status->value;
153  }
154 
155  public function mustBePosted() {
156  return true;
157  }
158 
159  public function isWriteMode() {
160  return true;
161  }
162 
163  public function getAllowedParams() {
164  $a = [
165  'user' => [
166  ApiBase::PARAM_TYPE => 'user',
167  ],
168  'userid' => [
169  ApiBase::PARAM_TYPE => 'integer',
170  ],
171  'add' => [
172  ApiBase::PARAM_TYPE => $this->getAllGroups(),
174  ],
175  'expiry' => [
176  ApiBase::PARAM_ISMULTI => true,
178  ApiBase::PARAM_DFLT => 'infinite',
179  ],
180  'remove' => [
181  ApiBase::PARAM_TYPE => $this->getAllGroups(),
183  ],
184  'reason' => [
185  ApiBase::PARAM_DFLT => ''
186  ],
187  'token' => [
188  // Standard definition automatically inserted
189  ApiBase::PARAM_HELP_MSG_APPEND => [ 'api-help-param-token-webui' ],
190  ],
191  'tags' => [
192  ApiBase::PARAM_TYPE => 'tags',
194  ],
195  ];
196  // CentralAuth's ApiGlobalUserRights subclass can't handle expiries
197  if ( !$this->getUserRightsPage()->canProcessExpiries() ) {
198  unset( $a['expiry'] );
199  }
200  return $a;
201  }
202 
203  public function needsToken() {
204  return 'userrights';
205  }
206 
207  protected function getWebUITokenSalt( array $params ) {
208  return $this->getUrUser( $params )->getName();
209  }
210 
211  protected function getExamplesMessages() {
212  $a = [
213  'action=userrights&user=FooBot&add=bot&remove=sysop|bureaucrat&token=123ABC'
214  => 'apihelp-userrights-example-user',
215  'action=userrights&userid=123&add=bot&remove=sysop|bureaucrat&token=123ABC'
216  => 'apihelp-userrights-example-userid',
217  ];
218  if ( $this->getUserRightsPage()->canProcessExpiries() ) {
219  $a['action=userrights&user=SometimeSysop&add=sysop&expiry=1%20month&token=123ABC']
220  = 'apihelp-userrights-example-expiry';
221  }
222  return $a;
223  }
224 
225  public function getHelpUrls() {
226  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:User_group_membership';
227  }
228 }
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking, formatting, etc.
static expiryToTimestamp( $expiry)
Converts a user group membership expiry string into a timestamp.
getResult()
Get the result object.
Definition: ApiBase.php:640
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:2077
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition: ApiBase.php:55
dieBlocked(AbstractBlock $block)
Throw an ApiUsageException, which will (if uncaught) call the main module&#39;s error handler and die wit...
Definition: ApiBase.php:2046
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2005
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
requireOnlyOneParameter( $params,... $required)
Die if none or more than one of a certain set of parameters is set and not false. ...
Definition: ApiBase.php:893
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
static getAllGroups()
Return the set of defined explicit groups.
Definition: User.php:4805
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition: ApiBase.php:138
getAllGroups()
Get all available groups.
getWebUITokenSalt(array $params)
getUrUser(array $params)
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
getContext()
Get the base IContextSource object.
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks...
Definition: ApiBase.php:710
Special page to allow managing user group membership.
This abstract class implements many basic API functions, and is the base of all API classes...
Definition: ApiBase.php:42
static canAddTagsAccompanyingChange(array $tags, User $user=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:521
getUserRightsPage()
Get a UserrightsPage object, or subclass.
return true
Definition: router.php:92
const PARAM_ALLOW_DUPLICATES
(boolean) Allow the same value to be set more than once when PARAM_ISMULTI is true?
Definition: ApiBase.php:109