X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/specials/SpecialChangeCredentials.php diff --git a/includes/specials/SpecialChangeCredentials.php b/includes/specials/SpecialChangeCredentials.php new file mode 100644 index 00000000..970a2e29 --- /dev/null +++ b/includes/specials/SpecialChangeCredentials.php @@ -0,0 +1,267 @@ +loadAuth( '' ); + return (bool)$this->authRequests; + } + + public function doesWrites() { + return true; + } + + protected function getDefaultAction( $subPage ) { + return AuthManager::ACTION_CHANGE; + } + + protected function getPreservedParams( $withToken = false ) { + $request = $this->getRequest(); + $params = parent::getPreservedParams( $withToken ); + $params += [ + 'returnto' => $request->getVal( 'returnto' ), + 'returntoquery' => $request->getVal( 'returntoquery' ), + ]; + return $params; + } + + public function onAuthChangeFormFields( + array $requests, array $fieldInfo, array &$formDescriptor, $action + ) { + // This method is never called for remove actions. + + $extraFields = []; + Hooks::run( 'ChangePasswordForm', [ &$extraFields ], '1.27' ); + foreach ( $extraFields as $extra ) { + list( $name, $label, $type, $default ) = $extra; + $formDescriptor[$name] = [ + 'type' => $type, + 'name' => $name, + 'label-message' => $label, + 'default' => $default, + ]; + + } + + return parent::onAuthChangeFormFields( $requests, $fieldInfo, $formDescriptor, $action ); + } + + public function execute( $subPage ) { + $this->setHeaders(); + $this->outputHeader(); + + $this->loadAuth( $subPage ); + + if ( !$subPage ) { + $this->showSubpageList(); + return; + } + + if ( !$this->authRequests ) { + // messages used: changecredentials-invalidsubpage, removecredentials-invalidsubpage + $this->showSubpageList( $this->msg( static::$messagePrefix . '-invalidsubpage', $subPage ) ); + return; + } + + $this->getOutput()->addBacklinkSubtitle( $this->getPageTitle() ); + + $status = $this->trySubmit(); + + if ( $status === false || !$status->isOK() ) { + $this->displayForm( $status ); + return; + } + + $response = $status->getValue(); + + switch ( $response->status ) { + case AuthenticationResponse::PASS: + $this->success(); + break; + case AuthenticationResponse::FAIL: + $this->displayForm( Status::newFatal( $response->message ) ); + break; + default: + throw new LogicException( 'invalid AuthenticationResponse' ); + } + } + + protected function loadAuth( $subPage, $authAction = null, $reset = false ) { + parent::loadAuth( $subPage, $authAction ); + if ( $subPage ) { + $this->authRequests = array_filter( $this->authRequests, function ( $req ) use ( $subPage ) { + return $req->getUniqueId() === $subPage; + } ); + if ( count( $this->authRequests ) > 1 ) { + throw new LogicException( 'Multiple AuthenticationRequest objects with same ID!' ); + } + } + } + + protected function getAuthFormDescriptor( $requests, $action ) { + if ( !static::$loadUserData ) { + return []; + } else { + $descriptor = parent::getAuthFormDescriptor( $requests, $action ); + + $any = false; + foreach ( $descriptor as &$field ) { + if ( $field['type'] === 'password' && $field['name'] !== 'retype' ) { + $any = true; + if ( isset( $field['cssclass'] ) ) { + $field['cssclass'] .= ' mw-changecredentials-validate-password'; + } else { + $field['cssclass'] = 'mw-changecredentials-validate-password'; + } + } + } + + if ( $any ) { + $this->getOutput()->addModules( [ + 'mediawiki.special.changecredentials.js' + ] ); + } + + return $descriptor; + } + } + + protected function getAuthForm( array $requests, $action ) { + $form = parent::getAuthForm( $requests, $action ); + $req = reset( $requests ); + $info = $req->describeCredentials(); + + $form->addPreText( + Html::openElement( 'dl' ) + . Html::element( 'dt', [], wfMessage( 'credentialsform-provider' )->text() ) + . Html::element( 'dd', [], $info['provider'] ) + . Html::element( 'dt', [], wfMessage( 'credentialsform-account' )->text() ) + . Html::element( 'dd', [], $info['account'] ) + . Html::closeElement( 'dl' ) + ); + + // messages used: changecredentials-submit removecredentials-submit + $form->setSubmitTextMsg( static::$messagePrefix . '-submit' ); + $form->showCancel()->setCancelTarget( $this->getReturnUrl() ?: Title::newMainPage() ); + + return $form; + } + + protected function needsSubmitButton( array $requests ) { + // Change/remove forms show are built from a single AuthenticationRequest and do not allow + // for redirect flow; they always need a submit button. + return true; + } + + public function handleFormSubmit( $data ) { + // remove requests do not accept user input + $requests = $this->authRequests; + if ( static::$loadUserData ) { + $requests = AuthenticationRequest::loadRequestsFromSubmission( $this->authRequests, $data ); + } + + $response = $this->performAuthenticationStep( $this->authAction, $requests ); + + // we can't handle FAIL or similar as failure here since it might require changing the form + return Status::newGood( $response ); + } + + /** + * @param Message|null $error + */ + protected function showSubpageList( $error = null ) { + $out = $this->getOutput(); + + if ( $error ) { + $out->addHTML( $error->parse() ); + } + + $groupedRequests = []; + foreach ( $this->authRequests as $req ) { + $info = $req->describeCredentials(); + $groupedRequests[(string)$info['provider']][] = $req; + } + + $linkRenderer = $this->getLinkRenderer(); + $out->addHTML( Html::openElement( 'dl' ) ); + foreach ( $groupedRequests as $group => $members ) { + $out->addHTML( Html::element( 'dt', [], $group ) ); + foreach ( $members as $req ) { + /** @var AuthenticationRequest $req */ + $info = $req->describeCredentials(); + $out->addHTML( Html::rawElement( 'dd', [], + $linkRenderer->makeLink( + $this->getPageTitle( $req->getUniqueId() ), + $info['account'] + ) + ) ); + } + } + $out->addHTML( Html::closeElement( 'dl' ) ); + } + + protected function success() { + $session = $this->getRequest()->getSession(); + $user = $this->getUser(); + $out = $this->getOutput(); + $returnUrl = $this->getReturnUrl(); + + // change user token and update the session + SessionManager::singleton()->invalidateSessionsForUser( $user ); + $session->setUser( $user ); + $session->resetId(); + + if ( $returnUrl ) { + $out->redirect( $returnUrl ); + } else { + // messages used: changecredentials-success removecredentials-success + $out->wrapWikiMsg( "
\n$1\n
", static::$messagePrefix + . '-success' ); + $out->returnToMain(); + } + } + + /** + * @return string|null + */ + protected function getReturnUrl() { + $request = $this->getRequest(); + $returnTo = $request->getText( 'returnto' ); + $returnToQuery = $request->getText( 'returntoquery', '' ); + + if ( !$returnTo ) { + return null; + } + + $title = Title::newFromText( $returnTo ); + return $title->getFullUrlForRedirect( $returnToQuery ); + } + + protected function getRequestBlacklist() { + return $this->getConfig()->get( 'ChangeCredentialsBlacklist' ); + } +}