PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 13.5.2
Jetpack – WP Security, Backup, Speed, & Growth v13.5.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / core-api / wpcom-endpoints / service-api-keys.php
jetpack / _inc / lib / core-api / wpcom-endpoints Last commit date
business-hours.php 4 years ago class-wpcom-rest-api-v2-endpoint-admin-color.php 2 years ago class-wpcom-rest-api-v2-endpoint-admin-menu.php 2 years ago class-wpcom-rest-api-v2-endpoint-ai.php 2 years ago class-wpcom-rest-api-v2-endpoint-app-media.php 2 years ago class-wpcom-rest-api-v2-endpoint-blog-stats.php 2 years ago class-wpcom-rest-api-v2-endpoint-external-media.php 2 years ago class-wpcom-rest-api-v2-endpoint-following.php 2 years ago class-wpcom-rest-api-v2-endpoint-goodreads.php 2 years ago class-wpcom-rest-api-v2-endpoint-google-docs.php 4 years ago class-wpcom-rest-api-v2-endpoint-instagram-gallery.php 3 years ago class-wpcom-rest-api-v2-endpoint-mailchimp.php 3 years ago class-wpcom-rest-api-v2-endpoint-newsletter-categories-list.php 2 years ago class-wpcom-rest-api-v2-endpoint-newsletter-categories-subscriptions-count.php 2 years ago class-wpcom-rest-api-v2-endpoint-podcast-player.php 2 years ago class-wpcom-rest-api-v2-endpoint-publicize-share-post.php 3 years ago class-wpcom-rest-api-v2-endpoint-related-posts.php 2 years ago class-wpcom-rest-api-v2-endpoint-resolve-redirect.php 2 years ago class-wpcom-rest-api-v2-endpoint-search.php 4 years ago class-wpcom-rest-api-v2-endpoint-send-email-preview.php 2 years ago class-wpcom-rest-api-v2-endpoint-template-loader.php 3 years ago class-wpcom-rest-api-v2-endpoint-top-posts.php 2 years ago class-wpcom-rest-api-v2-endpoint-transient.php 5 years ago class-wpcom-rest-api-v3-endpoint-blogging-prompts.php 2 years ago gutenberg-available-extensions.php 2 years ago hello.php 4 years ago memberships.php 2 years ago publicize-connection-test-results.php 3 years ago publicize-connections.php 2 years ago publicize-services.php 3 years ago service-api-keys.php 2 years ago sites-posts-featured-media-url.php 2 years ago subscribers.php 3 years ago trait-wpcom-rest-api-proxy-request-trait.php 2 years ago
service-api-keys.php
336 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Get and save API keys for a site.
4 *
5 * @package automattic/jetpack
6 */
7
8 /**
9 * Service API Keys: Exposes 3rd party api keys that are used on a site.
10 *
11 * [
12 * { # Availability Object. See schema for more detail.
13 * code: (string) Displays success if the operation was successfully executed and an error code if it was not
14 * service: (string) The name of the service in question
15 * service_api_key: (string) The API key used by the service empty if one is not set yet
16 * service_api_key_source: (string) The source of the API key, defaults to "site"
17 * message: (string) User friendly message
18 * },
19 * ...
20 * ]
21 *
22 * @since 6.9
23 */
24 class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
25
26 /**
27 * Constructor.
28 */
29 public function __construct() {
30 $this->namespace = 'wpcom/v2';
31 $this->rest_base = 'service-api-keys';
32
33 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
34 }
35
36 /**
37 * Register endpoint routes.
38 */
39 public function register_routes() {
40 register_rest_route(
41 'wpcom/v2',
42 '/service-api-keys/(?P<service>[a-z\-_]+)',
43 array(
44 array(
45 'methods' => WP_REST_Server::READABLE,
46 'callback' => array( __CLASS__, 'get_service_api_key' ),
47 'permission_callback' => '__return_true',
48 ),
49 array(
50 'methods' => WP_REST_Server::EDITABLE,
51 'callback' => array( __CLASS__, 'update_service_api_key' ),
52 'permission_callback' => array( __CLASS__, 'edit_others_posts_check' ),
53 'args' => array(
54 'service_api_key' => array(
55 'required' => true,
56 'type' => 'string',
57 ),
58 ),
59 ),
60 array(
61 'methods' => WP_REST_Server::DELETABLE,
62 'callback' => array( __CLASS__, 'delete_service_api_key' ),
63 'permission_callback' => array( __CLASS__, 'edit_others_posts_check' ),
64 ),
65 )
66 );
67 }
68
69 /**
70 * Permission check.
71 */
72 public static function edit_others_posts_check() {
73 if ( current_user_can( 'edit_others_posts' ) ) {
74 return true;
75 }
76
77 $user_permissions_error_msg = esc_html__(
78 'You do not have the correct user permissions to perform this action.
79 Please contact your site admin if you think this is a mistake.',
80 'jetpack'
81 );
82
83 return new WP_Error( 'invalid_user_permission_edit_others_posts', $user_permissions_error_msg, rest_authorization_required_code() );
84 }
85
86 /**
87 * Return the available Gutenberg extensions schema
88 *
89 * @return array Service API Key schema
90 */
91 public function get_public_item_schema() {
92 $schema = array(
93 '$schema' => 'http://json-schema.org/draft-04/schema#',
94 'title' => 'service-api-keys',
95 'type' => 'object',
96 'properties' => array(
97 'code' => array(
98 'description' => __( 'Displays success if the operation was successfully executed and an error code if it was not', 'jetpack' ),
99 'type' => 'string',
100 ),
101 'service' => array(
102 'description' => __( 'The name of the service in question', 'jetpack' ),
103 'type' => 'string',
104 ),
105 'service_api_key' => array(
106 'description' => __( 'The API key used by the service. Empty if none has been set yet', 'jetpack' ),
107 'type' => 'string',
108 ),
109 'service_api_key_source' => array(
110 'description' => __( 'The source of the API key. Defaults to "site"', 'jetpack' ),
111 'type' => 'string',
112 ),
113 'message' => array(
114 'description' => __( 'User friendly message', 'jetpack' ),
115 'type' => 'string',
116 ),
117 ),
118 );
119
120 return $this->add_additional_fields_schema( $schema );
121 }
122
123 /**
124 * Get third party plugin API keys.
125 *
126 * @param WP_REST_Request $request {
127 * Array of parameters received by request.
128 *
129 * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'.
130 * }
131 */
132 public static function get_service_api_key( $request ) {
133 $service = self::validate_service_api_service( $request['service'] );
134 if ( ! $service ) {
135 return self::service_api_invalid_service_response();
136 }
137
138 switch ( $service ) {
139 case 'mapbox':
140 if ( ! class_exists( 'Jetpack_Mapbox_Helper' ) ) {
141 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-mapbox-helper.php';
142 }
143 $mapbox = Jetpack_Mapbox_Helper::get_access_token();
144 $service_api_key = $mapbox['key'];
145 $service_api_key_source = $mapbox['source'];
146 break;
147 default:
148 $option = self::key_for_api_service( $service );
149 $service_api_key = Jetpack_Options::get_option( $option, '' );
150 $service_api_key_source = 'site';
151 }
152
153 $message = esc_html__( 'API key retrieved successfully.', 'jetpack' );
154
155 return array(
156 'code' => 'success',
157 'service' => $service,
158 'service_api_key' => $service_api_key,
159 'service_api_key_source' => $service_api_key_source,
160 'message' => $message,
161 );
162 }
163
164 /**
165 * Update third party plugin API keys.
166 *
167 * @param WP_REST_Request $request {
168 * Array of parameters received by request.
169 *
170 * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'.
171 * }
172 */
173 public static function update_service_api_key( $request ) {
174 $service = self::validate_service_api_service( $request['service'] );
175 if ( ! $service ) {
176 return self::service_api_invalid_service_response();
177 }
178 $json_params = $request->get_json_params();
179 $params = ! empty( $json_params ) ? $json_params : $request->get_body_params();
180 $service_api_key = trim( $params['service_api_key'] );
181 $option = self::key_for_api_service( $service );
182
183 $validation = self::validate_service_api_key( $service_api_key, $service );
184 if ( ! $validation['status'] ) {
185 return new WP_Error( 'invalid_key', esc_html__( 'Invalid API Key', 'jetpack' ), array( 'status' => 404 ) );
186 }
187 $message = esc_html__( 'API key updated successfully.', 'jetpack' );
188 Jetpack_Options::update_option( $option, $service_api_key );
189 return array(
190 'code' => 'success',
191 'service' => $service,
192 'service_api_key' => Jetpack_Options::get_option( $option, '' ),
193 'service_api_key_source' => 'site',
194 'message' => $message,
195 );
196 }
197
198 /**
199 * Delete a third party plugin API key.
200 *
201 * @param WP_REST_Request $request {
202 * Array of parameters received by request.
203 *
204 * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'.
205 * }
206 */
207 public static function delete_service_api_key( $request ) {
208 $service = self::validate_service_api_service( $request['service'] );
209 if ( ! $service ) {
210 return self::service_api_invalid_service_response();
211 }
212 $option = self::key_for_api_service( $service );
213 Jetpack_Options::delete_option( $option );
214 $message = esc_html__( 'API key deleted successfully.', 'jetpack' );
215
216 switch ( $service ) {
217 case 'mapbox':
218 // After deleting a custom Mapbox key, try to revert to the WordPress.com one if available.
219 if ( ! class_exists( 'Jetpack_Mapbox_Helper' ) ) {
220 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-mapbox-helper.php';
221 }
222 $mapbox = Jetpack_Mapbox_Helper::get_access_token();
223 $service_api_key = $mapbox['key'];
224 $service_api_key_source = $mapbox['source'];
225 break;
226 default:
227 $service_api_key = Jetpack_Options::get_option( $option, '' );
228 $service_api_key_source = 'site';
229 }
230
231 return array(
232 'code' => 'success',
233 'service' => $service,
234 'service_api_key' => $service_api_key,
235 'service_api_key_source' => $service_api_key_source,
236 'message' => $message,
237 );
238 }
239
240 /**
241 * Validate the service provided in /service-api-keys/ endpoints.
242 * To add a service to these endpoints, add the service name to $valid_services
243 * and add '{service name}_api_key' to the non-compact return array in get_option_names(),
244 * in class-jetpack-options.php
245 *
246 * @param string $service The service the API key is for.
247 * @return string Returns the service name if valid, null if invalid.
248 */
249 public static function validate_service_api_service( $service = null ) {
250 $valid_services = array(
251 'mapbox',
252 );
253 return in_array( $service, $valid_services, true ) ? $service : null;
254 }
255
256 /**
257 * Error response for invalid service API key requests with an invalid service.
258 */
259 public static function service_api_invalid_service_response() {
260 return new WP_Error(
261 'invalid_service',
262 esc_html__( 'Invalid Service', 'jetpack' ),
263 array( 'status' => 404 )
264 );
265 }
266
267 /**
268 * Validate API Key
269 *
270 * @param string $key The API key to be validated.
271 * @param string $service The service the API key is for.
272 */
273 public static function validate_service_api_key( $key = null, $service = null ) {
274 $validation = false;
275 switch ( $service ) {
276 case 'mapbox':
277 $validation = self::validate_service_api_key_mapbox( $key );
278 break;
279 }
280 return $validation;
281 }
282
283 /**
284 * Validate Mapbox API key
285 * Based loosely on https://github.com/mapbox/geocoding-example/blob/master/php/MapboxTest.php
286 *
287 * @param string $key The API key to be validated.
288 */
289 public static function validate_service_api_key_mapbox( $key ) {
290 $status = true;
291 $msg = null;
292 $mapbox_url = sprintf(
293 'https://api.mapbox.com?%s',
294 $key
295 );
296 $mapbox_response = wp_safe_remote_get( esc_url_raw( $mapbox_url ) );
297 $mapbox_body = wp_remote_retrieve_body( $mapbox_response );
298 if ( '{"api":"mapbox"}' !== $mapbox_body ) {
299 $status = false;
300 $msg = esc_html__( 'Can\'t connect to Mapbox', 'jetpack' );
301 return array(
302 'status' => $status,
303 'error_message' => $msg,
304 );
305 }
306 $mapbox_geocode_url = esc_url_raw(
307 sprintf(
308 'https://api.mapbox.com/geocoding/v5/mapbox.places/%s.json?access_token=%s',
309 '1+broadway+new+york+ny+usa',
310 $key
311 )
312 );
313 $mapbox_geocode_response = wp_safe_remote_get( esc_url_raw( $mapbox_geocode_url ) );
314 $mapbox_geocode_body = wp_remote_retrieve_body( $mapbox_geocode_response );
315 $mapbox_geocode_json = json_decode( $mapbox_geocode_body );
316 if ( isset( $mapbox_geocode_json->message ) || ! isset( $mapbox_geocode_json->query ) ) {
317 $status = false;
318 $msg = isset( $mapbox_geocode_json->message ) ? $mapbox_geocode_json->message : 'Unknown error';
319 }
320 return array(
321 'status' => $status,
322 'error_message' => $msg,
323 );
324 }
325
326 /**
327 * Create site option key for service
328 *
329 * @param string $service The service to create key for.
330 */
331 private static function key_for_api_service( $service ) {
332 return $service . '_api_key';
333 }
334 }
335 wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys' );
336