Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 131 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
UIHooks | |
0.00% |
0 / 131 |
|
0.00% |
0 / 8 |
552 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onGetPreferences | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
12 | |||
onMessagesPreLoad | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
30 | |||
onSpecialPageAfterExecute | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
30 | |||
onSpecialPageBeforeFormDisplay | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
onBeforeCreateEchoEvent | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
12 | |||
onSpecialPage_initList | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
6 | |||
onLoginFormValidErrorMessages | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\OAuth\Frontend; |
4 | |
5 | use MediaWiki\Cache\Hook\MessagesPreLoadHook; |
6 | use MediaWiki\Context\DerivativeContext; |
7 | use MediaWiki\Context\RequestContext; |
8 | use MediaWiki\Extension\OAuth\Backend\Consumer; |
9 | use MediaWiki\Extension\OAuth\Backend\Utils; |
10 | use MediaWiki\Extension\OAuth\Control\ConsumerAccessControl; |
11 | use MediaWiki\Extension\OAuth\Control\ConsumerSubmitControl; |
12 | use MediaWiki\Extension\OAuth\Frontend\SpecialPages\SpecialMWOAuthConsumerRegistration; |
13 | use MediaWiki\Extension\OAuth\Frontend\SpecialPages\SpecialMWOAuthManageConsumers; |
14 | use MediaWiki\Hook\LoginFormValidErrorMessagesHook; |
15 | use MediaWiki\Html\Html; |
16 | use MediaWiki\HTMLForm\HTMLForm; |
17 | use MediaWiki\Parser\Sanitizer; |
18 | use MediaWiki\Permissions\PermissionManager; |
19 | use MediaWiki\Preferences\Hook\GetPreferencesHook; |
20 | use MediaWiki\SpecialPage\Hook\SpecialPage_initListHook; |
21 | use MediaWiki\SpecialPage\Hook\SpecialPageAfterExecuteHook; |
22 | use MediaWiki\SpecialPage\Hook\SpecialPageBeforeFormDisplayHook; |
23 | use MediaWiki\SpecialPage\SpecialPage; |
24 | use MediaWiki\User\User; |
25 | use MediaWiki\WikiMap\WikiMap; |
26 | use MWException; |
27 | use OOUI\ButtonWidget; |
28 | |
29 | /** |
30 | * Class containing GUI even handler functions for an OAuth environment |
31 | * |
32 | * @phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName |
33 | */ |
34 | class UIHooks implements |
35 | GetPreferencesHook, |
36 | LoginFormValidErrorMessagesHook, |
37 | MessagesPreLoadHook, |
38 | SpecialPageAfterExecuteHook, |
39 | SpecialPageBeforeFormDisplayHook, |
40 | SpecialPage_initListHook |
41 | { |
42 | |
43 | /** @var PermissionManager */ |
44 | private $permissionManager; |
45 | |
46 | /** |
47 | * @param PermissionManager $permissionManager |
48 | */ |
49 | public function __construct( PermissionManager $permissionManager ) { |
50 | $this->permissionManager = $permissionManager; |
51 | } |
52 | |
53 | /** |
54 | * @param User $user |
55 | * @param array &$preferences |
56 | * @return bool |
57 | * @throws MWException |
58 | */ |
59 | public function onGetPreferences( $user, &$preferences ) { |
60 | $dbr = Utils::getCentralDB( DB_REPLICA ); |
61 | $conds = [ |
62 | 'oaac_user_id' => Utils::getCentralIdFromLocalUser( $user ), |
63 | ]; |
64 | |
65 | if ( !$this->permissionManager->userHasRight( $user, 'mwoauthviewsuppressed' ) ) { |
66 | $conds['oarc_deleted'] = 0; |
67 | } |
68 | $count = $dbr->newSelectQueryBuilder() |
69 | ->select( 'COUNT(*)' ) |
70 | ->from( 'oauth_accepted_consumer' ) |
71 | ->join( 'oauth_registered_consumer', null, 'oaac_consumer_id = oarc_id' ) |
72 | ->where( $conds ) |
73 | ->caller( __METHOD__ ) |
74 | ->fetchField(); |
75 | |
76 | $control = new ButtonWidget( [ |
77 | 'href' => SpecialPage::getTitleFor( 'OAuthManageMyGrants' )->getLinkURL(), |
78 | 'label' => wfMessage( 'mwoauth-prefs-managegrantslink' )->numParams( $count )->text() |
79 | ] ); |
80 | |
81 | $prefInsert = [ 'mwoauth-prefs-managegrants' => |
82 | [ |
83 | 'section' => 'personal/info', |
84 | 'label-message' => 'mwoauth-prefs-managegrants', |
85 | 'type' => 'info', |
86 | 'raw' => true, |
87 | 'default' => (string)$control |
88 | ], |
89 | ]; |
90 | |
91 | if ( array_key_exists( 'usergroups', $preferences ) ) { |
92 | $preferences = wfArrayInsertAfter( $preferences, $prefInsert, 'usergroups' ); |
93 | } else { |
94 | $preferences += $prefInsert; |
95 | } |
96 | |
97 | return true; |
98 | } |
99 | |
100 | /** |
101 | * Override MediaWiki namespace for a message |
102 | * @param string $title Message name (no prefix) |
103 | * @param string &$message Message wikitext |
104 | * @param string $code Language code |
105 | * @return bool false if we replaced $message |
106 | */ |
107 | public function onMessagesPreLoad( $title, &$message, $code ) { |
108 | // Quick fail check |
109 | if ( substr( $title, 0, 15 ) !== 'Tag-OAuth_CID:_' ) { |
110 | return true; |
111 | } |
112 | |
113 | // More expensive check |
114 | if ( !preg_match( '!^Tag-OAuth_CID:_(\d+)((?:-description)?)(?:/|$)!', $title, $m ) ) { |
115 | return true; |
116 | } |
117 | |
118 | // Put the correct language in the context, so that later uses of $context->msg() will use it |
119 | $context = new DerivativeContext( RequestContext::getMain() ); |
120 | $context->setLanguage( $code ); |
121 | |
122 | $dbr = Utils::getCentralDB( DB_REPLICA ); |
123 | $cmrAc = ConsumerAccessControl::wrap( |
124 | Consumer::newFromId( $dbr, (int)$m[1] ), |
125 | $context |
126 | ); |
127 | if ( !$cmrAc ) { |
128 | // Invalid consumer, skip it |
129 | return true; |
130 | } |
131 | |
132 | if ( $m[2] ) { |
133 | $message = $cmrAc->escapeForWikitext( $cmrAc->getDescription() ); |
134 | } else { |
135 | $target = SpecialPage::getTitleFor( 'OAuthListConsumers', |
136 | 'view/' . $cmrAc->getConsumerKey() |
137 | ); |
138 | $encName = $cmrAc->escapeForWikitext( $cmrAc->getNameAndVersion() ); |
139 | $message = "[[$target|$encName]]"; |
140 | } |
141 | return false; |
142 | } |
143 | |
144 | /** |
145 | * Append OAuth-specific grants to Special:ListGrants |
146 | * @param SpecialPage $special |
147 | * @param string $par |
148 | * @return bool |
149 | */ |
150 | public function onSpecialPageAfterExecute( $special, $par ) { |
151 | if ( $special->getName() !== 'Listgrants' ) { |
152 | return true; |
153 | } |
154 | |
155 | $out = $special->getOutput(); |
156 | |
157 | $out->addWikiMsg( 'mwoauth-listgrants-extra-summary' ); |
158 | |
159 | $out->addHTML( |
160 | Html::openElement( 'table', |
161 | [ 'class' => 'wikitable mw-listgrouprights-table' ] ) . |
162 | '<tr>' . |
163 | Html::element( 'th', [], $special->msg( 'listgrants-grant' )->text() ) . |
164 | Html::element( 'th', [], $special->msg( 'listgrants-rights' )->text() ) . |
165 | '</tr>' |
166 | ); |
167 | |
168 | $grants = [ |
169 | 'mwoauth-authonly' => [], |
170 | 'mwoauth-authonlyprivate' => [], |
171 | ]; |
172 | |
173 | foreach ( $grants as $grant => $rights ) { |
174 | $descs = []; |
175 | $rights = array_filter( $rights ); |
176 | foreach ( $rights as $permission => $granted ) { |
177 | $descs[] = $special->msg( |
178 | 'listgrouprights-right-display', |
179 | User::getRightDescription( $permission ), |
180 | '<span class="mw-listgrants-right-name">' . $permission . '</span>' |
181 | )->parse(); |
182 | } |
183 | if ( !count( $descs ) ) { |
184 | $grantCellHtml = ''; |
185 | } else { |
186 | sort( $descs ); |
187 | $grantCellHtml = '<ul><li>' . implode( "</li>\n<li>", $descs ) . '</li></ul>'; |
188 | } |
189 | |
190 | $id = Sanitizer::escapeIdForAttribute( $grant ); |
191 | $out->addHTML( Html::rawElement( 'tr', [ 'id' => $id ], |
192 | "<td>" . $special->msg( "grant-$grant" )->escaped() . "</td>" . |
193 | "<td>" . $grantCellHtml . '</td>' |
194 | ) ); |
195 | } |
196 | |
197 | $out->addHTML( Html::closeElement( 'table' ) ); |
198 | |
199 | return true; |
200 | } |
201 | |
202 | /** |
203 | * Add additional text to Special:BotPasswords |
204 | * @param string $name Special page name |
205 | * @param HTMLForm $form |
206 | * @return bool |
207 | */ |
208 | public function onSpecialPageBeforeFormDisplay( $name, $form ) { |
209 | global $wgMWOAuthCentralWiki; |
210 | |
211 | if ( $name === 'BotPasswords' ) { |
212 | if ( Utils::isCentralWiki() ) { |
213 | $url = SpecialPage::getTitleFor( 'OAuthConsumerRegistration' )->getFullURL(); |
214 | } else { |
215 | $url = WikiMap::getForeignURL( |
216 | $wgMWOAuthCentralWiki, |
217 | // Cross-wiki, so don't localize |
218 | 'Special:OAuthConsumerRegistration' |
219 | ); |
220 | } |
221 | $form->addPreHtml( $form->msg( 'mwoauth-botpasswords-note', $url )->parseAsBlock() ); |
222 | } |
223 | return true; |
224 | } |
225 | |
226 | /** |
227 | * @param array &$notifications |
228 | * @param array &$notificationCategories |
229 | * @param array &$icons |
230 | */ |
231 | public static function onBeforeCreateEchoEvent( |
232 | &$notifications, &$notificationCategories, &$icons |
233 | ) { |
234 | global $wgOAuthGroupsToNotify; |
235 | |
236 | if ( !Utils::isCentralWiki() ) { |
237 | return; |
238 | } |
239 | |
240 | $notificationCategories['oauth-owner'] = [ |
241 | 'tooltip' => 'echo-pref-tooltip-oauth-owner', |
242 | ]; |
243 | $notificationCategories['oauth-admin'] = [ |
244 | 'tooltip' => 'echo-pref-tooltip-oauth-admin', |
245 | 'usergroups' => $wgOAuthGroupsToNotify, |
246 | ]; |
247 | |
248 | foreach ( ConsumerSubmitControl::$actions as $eventName ) { |
249 | // oauth-app-propose and oauth-app-update notifies admins of the app. |
250 | // oauth-app-approve, oauth-app-reject, oauth-app-disable and oauth-app-reenable |
251 | // notify owner of the change. |
252 | $notifications["oauth-app-$eventName"] = |
253 | EchoOAuthStageChangePresentationModel::getDefinition( $eventName ); |
254 | } |
255 | |
256 | $icons['oauth'] = [ 'path' => 'OAuth/resources/assets/echo-icon.png' ]; |
257 | } |
258 | |
259 | /** |
260 | * @param array &$specialPages |
261 | */ |
262 | public function onSpecialPage_initList( &$specialPages ) { |
263 | if ( Utils::isCentralWiki() ) { |
264 | $specialPages['OAuthConsumerRegistration'] = [ |
265 | 'class' => SpecialMWOAuthConsumerRegistration::class, |
266 | 'services' => [ |
267 | 'PermissionManager', |
268 | 'GrantsInfo', |
269 | 'GrantsLocalization', |
270 | ], |
271 | ]; |
272 | $specialPages['OAuthManageConsumers'] = [ |
273 | 'class' => SpecialMWOAuthManageConsumers::class, |
274 | 'services' => [ |
275 | 'GrantsLocalization', |
276 | ], |
277 | ]; |
278 | } |
279 | } |
280 | |
281 | /** |
282 | * Show help text when a user is redirected to provider login page |
283 | * @param array &$messages |
284 | * @return bool |
285 | */ |
286 | public function onLoginFormValidErrorMessages( &$messages ) { |
287 | $messages = array_merge( $messages, [ |
288 | 'mwoauth-named-account-required-reason', |
289 | 'mwoauth-named-account-required-reason-for-temp-user', |
290 | 'mwoauth-available-only-to-registered', |
291 | ] ); |
292 | return true; |
293 | } |
294 | } |