Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 93 |
|
0.00% |
0 / 19 |
CRAP | |
0.00% |
0 / 1 |
ConsumerAcceptance | |
0.00% |
0 / 93 |
|
0.00% |
0 / 19 |
992 | |
0.00% |
0 / 1 |
getSchema | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
2 | |||
getFieldPermissionChecks | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
newFromToken | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
12 | |||
newFromUserConsumerWiki | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
12 | |||
getId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getWiki | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getUserId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getConsumerId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAccessToken | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAccessSecret | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getGrants | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAccepted | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getOAuthVersion | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
normalizeValues | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
encodeRow | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
decodeRow | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
userCanSee | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
userCanSeePrivate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
userCanSeeSecret | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\OAuth\Backend; |
4 | |
5 | use FormatJson; |
6 | use IContextSource; |
7 | use IDBAccessObject; |
8 | use MediaWiki\MediaWikiServices; |
9 | use Wikimedia\Rdbms\IDatabase; |
10 | |
11 | /** |
12 | * (c) Aaron Schulz 2013, GPL |
13 | * |
14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or |
17 | * (at your option) any later version. |
18 | * |
19 | * This program is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. |
23 | * |
24 | * You should have received a copy of the GNU General Public License along |
25 | * with this program; if not, write to the Free Software Foundation, Inc., |
26 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
27 | * http://www.gnu.org/copyleft/gpl.html |
28 | */ |
29 | |
30 | /** |
31 | * Representation of an OAuth consumer acceptance. |
32 | * Created when the user clicks through the OAuth authorization dialog, this allows |
33 | * the specified consumer to perform actions in the name of the user |
34 | * (subject to the grant and wiki restrictions stored in the acceptance object). |
35 | */ |
36 | class ConsumerAcceptance extends MWOAuthDAO { |
37 | /** @var int Unique ID */ |
38 | protected $id; |
39 | |
40 | /** @var string Wiki ID the application can be used on (or "*" for all) */ |
41 | protected $wiki; |
42 | |
43 | /** @var int Publisher user ID (on central wiki) */ |
44 | protected $userId; |
45 | |
46 | /** @var int */ |
47 | protected $consumerId; |
48 | |
49 | /** @var string Hex token */ |
50 | protected $accessToken; |
51 | |
52 | /** @var string Secret HMAC key */ |
53 | protected $accessSecret; |
54 | |
55 | /** @var string[] List of grants */ |
56 | protected $grants; |
57 | |
58 | /** @var string TS_MW timestamp of acceptance */ |
59 | protected $accepted; |
60 | |
61 | /** @var string */ |
62 | protected $oauth_version; |
63 | |
64 | protected static function getSchema() { |
65 | return [ |
66 | 'table' => 'oauth_accepted_consumer', |
67 | 'fieldColumnMap' => [ |
68 | 'id' => 'oaac_id', |
69 | 'wiki' => 'oaac_wiki', |
70 | 'userId' => 'oaac_user_id', |
71 | 'consumerId' => 'oaac_consumer_id', |
72 | 'accessToken' => 'oaac_access_token', |
73 | 'accessSecret' => 'oaac_access_secret', |
74 | 'grants' => 'oaac_grants', |
75 | 'accepted' => 'oaac_accepted', |
76 | 'oauth_version' => 'oaac_oauth_version', |
77 | ], |
78 | 'idField' => 'id', |
79 | 'autoIncrField' => 'id', |
80 | ]; |
81 | } |
82 | |
83 | protected static function getFieldPermissionChecks() { |
84 | return [ |
85 | 'wiki' => 'userCanSee', |
86 | 'userId' => 'userCanSee', |
87 | 'consumerId' => 'userCanSee', |
88 | 'accessToken' => 'userCanSeePrivate', |
89 | 'accessSecret' => 'userCanSeeSecret', |
90 | 'grants' => 'userCanSee', |
91 | 'accepted' => 'userCanSee', |
92 | 'oauth_version' => 'userCanSee', |
93 | ]; |
94 | } |
95 | |
96 | /** |
97 | * @param IDatabase $db |
98 | * @param string $token Access token |
99 | * @param int $flags ConsumerAcceptance::READ_* bitfield |
100 | * @return ConsumerAcceptance|bool |
101 | */ |
102 | public static function newFromToken( IDatabase $db, $token, $flags = 0 ) { |
103 | $row = $db->selectRow( static::getTable(), |
104 | array_values( static::getFieldColumnMap() ), |
105 | [ 'oaac_access_token' => (string)$token ], |
106 | __METHOD__, |
107 | ( $flags & IDBAccessObject::READ_LOCKING ) ? [ 'FOR UPDATE' ] : [] |
108 | ); |
109 | |
110 | if ( $row ) { |
111 | $consumer = new self(); |
112 | $consumer->loadFromRow( $db, $row ); |
113 | return $consumer; |
114 | } else { |
115 | return false; |
116 | } |
117 | } |
118 | |
119 | /** |
120 | * @param IDatabase $db |
121 | * @param int $userId of user who authorized (central wiki's id) |
122 | * @param Consumer $consumer |
123 | * @param string $wiki wiki associated with the acceptance |
124 | * @param int $flags ConsumerAcceptance::READ_* bitfield |
125 | * @param int $oauthVersion |
126 | * @return ConsumerAcceptance|bool |
127 | */ |
128 | public static function newFromUserConsumerWiki( |
129 | IDatabase $db, $userId, $consumer, |
130 | $wiki, $flags = 0, $oauthVersion = Consumer::OAUTH_VERSION_1 |
131 | ) { |
132 | $row = $db->selectRow( static::getTable(), |
133 | array_values( static::getFieldColumnMap() ), |
134 | [ |
135 | 'oaac_user_id' => $userId, |
136 | 'oaac_consumer_id' => $consumer->getId(), |
137 | 'oaac_oauth_version' => $oauthVersion, |
138 | 'oaac_wiki' => (string)$wiki |
139 | ], |
140 | __METHOD__, |
141 | ( $flags & IDBAccessObject::READ_LOCKING ) ? [ 'FOR UPDATE' ] : [] |
142 | ); |
143 | |
144 | if ( $row ) { |
145 | $consumer = new self(); |
146 | $consumer->loadFromRow( $db, $row ); |
147 | return $consumer; |
148 | } else { |
149 | return false; |
150 | } |
151 | } |
152 | |
153 | /** |
154 | * Database ID. |
155 | * @return int |
156 | */ |
157 | public function getId() { |
158 | return $this->get( 'id' ); |
159 | } |
160 | |
161 | /** |
162 | * Wiki on which the user has authorized the consumer to access their account. Wiki ID or '*' |
163 | * for all. |
164 | * @return string |
165 | */ |
166 | public function getWiki() { |
167 | return $this->get( 'wiki' ); |
168 | } |
169 | |
170 | /** |
171 | * Central user ID of the authorizing user. |
172 | * @return int |
173 | */ |
174 | public function getUserId() { |
175 | return $this->get( 'userId' ); |
176 | } |
177 | |
178 | /** |
179 | * Database ID of the consumer. |
180 | * @return int |
181 | */ |
182 | public function getConsumerId() { |
183 | return $this->get( 'consumerId' ); |
184 | } |
185 | |
186 | /** |
187 | * The access token for the OAuth protocol |
188 | * @return string |
189 | */ |
190 | public function getAccessToken() { |
191 | return $this->get( 'accessToken' ); |
192 | } |
193 | |
194 | /** |
195 | * Secret key used to derive the access secret for the OAuth protocol. |
196 | * The actual access secret will be calculated via Utils::hmacDBSecret() to mitigate |
197 | * DB leaks. |
198 | * @return string |
199 | */ |
200 | public function getAccessSecret() { |
201 | return $this->get( 'accessSecret' ); |
202 | } |
203 | |
204 | /** |
205 | * The list of grants which have been granted. |
206 | * @return string[] |
207 | */ |
208 | public function getGrants() { |
209 | return $this->get( 'grants' ); |
210 | } |
211 | |
212 | /** |
213 | * Date of the authorization, in TS_MW format. |
214 | * @return string |
215 | */ |
216 | public function getAccepted() { |
217 | return $this->get( 'accepted' ); |
218 | } |
219 | |
220 | /** |
221 | * @return int |
222 | */ |
223 | public function getOAuthVersion() { |
224 | return (int)$this->get( 'oauth_version' ); |
225 | } |
226 | |
227 | protected function normalizeValues() { |
228 | $this->userId = (int)$this->userId; |
229 | $this->consumerId = (int)$this->consumerId; |
230 | $this->accepted = wfTimestamp( TS_MW, $this->accepted ); |
231 | $this->grants = (array)$this->grants; |
232 | } |
233 | |
234 | protected function encodeRow( IDatabase $db, $row ) { |
235 | if ( (int)$row['oaac_user_id'] === 0 ) { |
236 | throw new MWOAuthException( 'mwoauth-consumer-access-no-user', [ |
237 | 'consumer_id' => $row['oaac_consumer_id'], |
238 | ] ); |
239 | } |
240 | // For compatibility with other wikis in the farm, un-remap some grants |
241 | foreach ( Consumer::$mapBackCompatGrants as $old => $new ) { |
242 | while ( ( $i = array_search( $new, $row['oaac_grants'], true ) ) !== false ) { |
243 | $row['oaac_grants'][$i] = $old; |
244 | } |
245 | } |
246 | |
247 | $row['oaac_grants'] = FormatJson::encode( $row['oaac_grants'] ); |
248 | $row['oaac_accepted'] = $db->timestamp( $row['oaac_accepted'] ); |
249 | return $row; |
250 | } |
251 | |
252 | protected function decodeRow( IDatabase $db, $row ) { |
253 | $row['oaac_grants'] = FormatJson::decode( $row['oaac_grants'], true ); |
254 | $row['oaac_accepted'] = wfTimestamp( TS_MW, $row['oaac_accepted'] ); |
255 | |
256 | // For backwards compatibility, remap some grants |
257 | foreach ( Consumer::$mapBackCompatGrants as $old => $new ) { |
258 | while ( ( $i = array_search( $old, $row['oaac_grants'], true ) ) !== false ) { |
259 | $row['oaac_grants'][$i] = $new; |
260 | } |
261 | } |
262 | |
263 | return $row; |
264 | } |
265 | |
266 | protected function userCanSee( $name, IContextSource $context ) { |
267 | $centralUserId = Utils::getCentralIdFromLocalUser( $context->getUser() ); |
268 | $permissionManager = MediaWikiServices::getInstance()->getPermissionManager(); |
269 | |
270 | if ( $this->userId != $centralUserId |
271 | && !$permissionManager->userHasRight( $context->getUser(), 'mwoauthviewprivate' ) |
272 | ) { |
273 | return $context->msg( 'mwoauth-field-private' ); |
274 | } else { |
275 | return true; |
276 | } |
277 | } |
278 | |
279 | protected function userCanSeePrivate( $name, IContextSource $context ) { |
280 | $permissionManager = MediaWikiServices::getInstance()->getPermissionManager(); |
281 | |
282 | if ( !$permissionManager->userHasRight( $context->getUser(), 'mwoauthviewprivate' ) ) { |
283 | return $context->msg( 'mwoauth-field-private' ); |
284 | } else { |
285 | return $this->userCanSee( $name, $context ); |
286 | } |
287 | } |
288 | |
289 | protected function userCanSeeSecret( $name, IContextSource $context ) { |
290 | return $context->msg( 'mwoauth-field-private' ); |
291 | } |
292 | } |