MediaWiki REL1_34
SpecialChangeCredentials.php
Go to the documentation of this file.
1<?php
2
7
14 protected static $allowedActions = [ AuthManager::ACTION_CHANGE ];
15
16 protected static $messagePrefix = 'changecredentials';
17
19 protected static $loadUserData = true;
20
21 public function __construct( $name = 'ChangeCredentials' ) {
22 parent::__construct( $name, 'editmyprivateinfo' );
23 }
24
25 protected function getGroupName() {
26 return 'users';
27 }
28
29 public function isListed() {
30 $this->loadAuth( '' );
31 return (bool)$this->authRequests;
32 }
33
34 public function doesWrites() {
35 return true;
36 }
37
38 protected function getDefaultAction( $subPage ) {
39 return AuthManager::ACTION_CHANGE;
40 }
41
42 protected function getPreservedParams( $withToken = false ) {
43 $request = $this->getRequest();
44 $params = parent::getPreservedParams( $withToken );
45 $params += [
46 'returnto' => $request->getVal( 'returnto' ),
47 'returntoquery' => $request->getVal( 'returntoquery' ),
48 ];
49 return $params;
50 }
51
52 public function execute( $subPage ) {
53 $this->setHeaders();
54 $this->outputHeader();
55
56 $this->loadAuth( $subPage );
57
58 if ( !$subPage ) {
59 $this->showSubpageList();
60 return;
61 }
62
63 if ( !$this->authRequests ) {
64 // messages used: changecredentials-invalidsubpage, removecredentials-invalidsubpage
65 $this->showSubpageList( $this->msg( static::$messagePrefix . '-invalidsubpage', $subPage ) );
66 return;
67 }
68
69 $this->getOutput()->addBacklinkSubtitle( $this->getPageTitle() );
70
71 $status = $this->trySubmit();
72
73 if ( $status === false || !$status->isOK() ) {
74 $this->displayForm( $status );
75 return;
76 }
77
78 $response = $status->getValue();
79
80 switch ( $response->status ) {
81 case AuthenticationResponse::PASS:
82 $this->success();
83 break;
84 case AuthenticationResponse::FAIL:
85 $this->displayForm( Status::newFatal( $response->message ) );
86 break;
87 default:
88 throw new LogicException( 'invalid AuthenticationResponse' );
89 }
90 }
91
92 protected function loadAuth( $subPage, $authAction = null, $reset = false ) {
93 parent::loadAuth( $subPage, $authAction );
94 if ( $subPage ) {
95 $this->authRequests = array_filter( $this->authRequests, function ( $req ) use ( $subPage ) {
96 return $req->getUniqueId() === $subPage;
97 } );
98 if ( count( $this->authRequests ) > 1 ) {
99 throw new LogicException( 'Multiple AuthenticationRequest objects with same ID!' );
100 }
101 }
102 }
103
104 protected function getAuthFormDescriptor( $requests, $action ) {
105 if ( !static::$loadUserData ) {
106 return [];
107 } else {
108 $descriptor = parent::getAuthFormDescriptor( $requests, $action );
109
110 $any = false;
111 foreach ( $descriptor as &$field ) {
112 if ( $field['type'] === 'password' && $field['name'] !== 'retype' ) {
113 $any = true;
114 if ( isset( $field['cssclass'] ) ) {
115 $field['cssclass'] .= ' mw-changecredentials-validate-password';
116 } else {
117 $field['cssclass'] = 'mw-changecredentials-validate-password';
118 }
119 }
120 }
121
122 if ( $any ) {
123 $this->getOutput()->addModules( 'mediawiki.misc-authed-ooui' );
124 }
125
126 return $descriptor;
127 }
128 }
129
130 protected function getAuthForm( array $requests, $action ) {
131 $form = parent::getAuthForm( $requests, $action );
132 $req = reset( $requests );
133 $info = $req->describeCredentials();
134
135 $form->addPreText(
136 Html::openElement( 'dl' )
137 . Html::element( 'dt', [], $this->msg( 'credentialsform-provider' )->text() )
138 . Html::element( 'dd', [], $info['provider'] )
139 . Html::element( 'dt', [], $this->msg( 'credentialsform-account' )->text() )
140 . Html::element( 'dd', [], $info['account'] )
141 . Html::closeElement( 'dl' )
142 );
143
144 // messages used: changecredentials-submit removecredentials-submit
145 $form->setSubmitTextMsg( static::$messagePrefix . '-submit' );
146 $form->showCancel()->setCancelTarget( $this->getReturnUrl() ?: Title::newMainPage() );
147
148 return $form;
149 }
150
151 protected function needsSubmitButton( array $requests ) {
152 // Change/remove forms show are built from a single AuthenticationRequest and do not allow
153 // for redirect flow; they always need a submit button.
154 return true;
155 }
156
157 public function handleFormSubmit( $data ) {
158 // remove requests do not accept user input
159 $requests = $this->authRequests;
160 if ( static::$loadUserData ) {
161 $requests = AuthenticationRequest::loadRequestsFromSubmission( $this->authRequests, $data );
162 }
163
164 $response = $this->performAuthenticationStep( $this->authAction, $requests );
165
166 // we can't handle FAIL or similar as failure here since it might require changing the form
167 return Status::newGood( $response );
168 }
169
173 protected function showSubpageList( $error = null ) {
174 $out = $this->getOutput();
175
176 if ( $error ) {
177 $out->addHTML( $error->parse() );
178 }
179
180 $groupedRequests = [];
181 foreach ( $this->authRequests as $req ) {
182 $info = $req->describeCredentials();
183 $groupedRequests[(string)$info['provider']][] = $req;
184 }
185
187 $out->addHTML( Html::openElement( 'dl' ) );
188 foreach ( $groupedRequests as $group => $members ) {
189 $out->addHTML( Html::element( 'dt', [], $group ) );
190 foreach ( $members as $req ) {
192 $info = $req->describeCredentials();
193 $out->addHTML( Html::rawElement( 'dd', [],
194 $linkRenderer->makeLink(
195 $this->getPageTitle( $req->getUniqueId() ),
196 $info['account']
197 )
198 ) );
199 }
200 }
201 $out->addHTML( Html::closeElement( 'dl' ) );
202 }
203
204 protected function success() {
205 $session = $this->getRequest()->getSession();
206 $user = $this->getUser();
207 $out = $this->getOutput();
208 $returnUrl = $this->getReturnUrl();
209
210 // change user token and update the session
211 SessionManager::singleton()->invalidateSessionsForUser( $user );
212 $session->setUser( $user );
213 $session->resetId();
214
215 if ( $returnUrl ) {
216 $out->redirect( $returnUrl );
217 } else {
218 // messages used: changecredentials-success removecredentials-success
219 $out->wrapWikiMsg( "<div class=\"successbox\">\n$1\n</div>", static::$messagePrefix
220 . '-success' );
221 $out->returnToMain();
222 }
223 }
224
228 protected function getReturnUrl() {
229 $request = $this->getRequest();
230 $returnTo = $request->getText( 'returnto' );
231 $returnToQuery = $request->getText( 'returntoquery', '' );
232
233 if ( !$returnTo ) {
234 return null;
235 }
236
237 $title = Title::newFromText( $returnTo );
238 return $title->getFullUrlForRedirect( $returnToQuery );
239 }
240
241 protected function getRequestBlacklist() {
242 return $this->getConfig()->get( 'ChangeCredentialsBlacklist' );
243 }
244}
A special page subclass for authentication-related special pages.
string $authAction
one of the AuthManager::ACTION_* constants.
performAuthenticationStep( $action, array $requests)
displayForm( $status)
Display the form.
AuthenticationRequest[] $authRequests
string $subPage
Subpage of the special page.
getRequest()
Get the WebRequest being used for this instance.
trySubmit()
Attempts to do an authentication step with the submitted data.
This serves as the entry point to the authentication system.
This is a value object for authentication requests.
describeCredentials()
Describe the credentials represented by this request.
This is a value object to hold authentication response data.
This serves as the entry point to the MediaWiki session handling system.
Special change to change credentials (such as the password).
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getAuthForm(array $requests, $action)
doesWrites()
Indicates whether this special page may perform database writes.
handleFormSubmit( $data)
Submit handler callback for HTMLForm.
getPreservedParams( $withToken=false)
Returns URL query parameters which can be used to reload the page (or leave and return) while preserv...
isListed()
Whether this special page is listed in Special:SpecialPages.
getRequestBlacklist()
Allows blacklisting certain request types.
getAuthFormDescriptor( $requests, $action)
Generates a HTMLForm descriptor array from a set of authentication requests.
loadAuth( $subPage, $authAction=null, $reset=false)
Load or initialize $authAction, $authRequests and $subPage.
__construct( $name='ChangeCredentials')
getDefaultAction( $subPage)
Get the default action for this special page, if none is given via URL/POST data.
needsSubmitButton(array $requests)
Returns true if the form built from the given AuthenticationRequests needs a submit button.
static $loadUserData
Change action needs user data; remove action does not.
execute( $subPage)
Default execute method Checks user permissions.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getPageTitle( $subpage=false)
Get a self-referential title object.
MediaWiki Linker LinkRenderer null $linkRenderer