Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 43 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
Resource | |
0.00% |
0 / 43 |
|
0.00% |
0 / 10 |
182 | |
0.00% |
0 / 1 |
factory | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
needsReadAccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
needsWriteAccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
doExecuteProtected | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
getProfile | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
getScopes | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
respond | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getParamSettings | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\OAuth\Rest\Handler; |
4 | |
5 | use FormatJson; |
6 | use GuzzleHttp\Psr7\ServerRequest; |
7 | use MediaWiki\Extension\OAuth\Backend\MWOAuthException; |
8 | use MediaWiki\Extension\OAuth\ResourceServer; |
9 | use MediaWiki\Extension\OAuth\Response; |
10 | use MediaWiki\Extension\OAuth\UserStatementProvider; |
11 | use MediaWiki\Rest\Handler; |
12 | use MediaWiki\Rest\HttpException; |
13 | use MWException; |
14 | use Psr\Http\Message\ResponseInterface; |
15 | use Psr\Http\Message\ServerRequestInterface; |
16 | use Wikimedia\ParamValidator\ParamValidator; |
17 | |
18 | /** |
19 | * Handles the oauth2/resource/profile and oauth2/resource/scope endpoints, which return |
20 | * information about the user and the grants of the application, respectively. |
21 | */ |
22 | class Resource extends Handler { |
23 | |
24 | /** |
25 | * (string) TYPE_PROFILE constant to specify the profile type of the resource. |
26 | */ |
27 | private const TYPE_PROFILE = 'profile'; |
28 | |
29 | /** |
30 | * (string) TYPE_SCOPES constant to specify the scopes type of the resource. |
31 | */ |
32 | private const TYPE_SCOPES = 'scopes'; |
33 | |
34 | /** @var ResourceServer */ |
35 | protected $resourceServer; |
36 | |
37 | /** |
38 | * @return static |
39 | */ |
40 | public static function factory() { |
41 | return new static( |
42 | ResourceServer::factory() |
43 | ); |
44 | } |
45 | |
46 | /** |
47 | * @param ResourceServer $resourceServer |
48 | */ |
49 | protected function __construct( $resourceServer ) { |
50 | $this->resourceServer = $resourceServer; |
51 | } |
52 | |
53 | /** |
54 | * All access controls are handled over OAuth2 |
55 | * |
56 | * @return bool |
57 | */ |
58 | public function needsReadAccess() { |
59 | return false; |
60 | } |
61 | |
62 | /** |
63 | * @return bool |
64 | */ |
65 | public function needsWriteAccess() { |
66 | return false; |
67 | } |
68 | |
69 | /** |
70 | * @return ResponseInterface |
71 | */ |
72 | public function execute() { |
73 | $response = new Response(); |
74 | $request = ServerRequest::fromGlobals()->withHeader( |
75 | 'authorization', |
76 | $this->getRequest()->getHeader( 'authorization' ) |
77 | ); |
78 | |
79 | $callback = [ $this, 'doExecuteProtected' ]; |
80 | return $this->resourceServer->verify( $request, $response, $callback ); |
81 | } |
82 | |
83 | /** |
84 | * @param ServerRequestInterface $request |
85 | * @param ResponseInterface $response |
86 | * @throws HttpException |
87 | * @return ResponseInterface |
88 | * @throws MWOAuthException |
89 | */ |
90 | public function doExecuteProtected( $request, $response ) { |
91 | $type = $this->getRequest()->getPathParam( 'type' ); |
92 | |
93 | switch ( $type ) { |
94 | case self::TYPE_PROFILE: |
95 | return $this->getProfile( $response ); |
96 | case self::TYPE_SCOPES: |
97 | return $this->getScopes( $response ); |
98 | } |
99 | |
100 | throw new HttpException( 'Invalid resource type', 400 ); |
101 | } |
102 | |
103 | /** |
104 | * Return appropriate profile info based on approved scopes |
105 | * |
106 | * @param ResponseInterface $response |
107 | * @return ResponseInterface |
108 | * @throws HttpException |
109 | * @throws MWOAuthException |
110 | */ |
111 | private function getProfile( $response ) { |
112 | // Intersection between approved and requested scopes |
113 | $scopes = array_keys( $this->resourceServer->getScopes() ); |
114 | $userStatementProvider = UserStatementProvider::factory( |
115 | $this->resourceServer->getUser(), |
116 | $this->resourceServer->getClient(), |
117 | $scopes |
118 | ); |
119 | |
120 | try { |
121 | $profile = $userStatementProvider->getUserProfile(); |
122 | } catch ( MWException $ex ) { |
123 | throw new HttpException( $ex->getMessage(), $ex->getCode() ); |
124 | } |
125 | |
126 | return $this->respond( $response, $profile ); |
127 | } |
128 | |
129 | /** |
130 | * Get all available scopes client application can use |
131 | * |
132 | * @param ResponseInterface $response |
133 | * @return ResponseInterface |
134 | * @throws MWOAuthException |
135 | */ |
136 | private function getScopes( $response ) { |
137 | $grants = $this->resourceServer->getClient()->getGrants(); |
138 | return $this->respond( $response, [ |
139 | self::TYPE_SCOPES => $grants |
140 | ] ); |
141 | } |
142 | |
143 | /** |
144 | * @param ResponseInterface $response |
145 | * @param array $data |
146 | * @return ResponseInterface |
147 | */ |
148 | private function respond( $response, $data = [] ) { |
149 | $response->getBody()->write( FormatJson::encode( $data ) ); |
150 | return $response; |
151 | } |
152 | |
153 | public function getParamSettings() { |
154 | return [ |
155 | 'type' => [ |
156 | self::PARAM_SOURCE => 'path', |
157 | ParamValidator::PARAM_TYPE => [ self::TYPE_PROFILE, self::TYPE_SCOPES ], |
158 | ParamValidator::PARAM_REQUIRED => true, |
159 | ], |
160 | ]; |
161 | } |
162 | } |