MediaWiki  1.29.2
AuthManagerSpecialPage.php
Go to the documentation of this file.
1 <?php
2 
8 
14 abstract class AuthManagerSpecialPage extends SpecialPage {
17  protected static $allowedActions = [
18  AuthManager::ACTION_LOGIN, AuthManager::ACTION_LOGIN_CONTINUE,
19  AuthManager::ACTION_CREATE, AuthManager::ACTION_CREATE_CONTINUE,
20  AuthManager::ACTION_LINK, AuthManager::ACTION_LINK_CONTINUE,
21  AuthManager::ACTION_CHANGE, AuthManager::ACTION_REMOVE, AuthManager::ACTION_UNLINK,
22  ];
23 
25  protected static $messages = [];
26 
28  protected $authAction;
29 
31  protected $authRequests;
32 
34  protected $subPage;
35 
37  protected $isReturn;
38 
40  protected $savedRequest;
41 
53  public function onAuthChangeFormFields(
54  array $requests, array $fieldInfo, array &$formDescriptor, $action
55  ) {
56  return true;
57  }
58 
59  protected function getLoginSecurityLevel() {
60  return $this->getName();
61  }
62 
63  public function getRequest() {
64  return $this->savedRequest ?: $this->getContext()->getRequest();
65  }
66 
75  protected function setRequest( array $data, $wasPosted = null ) {
76  $request = $this->getContext()->getRequest();
77  if ( $wasPosted === null ) {
78  $wasPosted = $request->wasPosted();
79  }
80  $this->savedRequest = new DerivativeRequest( $request, $data + $request->getQueryValues(),
81  $wasPosted );
82  }
83 
84  protected function beforeExecute( $subPage ) {
85  $this->getOutput()->disallowUserJs();
86 
87  return $this->handleReturnBeforeExecute( $subPage )
89  }
90 
107  protected function handleReturnBeforeExecute( $subPage ) {
108  $authManager = AuthManager::singleton();
109  $key = 'AuthManagerSpecialPage:return:' . $this->getName();
110 
111  if ( $subPage === 'return' ) {
112  $this->loadAuth( $subPage );
113  $preservedParams = $this->getPreservedParams( false );
114 
115  // FIXME save POST values only from request
116  $authData = array_diff_key( $this->getRequest()->getValues(),
117  $preservedParams, [ 'title' => 1 ] );
118  $authManager->setAuthenticationSessionData( $key, $authData );
119 
120  $url = $this->getPageTitle()->getFullURL( $preservedParams, false, PROTO_HTTPS );
121  $this->getOutput()->redirect( $url );
122  return false;
123  }
124 
125  $authData = $authManager->getAuthenticationSessionData( $key );
126  if ( $authData ) {
127  $authManager->removeAuthenticationSessionData( $key );
128  $this->isReturn = true;
129  $this->setRequest( $authData, true );
130  }
131 
132  return true;
133  }
134 
145  protected function handleReauthBeforeExecute( $subPage ) {
146  $authManager = AuthManager::singleton();
147  $request = $this->getRequest();
148  $key = 'AuthManagerSpecialPage:reauth:' . $this->getName();
149 
150  $securityLevel = $this->getLoginSecurityLevel();
151  if ( $securityLevel ) {
152  $securityStatus = AuthManager::singleton()
153  ->securitySensitiveOperationStatus( $securityLevel );
154  if ( $securityStatus === AuthManager::SEC_REAUTH ) {
155  $queryParams = array_diff_key( $request->getQueryValues(), [ 'title' => true ] );
156 
157  if ( $request->wasPosted() ) {
158  // unique ID in case the same special page is open in multiple browser tabs
159  $uniqueId = MWCryptRand::generateHex( 6 );
160  $key = $key . ':' . $uniqueId;
161 
162  $queryParams = [ 'authUniqueId' => $uniqueId ] + $queryParams;
163  $authData = array_diff_key( $request->getValues(),
164  $this->getPreservedParams( false ), [ 'title' => 1 ] );
165  $authManager->setAuthenticationSessionData( $key, $authData );
166  }
167 
168  $title = SpecialPage::getTitleFor( 'Userlogin' );
169  $url = $title->getFullURL( [
170  'returnto' => $this->getFullTitle()->getPrefixedDBkey(),
171  'returntoquery' => wfArrayToCgi( $queryParams ),
172  'force' => $securityLevel,
173  ], false, PROTO_HTTPS );
174 
175  $this->getOutput()->redirect( $url );
176  return false;
177  } elseif ( $securityStatus !== AuthManager::SEC_OK ) {
178  throw new ErrorPageError( 'cannotauth-not-allowed-title', 'cannotauth-not-allowed' );
179  }
180  }
181 
182  $uniqueId = $request->getVal( 'authUniqueId' );
183  if ( $uniqueId ) {
184  $key = $key . ':' . $uniqueId;
185  $authData = $authManager->getAuthenticationSessionData( $key );
186  if ( $authData ) {
187  $authManager->removeAuthenticationSessionData( $key );
188  $this->setRequest( $authData, true );
189  }
190  }
191 
192  return true;
193  }
194 
201  abstract protected function getDefaultAction( $subPage );
202 
209  protected function messageKey( $defaultKey ) {
210  return array_key_exists( $defaultKey, static::$messages )
211  ? static::$messages[$defaultKey] : $defaultKey;
212  }
213 
218  protected function getRequestBlacklist() {
219  return [];
220  }
221 
231  protected function loadAuth( $subPage, $authAction = null, $reset = false ) {
232  // Do not load if already loaded, to cut down on the number of getAuthenticationRequests
233  // calls. This is important for requests which have hidden information so any
234  // getAuthenticationRequests call would mean putting data into some cache.
235  if (
236  !$reset && $this->subPage === $subPage && $this->authAction
237  && ( !$authAction || $authAction === $this->authAction )
238  ) {
239  return;
240  }
241 
242  $request = $this->getRequest();
243  $this->subPage = $subPage;
244  $this->authAction = $authAction ?: $request->getText( 'authAction' );
245  if ( !in_array( $this->authAction, static::$allowedActions, true ) ) {
246  $this->authAction = $this->getDefaultAction( $subPage );
247  if ( $request->wasPosted() ) {
248  $continueAction = $this->getContinueAction( $this->authAction );
249  if ( in_array( $continueAction, static::$allowedActions, true ) ) {
250  $this->authAction = $continueAction;
251  }
252  }
253  }
254 
255  $allReqs = AuthManager::singleton()->getAuthenticationRequests(
256  $this->authAction, $this->getUser() );
257  $this->authRequests = array_filter( $allReqs, function ( $req ) use ( $subPage ) {
258  return !in_array( get_class( $req ), $this->getRequestBlacklist(), true );
259  } );
260  }
261 
266  protected function isContinued() {
267  return in_array( $this->authAction, [
268  AuthManager::ACTION_LOGIN_CONTINUE,
269  AuthManager::ACTION_CREATE_CONTINUE,
270  AuthManager::ACTION_LINK_CONTINUE,
271  ], true );
272  }
273 
279  protected function getContinueAction( $action ) {
280  switch ( $action ) {
281  case AuthManager::ACTION_LOGIN:
282  $action = AuthManager::ACTION_LOGIN_CONTINUE;
283  break;
284  case AuthManager::ACTION_CREATE:
285  $action = AuthManager::ACTION_CREATE_CONTINUE;
286  break;
287  case AuthManager::ACTION_LINK:
288  $action = AuthManager::ACTION_LINK_CONTINUE;
289  break;
290  }
291  return $action;
292  }
293 
302  protected function isActionAllowed( $action ) {
303  $authManager = AuthManager::singleton();
304  if ( !in_array( $action, static::$allowedActions, true ) ) {
305  throw new InvalidArgumentException( 'invalid action: ' . $action );
306  }
307 
308  // calling getAuthenticationRequests can be expensive, avoid if possible
309  $requests = ( $action === $this->authAction ) ? $this->authRequests
310  : $authManager->getAuthenticationRequests( $action );
311  if ( !$requests ) {
312  // no provider supports this action in the current state
313  return false;
314  }
315 
316  switch ( $action ) {
317  case AuthManager::ACTION_LOGIN:
318  case AuthManager::ACTION_LOGIN_CONTINUE:
319  return $authManager->canAuthenticateNow();
320  case AuthManager::ACTION_CREATE:
321  case AuthManager::ACTION_CREATE_CONTINUE:
322  return $authManager->canCreateAccounts();
323  case AuthManager::ACTION_LINK:
324  case AuthManager::ACTION_LINK_CONTINUE:
325  return $authManager->canLinkAccounts();
326  case AuthManager::ACTION_CHANGE:
327  case AuthManager::ACTION_REMOVE:
328  case AuthManager::ACTION_UNLINK:
329  return true;
330  default:
331  // should never reach here but makes static code analyzers happy
332  throw new InvalidArgumentException( 'invalid action: ' . $action );
333  }
334  }
335 
342  protected function performAuthenticationStep( $action, array $requests ) {
343  if ( !in_array( $action, static::$allowedActions, true ) ) {
344  throw new InvalidArgumentException( 'invalid action: ' . $action );
345  }
346 
347  $authManager = AuthManager::singleton();
348  $returnToUrl = $this->getPageTitle( 'return' )
349  ->getFullURL( $this->getPreservedParams( true ), false, PROTO_HTTPS );
350 
351  switch ( $action ) {
352  case AuthManager::ACTION_LOGIN:
353  return $authManager->beginAuthentication( $requests, $returnToUrl );
354  case AuthManager::ACTION_LOGIN_CONTINUE:
355  return $authManager->continueAuthentication( $requests );
356  case AuthManager::ACTION_CREATE:
357  return $authManager->beginAccountCreation( $this->getUser(), $requests,
358  $returnToUrl );
359  case AuthManager::ACTION_CREATE_CONTINUE:
360  return $authManager->continueAccountCreation( $requests );
361  case AuthManager::ACTION_LINK:
362  return $authManager->beginAccountLink( $this->getUser(), $requests, $returnToUrl );
363  case AuthManager::ACTION_LINK_CONTINUE:
364  return $authManager->continueAccountLink( $requests );
365  case AuthManager::ACTION_CHANGE:
366  case AuthManager::ACTION_REMOVE:
367  case AuthManager::ACTION_UNLINK:
368  if ( count( $requests ) > 1 ) {
369  throw new InvalidArgumentException( 'only one auth request can be changed at a time' );
370  } elseif ( !$requests ) {
371  throw new InvalidArgumentException( 'no auth request' );
372  }
373  $req = reset( $requests );
374  $status = $authManager->allowsAuthenticationDataChange( $req );
375  Hooks::run( 'ChangeAuthenticationDataAudit', [ $req, $status ] );
376  if ( !$status->isGood() ) {
377  return AuthenticationResponse::newFail( $status->getMessage() );
378  }
379  $authManager->changeAuthenticationData( $req );
380  return AuthenticationResponse::newPass();
381  default:
382  // should never reach here but makes static code analyzers happy
383  throw new InvalidArgumentException( 'invalid action: ' . $action );
384  }
385  }
386 
397  protected function trySubmit() {
398  $status = false;
399 
400  $form = $this->getAuthForm( $this->authRequests, $this->authAction );
401  $form->setSubmitCallback( [ $this, 'handleFormSubmit' ] );
402 
403  if ( $this->getRequest()->wasPosted() ) {
404  // handle tokens manually; $form->tryAuthorizedSubmit only works for logged-in users
405  $requestTokenValue = $this->getRequest()->getVal( $this->getTokenName() );
406  $sessionToken = $this->getToken();
407  if ( $sessionToken->wasNew() ) {
408  return Status::newFatal( $this->messageKey( 'authform-newtoken' ) );
409  } elseif ( !$requestTokenValue ) {
410  return Status::newFatal( $this->messageKey( 'authform-notoken' ) );
411  } elseif ( !$sessionToken->match( $requestTokenValue ) ) {
412  return Status::newFatal( $this->messageKey( 'authform-wrongtoken' ) );
413  }
414 
415  $form->prepareForm();
416  $status = $form->trySubmit();
417 
418  // HTMLForm submit return values are a mess; let's ensure it is false or a Status
419  // FIXME this probably should be in HTMLForm
420  if ( $status === true ) {
421  // not supposed to happen since our submit handler should always return a Status
422  throw new UnexpectedValueException( 'HTMLForm::trySubmit() returned true' );
423  } elseif ( $status === false ) {
424  // form was not submitted; nothing to do
425  } elseif ( $status instanceof Status ) {
426  // already handled by the form; nothing to do
427  } elseif ( $status instanceof StatusValue ) {
428  // in theory not an allowed return type but nothing stops the submit handler from
429  // accidentally returning it so best check and fix
431  } elseif ( is_string( $status ) ) {
432  $status = Status::newFatal( new RawMessage( '$1', $status ) );
433  } elseif ( is_array( $status ) ) {
434  if ( is_string( reset( $status ) ) ) {
435  $status = call_user_func_array( 'Status::newFatal', $status );
436  } elseif ( is_array( reset( $status ) ) ) {
438  foreach ( $status as $message ) {
439  call_user_func_array( [ $status, 'fatal' ], $message );
440  }
441  } else {
442  throw new UnexpectedValueException( 'invalid HTMLForm::trySubmit() return value: '
443  . 'first element of array is ' . gettype( reset( $status ) ) );
444  }
445  } else {
446  // not supposed to happen but HTMLForm does not actually verify the return type
447  // from the submit callback; better safe then sorry
448  throw new UnexpectedValueException( 'invalid HTMLForm::trySubmit() return type: '
449  . gettype( $status ) );
450  }
451 
452  if ( ( !$status || !$status->isOK() ) && $this->isReturn ) {
453  // This is awkward. There was a form validation error, which means the data was not
454  // passed to AuthManager. Normally we would display the form with an error message,
455  // but for the data we received via the redirect flow that would not be helpful at all.
456  // Let's just submit the data to AuthManager directly instead.
457  LoggerFactory::getInstance( 'authentication' )
458  ->warning( 'Validation error on return', [ 'data' => $form->mFieldData,
459  'status' => $status->getWikiText() ] );
460  $status = $this->handleFormSubmit( $form->mFieldData );
461  }
462  }
463 
464  $changeActions = [
465  AuthManager::ACTION_CHANGE, AuthManager::ACTION_REMOVE, AuthManager::ACTION_UNLINK
466  ];
467  if ( in_array( $this->authAction, $changeActions, true ) && $status && !$status->isOK() ) {
468  Hooks::run( 'ChangeAuthenticationDataAudit', [ reset( $this->authRequests ), $status ] );
469  }
470 
471  return $status;
472  }
473 
480  public function handleFormSubmit( $data ) {
481  $requests = AuthenticationRequest::loadRequestsFromSubmission( $this->authRequests, $data );
482  $response = $this->performAuthenticationStep( $this->authAction, $requests );
483 
484  // we can't handle FAIL or similar as failure here since it might require changing the form
485  return Status::newGood( $response );
486  }
487 
495  protected function getPreservedParams( $withToken = false ) {
496  $params = [];
497  if ( $this->authAction !== $this->getDefaultAction( $this->subPage ) ) {
498  $params['authAction'] = $this->getContinueAction( $this->authAction );
499  }
500  if ( $withToken ) {
501  $params[$this->getTokenName()] = $this->getToken()->toString();
502  }
503  return $params;
504  }
505 
512  protected function getAuthFormDescriptor( $requests, $action ) {
513  $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
514  $formDescriptor = $this->fieldInfoToFormDescriptor( $requests, $fieldInfo, $action );
515 
516  $this->addTabIndex( $formDescriptor );
517 
518  return $formDescriptor;
519  }
520 
526  protected function getAuthForm( array $requests, $action ) {
527  $formDescriptor = $this->getAuthFormDescriptor( $requests, $action );
528  $context = $this->getContext();
529  if ( $context->getRequest() !== $this->getRequest() ) {
530  // We have overridden the request, need to make sure the form uses that too.
531  $context = new DerivativeContext( $this->getContext() );
532  $context->setRequest( $this->getRequest() );
533  }
534  $form = HTMLForm::factory( 'ooui', $formDescriptor, $context );
535  $form->setAction( $this->getFullTitle()->getFullURL( $this->getPreservedParams() ) );
536  $form->addHiddenField( $this->getTokenName(), $this->getToken()->toString() );
537  $form->addHiddenField( 'authAction', $this->authAction );
538  $form->suppressDefaultSubmit( !$this->needsSubmitButton( $requests ) );
539 
540  return $form;
541  }
542 
547  protected function displayForm( $status ) {
548  if ( $status instanceof StatusValue ) {
550  }
551  $form = $this->getAuthForm( $this->authRequests, $this->authAction );
552  $form->prepareForm()->displayForm( $status );
553  }
554 
565  protected function needsSubmitButton( array $requests ) {
566  $customSubmitButtonPresent = false;
567 
568  // Secondary and preauth providers always need their data; they will not care what button
569  // is used, so they can be ignored. So can OPTIONAL buttons createdby primary providers;
570  // that's the point in being optional. Se we need to check whether all primary providers
571  // have their own buttons and whether there is at least one button present.
572  foreach ( $requests as $req ) {
573  if ( $req->required === AuthenticationRequest::PRIMARY_REQUIRED ) {
574  if ( $this->hasOwnSubmitButton( $req ) ) {
575  $customSubmitButtonPresent = true;
576  } else {
577  return true;
578  }
579  }
580  }
581  return !$customSubmitButtonPresent;
582  }
583 
590  foreach ( $req->getFieldInfo() as $field => $info ) {
591  if ( $info['type'] === 'button' ) {
592  return true;
593  }
594  }
595  return false;
596  }
597 
603  protected function addTabIndex( &$formDescriptor ) {
604  $i = 1;
605  foreach ( $formDescriptor as $field => &$definition ) {
606  $class = false;
607  if ( array_key_exists( 'class', $definition ) ) {
608  $class = $definition['class'];
609  } elseif ( array_key_exists( 'type', $definition ) ) {
610  $class = HTMLForm::$typeMappings[$definition['type']];
611  }
612  if ( $class !== 'HTMLInfoField' ) {
613  $definition['tabindex'] = $i;
614  $i++;
615  }
616  }
617  }
618 
623  protected function getToken() {
624  return $this->getRequest()->getSession()->getToken( 'AuthManagerSpecialPage:'
625  . $this->getName() );
626  }
627 
632  protected function getTokenName() {
633  return 'wpAuthToken';
634  }
635 
645  protected function fieldInfoToFormDescriptor( array $requests, array $fieldInfo, $action ) {
646  $formDescriptor = [];
647  foreach ( $fieldInfo as $fieldName => $singleFieldInfo ) {
648  $formDescriptor[$fieldName] = self::mapSingleFieldInfo( $singleFieldInfo, $fieldName );
649  }
650 
651  $requestSnapshot = serialize( $requests );
652  $this->onAuthChangeFormFields( $requests, $fieldInfo, $formDescriptor, $action );
653  \Hooks::run( 'AuthChangeFormFields', [ $requests, $fieldInfo, &$formDescriptor, $action ] );
654  if ( $requestSnapshot !== serialize( $requests ) ) {
655  LoggerFactory::getInstance( 'authentication' )->warning(
656  'AuthChangeFormFields hook changed auth requests' );
657  }
658 
659  // Process the special 'weight' property, which is a way for AuthChangeFormFields hook
660  // subscribers (who only see one field at a time) to influence ordering.
661  self::sortFormDescriptorFields( $formDescriptor );
662 
663  return $formDescriptor;
664  }
665 
673  protected static function mapSingleFieldInfo( $singleFieldInfo, $fieldName ) {
674  $type = self::mapFieldInfoTypeToFormDescriptorType( $singleFieldInfo['type'] );
675  $descriptor = [
676  'type' => $type,
677  // Do not prefix input name with 'wp'. This is important for the redirect flow.
678  'name' => $fieldName,
679  ];
680 
681  if ( $type === 'submit' && isset( $singleFieldInfo['label'] ) ) {
682  $descriptor['default'] = $singleFieldInfo['label']->plain();
683  } elseif ( $type !== 'submit' ) {
684  $descriptor += array_filter( [
685  // help-message is omitted as it is usually not really useful for a web interface
686  'label-message' => self::getField( $singleFieldInfo, 'label' ),
687  ] );
688 
689  if ( isset( $singleFieldInfo['options'] ) ) {
690  $descriptor['options'] = array_flip( array_map( function ( $message ) {
692  return $message->parse();
693  }, $singleFieldInfo['options'] ) );
694  }
695 
696  if ( isset( $singleFieldInfo['value'] ) ) {
697  $descriptor['default'] = $singleFieldInfo['value'];
698  }
699 
700  if ( empty( $singleFieldInfo['optional'] ) ) {
701  $descriptor['required'] = true;
702  }
703  }
704 
705  return $descriptor;
706  }
707 
715  protected static function sortFormDescriptorFields( array &$formDescriptor ) {
716  $i = 0;
717  foreach ( $formDescriptor as &$field ) {
718  $field['__index'] = $i++;
719  }
720  uasort( $formDescriptor, function ( $first, $second ) {
721  return self::getField( $first, 'weight', 0 ) - self::getField( $second, 'weight', 0 )
722  ?: $first['__index'] - $second['__index'];
723  } );
724  foreach ( $formDescriptor as &$field ) {
725  unset( $field['__index'] );
726  }
727  }
728 
736  protected static function getField( array $array, $fieldName, $default = null ) {
737  if ( array_key_exists( $fieldName, $array ) ) {
738  return $array[$fieldName];
739  } else {
740  return $default;
741  }
742  }
743 
750  protected static function mapFieldInfoTypeToFormDescriptorType( $type ) {
751  $map = [
752  'string' => 'text',
753  'password' => 'password',
754  'select' => 'select',
755  'checkbox' => 'check',
756  'multiselect' => 'multiselect',
757  'button' => 'submit',
758  'hidden' => 'hidden',
759  'null' => 'info',
760  ];
761  if ( !array_key_exists( $type, $map ) ) {
762  throw new \LogicException( 'invalid field type: ' . $type );
763  }
764  return $map[$type];
765  }
766 }
AuthManagerSpecialPage\$isReturn
bool $isReturn
True if the current request is a result of returning from a redirect flow.
Definition: AuthManagerSpecialPage.php:37
DerivativeRequest
Similar to FauxRequest, but only fakes URL parameters and method (POST or GET) and use the base reque...
Definition: DerivativeRequest.php:34
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:628
HTMLForm\$typeMappings
static $typeMappings
Definition: HTMLForm.php:130
AuthManagerSpecialPage\displayForm
displayForm( $status)
Display the form.
Definition: AuthManagerSpecialPage.php:547
$context
error also a ContextSource you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
Definition: hooks.txt:2612
StatusValue
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: StatusValue.php:42
$request
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2612
AuthManagerSpecialPage\handleReauthBeforeExecute
handleReauthBeforeExecute( $subPage)
Handle redirection when the user needs to (re)authenticate.
Definition: AuthManagerSpecialPage.php:145
AuthManagerSpecialPage\getTokenName
getTokenName()
Returns the name of the CSRF token (under which it should be found in the POST or GET data).
Definition: AuthManagerSpecialPage.php:632
AuthManagerSpecialPage\addTabIndex
addTabIndex(&$formDescriptor)
Adds a sequential tabindex starting from 1 to all form elements.
Definition: AuthManagerSpecialPage.php:603
AuthManagerSpecialPage\getAuthFormDescriptor
getAuthFormDescriptor( $requests, $action)
Generates a HTMLForm descriptor array from a set of authentication requests.
Definition: AuthManagerSpecialPage.php:512
AuthManagerSpecialPage\onAuthChangeFormFields
onAuthChangeFormFields(array $requests, array $fieldInfo, array &$formDescriptor, $action)
Change the form descriptor that determines how a field will look in the authentication form.
Definition: AuthManagerSpecialPage.php:53
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:675
captcha-old.count
count
Definition: captcha-old.py:225
$status
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition: hooks.txt:1049
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
$req
this hook is for auditing only $req
Definition: hooks.txt:990
AuthManagerSpecialPage\fieldInfoToFormDescriptor
fieldInfoToFormDescriptor(array $requests, array $fieldInfo, $action)
Turns a field info array into a form descriptor.
Definition: AuthManagerSpecialPage.php:645
StatusValue\newFatal
static newFatal( $message)
Factory function for fatal errors.
Definition: StatusValue.php:63
AuthManagerSpecialPage\sortFormDescriptorFields
static sortFormDescriptorFields(array &$formDescriptor)
Sort the fields of a form descriptor by their 'weight' property.
Definition: AuthManagerSpecialPage.php:715
$params
$params
Definition: styleTest.css.php:40
serialize
serialize()
Definition: ApiMessage.php:177
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:82
AuthManagerSpecialPage\handleFormSubmit
handleFormSubmit( $data)
Submit handler callback for HTMLForm.
Definition: AuthManagerSpecialPage.php:480
AuthManagerSpecialPage\getAuthForm
getAuthForm(array $requests, $action)
Definition: AuthManagerSpecialPage.php:526
MWCryptRand\generateHex
static generateHex( $chars, $forceStrong=false)
Generate a run of (ideally) cryptographically random data and return it in hexadecimal string format.
Definition: MWCryptRand.php:76
ContextSource\getRequest
getRequest()
Get the WebRequest object.
Definition: ContextSource.php:78
$type
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
Definition: hooks.txt:2536
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:150
AuthManagerSpecialPage
A special page subclass for authentication-related special pages.
Definition: AuthManagerSpecialPage.php:14
$messages
$messages
Definition: LogTests.i18n.php:8
AuthManagerSpecialPage\$authRequests
AuthenticationRequest[] $authRequests
Definition: AuthManagerSpecialPage.php:31
AuthManagerSpecialPage\getField
static getField(array $array, $fieldName, $default=null)
Get an array value, or a default if it does not exist.
Definition: AuthManagerSpecialPage.php:736
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:40
AuthManagerSpecialPage\trySubmit
trySubmit()
Attempts to do an authentication step with the submitted data.
Definition: AuthManagerSpecialPage.php:397
AuthManagerSpecialPage\getLoginSecurityLevel
getLoginSecurityLevel()
Tells if the special page does something security-sensitive and needs extra defense against a stolen ...
Definition: AuthManagerSpecialPage.php:59
AuthManagerSpecialPage\$subPage
string $subPage
Subpage of the special page.
Definition: AuthManagerSpecialPage.php:34
AuthManagerSpecialPage\performAuthenticationStep
performAuthenticationStep( $action, array $requests)
Definition: AuthManagerSpecialPage.php:342
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:31
AuthManagerSpecialPage\mapFieldInfoTypeToFormDescriptorType
static mapFieldInfoTypeToFormDescriptorType( $type)
Maps AuthenticationRequest::getFieldInfo() types to HTMLForm types.
Definition: AuthManagerSpecialPage.php:750
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:934
AuthManagerSpecialPage\getPreservedParams
getPreservedParams( $withToken=false)
Returns URL query parameters which can be used to reload the page (or leave and return) while preserv...
Definition: AuthManagerSpecialPage.php:495
AuthManagerSpecialPage\messageKey
messageKey( $defaultKey)
Return custom message key.
Definition: AuthManagerSpecialPage.php:209
AuthManagerSpecialPage\$authAction
string $authAction
one of the AuthManager::ACTION_* constants.
Definition: AuthManagerSpecialPage.php:28
Status\wrap
static wrap( $sv)
Succinct helper method to wrap a StatusValue.
Definition: Status.php:55
SpecialPage\getFullTitle
getFullTitle()
Return the full title, including $par.
Definition: SpecialPage.php:724
HTMLForm\factory
static factory( $displayFormat)
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:277
MediaWiki\Auth\AuthenticationResponse
This is a value object to hold authentication response data.
Definition: AuthenticationResponse.php:37
AuthManagerSpecialPage\loadAuth
loadAuth( $subPage, $authAction=null, $reset=false)
Load or initialize $authAction, $authRequests and $subPage.
Definition: AuthManagerSpecialPage.php:231
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:685
AuthManagerSpecialPage\handleReturnBeforeExecute
handleReturnBeforeExecute( $subPage)
Handle redirection from the /return subpage.
Definition: AuthManagerSpecialPage.php:107
PROTO_HTTPS
const PROTO_HTTPS
Definition: Defines.php:218
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:648
AuthManagerSpecialPage\$messages
static array $messages
Customized messages.
Definition: AuthManagerSpecialPage.php:25
AuthManagerSpecialPage\$allowedActions
static string[] $allowedActions
The list of actions this special page deals with.
Definition: AuthManagerSpecialPage.php:17
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:76
SpecialPage
Parent class for all special pages.
Definition: SpecialPage.php:36
AuthManagerSpecialPage\mapSingleFieldInfo
static mapSingleFieldInfo( $singleFieldInfo, $fieldName)
Maps an authentication field configuration for a single field (as returned by AuthenticationRequest::...
Definition: AuthManagerSpecialPage.php:673
AuthManagerSpecialPage\setRequest
setRequest(array $data, $wasPosted=null)
Override the POST data, GET data from the real request is preserved.
Definition: AuthManagerSpecialPage.php:75
AuthManagerSpecialPage\hasOwnSubmitButton
hasOwnSubmitButton(AuthenticationRequest $req)
Checks whether the given AuthenticationRequest has its own submit button.
Definition: AuthManagerSpecialPage.php:589
$response
this hook is for auditing only $response
Definition: hooks.txt:783
AuthManagerSpecialPage\getDefaultAction
getDefaultAction( $subPage)
Get the default action for this special page, if none is given via URL/POST data.
MediaWiki\Auth\AuthManager
This serves as the entry point to the authentication system.
Definition: AuthManager.php:82
AuthManagerSpecialPage\getContinueAction
getContinueAction( $action)
Gets the _CONTINUE version of an action.
Definition: AuthManagerSpecialPage.php:279
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:38
AuthManagerSpecialPage\beforeExecute
beforeExecute( $subPage)
Gets called before.
Definition: AuthManagerSpecialPage.php:84
AuthManagerSpecialPage\isActionAllowed
isActionAllowed( $action)
Checks whether AuthManager is ready to perform the action.
Definition: AuthManagerSpecialPage.php:302
AuthManagerSpecialPage\needsSubmitButton
needsSubmitButton(array $requests)
Returns true if the form built from the given AuthenticationRequests needs a submit button.
Definition: AuthManagerSpecialPage.php:565
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
$requests
Allows to change the fields on the form that will be generated are created Can be used to omit specific feeds from being outputted You must not use this hook to add use OutputPage::addFeedLink() instead. & $feedLinks hooks can tweak the array to change how login etc forms should look $requests
Definition: hooks.txt:306
LoggerFactory
MediaWiki Logger LoggerFactory implements a PSR[0] compatible message logging system Named Psr Log LoggerInterface instances can be obtained from the MediaWiki Logger LoggerFactory::getInstance() static method. MediaWiki\Logger\LoggerFactory expects a class implementing the MediaWiki\Logger\Spi interface to act as a factory for new Psr\Log\LoggerInterface instances. The "Spi" in MediaWiki\Logger\Spi stands for "service provider interface". An SPI is an API intended to be implemented or extended by a third party. This software design pattern is intended to enable framework extension and replaceable components. It is specifically used in the MediaWiki\Logger\LoggerFactory service to allow alternate PSR-3 logging implementations to be easily integrated with MediaWiki. The service provider interface allows the backend logging library to be implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the classname of the default MediaWiki\Logger\Spi implementation to be loaded at runtime. This can either be the name of a class implementing the MediaWiki\Logger\Spi with a zero argument const ructor or a callable that will return an MediaWiki\Logger\Spi instance. Alternately the MediaWiki\Logger\LoggerFactory MediaWiki Logger LoggerFactory
Definition: logger.txt:5
AuthManagerSpecialPage\isContinued
isContinued()
Returns true if this is not the first step of the authentication.
Definition: AuthManagerSpecialPage.php:266
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:1956
AuthManagerSpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: AuthManagerSpecialPage.php:63
AuthManagerSpecialPage\getToken
getToken()
Returns the CSRF token.
Definition: AuthManagerSpecialPage.php:623
AuthManagerSpecialPage\getRequestBlacklist
getRequestBlacklist()
Allows blacklisting certain request types.
Definition: AuthManagerSpecialPage.php:218
MediaWiki\Session\Token
Value object representing a CSRF token.
Definition: Token.php:32
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:27
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
MediaWiki\Auth\AuthenticationRequest
This is a value object for authentication requests.
Definition: AuthenticationRequest.php:37
array
the array() calling protocol came about after MediaWiki 1.4rc1.
AuthManagerSpecialPage\$savedRequest
WebRequest null $savedRequest
If set, will be used instead of the real request.
Definition: AuthManagerSpecialPage.php:40
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:408