Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
51 / 51 |
|
100.00% |
6 / 6 |
CRAP | |
100.00% |
1 / 1 |
ResetPasswordSecondaryAuthenticationProvider | |
100.00% |
51 / 51 |
|
100.00% |
6 / 6 |
24 | |
100.00% |
1 / 1 |
getAuthenticationRequests | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
beginSecondaryAuthentication | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
continueSecondaryAuthentication | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
beginSecondaryAccountCreation | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
continueSecondaryAccountCreation | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
tryReset | |
100.00% |
46 / 46 |
|
100.00% |
1 / 1 |
19 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | * @ingroup Auth |
20 | */ |
21 | |
22 | namespace MediaWiki\Auth; |
23 | |
24 | use MediaWiki\User\User; |
25 | |
26 | /** |
27 | * Reset the local password, if signalled via $this->manager->setAuthenticationSessionData() |
28 | * |
29 | * The authentication data key is 'reset-pass'; the data is an object with the |
30 | * following properties: |
31 | * - msg: Message object to display to the user |
32 | * - hard: Boolean, if true the reset cannot be skipped. |
33 | * - req: Optional PasswordAuthenticationRequest to use to actually reset the |
34 | * password. Won't be displayed to the user. |
35 | * |
36 | * @ingroup Auth |
37 | * @since 1.27 |
38 | */ |
39 | class ResetPasswordSecondaryAuthenticationProvider extends AbstractSecondaryAuthenticationProvider { |
40 | |
41 | public function getAuthenticationRequests( $action, array $options ) { |
42 | return []; |
43 | } |
44 | |
45 | public function beginSecondaryAuthentication( $user, array $reqs ) { |
46 | return $this->tryReset( $user, $reqs ); |
47 | } |
48 | |
49 | public function continueSecondaryAuthentication( $user, array $reqs ) { |
50 | return $this->tryReset( $user, $reqs ); |
51 | } |
52 | |
53 | public function beginSecondaryAccountCreation( $user, $creator, array $reqs ) { |
54 | return $this->tryReset( $user, $reqs ); |
55 | } |
56 | |
57 | public function continueSecondaryAccountCreation( $user, $creator, array $reqs ) { |
58 | return $this->tryReset( $user, $reqs ); |
59 | } |
60 | |
61 | /** |
62 | * Try to reset the password |
63 | * @param User $user |
64 | * @param AuthenticationRequest[] $reqs |
65 | * @return AuthenticationResponse |
66 | */ |
67 | protected function tryReset( User $user, array $reqs ) { |
68 | $data = $this->manager->getAuthenticationSessionData( 'reset-pass' ); |
69 | if ( !$data ) { |
70 | return AuthenticationResponse::newAbstain(); |
71 | } |
72 | |
73 | if ( is_array( $data ) ) { |
74 | $data = (object)$data; |
75 | } |
76 | if ( !is_object( $data ) ) { |
77 | throw new \UnexpectedValueException( 'reset-pass is not valid' ); |
78 | } |
79 | |
80 | if ( !isset( $data->msg ) ) { |
81 | throw new \UnexpectedValueException( 'reset-pass msg is missing' ); |
82 | } elseif ( !$data->msg instanceof \Message ) { |
83 | throw new \UnexpectedValueException( 'reset-pass msg is not valid' ); |
84 | } elseif ( !isset( $data->hard ) ) { |
85 | throw new \UnexpectedValueException( 'reset-pass hard is missing' ); |
86 | } elseif ( isset( $data->req ) && ( |
87 | !$data->req instanceof PasswordAuthenticationRequest || |
88 | !array_key_exists( 'retype', $data->req->getFieldInfo() ) |
89 | ) ) { |
90 | throw new \UnexpectedValueException( 'reset-pass req is not valid' ); |
91 | } |
92 | |
93 | if ( !$data->hard ) { |
94 | $req = ButtonAuthenticationRequest::getRequestByName( $reqs, 'skipReset' ); |
95 | if ( $req ) { |
96 | $this->manager->removeAuthenticationSessionData( 'reset-pass' ); |
97 | return AuthenticationResponse::newPass(); |
98 | } |
99 | } |
100 | |
101 | /** @var PasswordAuthenticationRequest $needReq */ |
102 | $needReq = $data->req ?? new PasswordAuthenticationRequest(); |
103 | '@phan-var PasswordAuthenticationRequest $needReq'; |
104 | if ( !$needReq->action ) { |
105 | $needReq->action = AuthManager::ACTION_CHANGE; |
106 | } |
107 | $needReq->required = $data->hard ? AuthenticationRequest::REQUIRED |
108 | : AuthenticationRequest::OPTIONAL; |
109 | $needReqs = [ $needReq ]; |
110 | if ( !$data->hard ) { |
111 | $needReqs[] = new ButtonAuthenticationRequest( |
112 | 'skipReset', |
113 | wfMessage( 'authprovider-resetpass-skip-label' ), |
114 | wfMessage( 'authprovider-resetpass-skip-help' ) |
115 | ); |
116 | } |
117 | |
118 | /** @var PasswordAuthenticationRequest $req */ |
119 | $req = AuthenticationRequest::getRequestByClass( $reqs, get_class( $needReq ) ); |
120 | '@phan-var PasswordAuthenticationRequest $req'; |
121 | if ( !$req || !array_key_exists( 'retype', $req->getFieldInfo() ) ) { |
122 | return AuthenticationResponse::newUI( $needReqs, $data->msg, 'warning' ); |
123 | } |
124 | |
125 | if ( $req->password !== $req->retype ) { |
126 | return AuthenticationResponse::newUI( $needReqs, new \Message( 'badretype' ), 'error' ); |
127 | } |
128 | |
129 | $req->username = $user->getName(); |
130 | $status = $this->manager->allowsAuthenticationDataChange( $req ); |
131 | if ( !$status->isGood() ) { |
132 | return AuthenticationResponse::newUI( $needReqs, $status->getMessage(), 'error' ); |
133 | } |
134 | $this->manager->changeAuthenticationData( $req ); |
135 | |
136 | $this->manager->removeAuthenticationSessionData( 'reset-pass' ); |
137 | return AuthenticationResponse::newPass(); |
138 | } |
139 | } |