MediaWiki master
ApiUnblock.php
Go to the documentation of this file.
1<?php
9namespace MediaWiki\Api;
10
23use RuntimeException;
26
33class ApiUnblock extends ApiBase {
34
37
38 private BlockPermissionCheckerFactory $permissionCheckerFactory;
39 private UnblockUserFactory $unblockUserFactory;
40 private UserIdentityLookup $userIdentityLookup;
41 private WatchedItemStoreInterface $watchedItemStore;
42 private DatabaseBlockStore $blockStore;
43 private BlockTargetFactory $blockTargetFactory;
44
45 public function __construct(
46 ApiMain $main,
47 string $action,
48 BlockPermissionCheckerFactory $permissionCheckerFactory,
49 UnblockUserFactory $unblockUserFactory,
50 UserIdentityLookup $userIdentityLookup,
51 WatchedItemStoreInterface $watchedItemStore,
52 WatchlistManager $watchlistManager,
53 UserOptionsLookup $userOptionsLookup,
54 DatabaseBlockStore $blockStore,
55 BlockTargetFactory $blockTargetFactory
56 ) {
57 parent::__construct( $main, $action );
58
59 $this->permissionCheckerFactory = $permissionCheckerFactory;
60 $this->unblockUserFactory = $unblockUserFactory;
61 $this->userIdentityLookup = $userIdentityLookup;
62 $this->watchedItemStore = $watchedItemStore;
63
64 // Variables needed in ApiWatchlistTrait trait
65 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
66 $this->watchlistMaxDuration =
68 $this->watchlistManager = $watchlistManager;
69 $this->userOptionsLookup = $userOptionsLookup;
70 $this->blockStore = $blockStore;
71 $this->blockTargetFactory = $blockTargetFactory;
72 }
73
77 public function execute() {
78 $performer = $this->getUser();
79 $params = $this->extractRequestParams();
80
81 $this->requireOnlyOneParameter( $params, 'id', 'user', 'userid' );
82
83 if ( !$this->getAuthority()->isAllowed( 'block' ) ) {
84 $this->dieWithError( 'apierror-permissiondenied-unblock', 'permissiondenied' );
85 }
86
87 if ( $params['userid'] !== null ) {
88 $identity = $this->userIdentityLookup->getUserIdentityByUserId( $params['userid'] );
89 if ( !$identity ) {
90 $this->dieWithError( [ 'apierror-nosuchuserid', $params['userid'] ], 'nosuchuserid' );
91 }
92 $params['user'] = $identity;
93 }
94
95 $blockToRemove = null;
96 if ( $params['id'] !== null ) {
97 $blockToRemove = $this->blockStore->newFromID( $params['id'], true );
98 if ( !$blockToRemove ) {
99 $this->dieWithError(
100 [ 'apierror-nosuchblockid', $params['id'] ],
101 'nosuchblockid' );
102 }
103 $target = $blockToRemove->getRedactedTarget();
104 if ( !$target ) {
105 throw new RuntimeException( 'Block has no target' );
106 }
107 } else {
108 $target = $this->blockTargetFactory->newFromUser( $params['user'] );
109 }
110
111 # T17810: blocked admins should have limited access here
112 $status = $this->permissionCheckerFactory
113 ->newChecker(
114 $this->getAuthority()
115 )->checkBlockPermissions( $target );
116
117 if ( $status !== true ) {
118 $this->dieWithError(
119 $status,
120 null,
121 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable Block is checked and not null
122 [ 'blockinfo' => $this->getBlockDetails( $performer->getBlock() ) ]
123 );
124 }
125
126 if ( $blockToRemove !== null ) {
127 $status = $this->unblockUserFactory->newRemoveBlock(
128 $blockToRemove,
129 $this->getAuthority(),
130 $params['reason'],
131 $params['tags'] ?? []
132 )->unblock();
133 } else {
134 $status = $this->unblockUserFactory->newUnblockUser(
135 $target,
136 $this->getAuthority(),
137 $params['reason'],
138 $params['tags'] ?? []
139 )->unblock();
140 }
141
142 if ( !$status->isOK() ) {
143 $this->dieStatus( $status );
144 }
145
146 $block = $status->getValue();
147 $targetType = $block->getType();
148 $targetName = $targetType === Block::TYPE_AUTO ? '' : $block->getTargetName();
149 $targetUserId = $block->getTargetUserIdentity() ? $block->getTargetUserIdentity()->getId() : 0;
150
151 $userPage = Title::makeTitle( NS_USER, $targetName );
152 $watchlistExpiry = $this->getExpiryFromParams( $params, $userPage, $this->getUser() );
153 $watchuser = $params['watchuser'];
154 if ( $watchuser && $targetType !== Block::TYPE_RANGE && $targetType !== Block::TYPE_AUTO ) {
155 $this->setWatch( 'watch', $userPage, $this->getUser(), null, $watchlistExpiry );
156 } else {
157 $watchuser = false;
158 $watchlistExpiry = null;
159 }
160
161 $res = [
162 'id' => $block->getId(),
163 'user' => $targetName,
164 'userid' => $targetUserId,
165 'reason' => $params['reason'],
166 'watchuser' => $watchuser,
167 ];
168
169 if ( $watchlistExpiry !== null ) {
170 $res['watchlistexpiry'] = $this->getWatchlistExpiry(
171 $this->watchedItemStore,
172 $userPage,
173 $this->getUser()
174 );
175 }
176
177 $this->getResult()->addValue( null, $this->getModuleName(), $res );
178 }
179
181 public function mustBePosted() {
182 return true;
183 }
184
186 public function isWriteMode() {
187 return true;
188 }
189
191 public function getAllowedParams() {
192 $params = [
193 'id' => [
194 ParamValidator::PARAM_TYPE => 'integer',
195 ],
196 'user' => [
197 ParamValidator::PARAM_TYPE => 'user',
198 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'cidr', 'id' ],
199 UserDef::PARAM_RETURN_OBJECT => true,
200 ],
201 'userid' => [
202 ParamValidator::PARAM_TYPE => 'integer',
203 ParamValidator::PARAM_DEPRECATED => true,
204 ],
205 'reason' => '',
206 'tags' => [
207 ParamValidator::PARAM_TYPE => 'tags',
208 ParamValidator::PARAM_ISMULTI => true,
209 ],
210 'watchuser' => false,
211 ];
212
213 // Params appear in the docs in the order they are defined,
214 // which is why this is here and not at the bottom.
215 // @todo Find better way to support insertion at arbitrary position
216 if ( $this->watchlistExpiryEnabled ) {
217 $params += [
218 'watchlistexpiry' => [
219 ParamValidator::PARAM_TYPE => 'expiry',
220 ExpiryDef::PARAM_MAX => $this->watchlistMaxDuration,
221 ExpiryDef::PARAM_USE_MAX => true,
222 ]
223 ];
224 }
225
226 return $params;
227 }
228
230 public function needsToken() {
231 return 'csrf';
232 }
233
235 protected function getExamplesMessages() {
236 return [
237 'action=unblock&id=105'
238 => 'apihelp-unblock-example-id',
239 'action=unblock&user=Bob&reason=Sorry%20Bob'
240 => 'apihelp-unblock-example-user',
241 ];
242 }
243
245 public function getHelpUrls() {
246 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Block';
247 }
248}
249
251class_alias( ApiUnblock::class, 'ApiUnblock' );
const NS_USER
Definition Defines.php:53
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:61
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1511
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:543
getResult()
Get the result object.
Definition ApiBase.php:682
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition ApiBase.php:1562
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:823
requireOnlyOneParameter( $params,... $required)
Die if 0 or more than one of a certain set of parameters is set and not false.
Definition ApiBase.php:961
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:65
API module that facilitates the unblocking of users.
mustBePosted()
Indicates whether this module must be called with a POST request.Implementations of this method must ...
needsToken()
Returns the token type this module requires in order to execute.Modules are strongly encouraged to us...
execute()
Unblocks the specified user or provides the reason the unblock failed.
isWriteMode()
Indicates whether this module requires write access to the wiki.API modules must override this method...
__construct(ApiMain $main, string $action, BlockPermissionCheckerFactory $permissionCheckerFactory, UnblockUserFactory $unblockUserFactory, UserIdentityLookup $userIdentityLookup, WatchedItemStoreInterface $watchedItemStore, WatchlistManager $watchlistManager, UserOptionsLookup $userOptionsLookup, DatabaseBlockStore $blockStore, BlockTargetFactory $blockTargetFactory)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getHelpUrls()
Return links to more detailed help pages about the module.1.25, returning boolean false is deprecated...
getExamplesMessages()
Returns usage examples for this module.Return value has query strings as keys, with values being eith...
Factory for BlockTarget objects.
makeTitle( $linkId)
Convert a link ID to a Title.to override Title
A class containing constants representing the names of configuration variables.
const WatchlistExpiry
Name constant for the WatchlistExpiry setting, for use with Config::get()
const WatchlistExpiryMaxDuration
Name constant for the WatchlistExpiryMaxDuration setting, for use with Config::get()
Type definition for user types.
Definition UserDef.php:27
Represents a title within MediaWiki.
Definition Title.php:69
Provides access to user options.
Service for formatting and validating API parameters.
Type definition for expiry timestamps.
Definition ExpiryDef.php:18
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Represents a block that may prevent users from performing specific operations.
Definition Block.php:31
Service for looking up UserIdentity.
setWatch(string $watch, PageIdentity $page, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
getExpiryFromParams(array $params, ?PageIdentity $page=null, ?UserIdentity $user=null, string $userOption='watchdefault-expiry')
Get formatted expiry from the given parameters.
getWatchlistExpiry(WatchedItemStoreInterface $store, PageIdentity $page, UserIdentity $user)
Get existing expiry from the database.