PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-licensing/src/class-endpoints.php +431 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,431 @@
1 +<?php
2 +/**
3 + * A Licensing Endpoints class for Jetpack.
4 + *
5 + * @package automattic/jetpack-licensing
6 + */
7 +
8 +namespace Automattic\Jetpack\Licensing;
9 +
10 +use Automattic\Jetpack\Connection\Client;
11 +use Automattic\Jetpack\Licensing;
12 +use Automattic\Jetpack\Status\Visitor;
13 +use Jetpack_Options;
14 +use WP_Error;
15 +use WP_REST_Request;
16 +use WP_REST_Response;
17 +
18 +/**
19 + * Class Endpoints.
20 + * Helper class that is responsible for registering and responding to licensing endpoint requests.
21 + *
22 + * @since 1.7.0
23 + */
24 +class Endpoints {
25 + /**
26 + * This property stores the localized "Insufficient Permissions" error message.
27 + *
28 + * @var string Generic error message when user is not allowed to perform an action.
29 + */
30 + private static $user_permissions_error_msg;
31 +
32 + /**
33 + * Constructor.
34 + */
35 + public function __construct() {
36 + self::$user_permissions_error_msg = esc_html__(
37 + 'You do not have the correct user permissions to perform this action.
38 + Please contact your site admin if you think this is a mistake.',
39 + 'jetpack-licensing'
40 + );
41 + }
42 +
43 + /**
44 + * Declare the endpoints for the licensing package.
45 + *
46 + * @since 1.7.0
47 + *
48 + * @since-jetpack 10.9.0
49 + */
50 + public function register_endpoints() {
51 + /*
52 + * Get and update the last licensing error message.
53 + */
54 + register_rest_route(
55 + 'jetpack/v4',
56 + '/licensing/error',
57 + array(
58 + array(
59 + 'methods' => \WP_REST_Server::READABLE,
60 + 'callback' => __CLASS__ . '::get_licensing_error',
61 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
62 + ),
63 + array(
64 + 'methods' => \WP_REST_Server::EDITABLE,
65 + 'callback' => __CLASS__ . '::update_licensing_error',
66 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
67 + 'args' => array(
68 + 'error' => array(
69 + 'required' => true,
70 + 'type' => 'string',
71 + 'validate_callback' => __CLASS__ . '::validate_string',
72 + 'sanitize_callback' => 'sanitize_text_field',
73 + ),
74 + ),
75 + ),
76 + )
77 + );
78 +
79 + /**
80 + * Sets a license. This is still used as part of the first pass at licensing done for partners.
81 + *
82 + * See https://github.com/Automattic/jetpack/pull/23687 for more details.
83 + */
84 + register_rest_route(
85 + 'jetpack/v4',
86 + '/licensing/set-license',
87 + array(
88 + 'methods' => \WP_REST_Server::EDITABLE,
89 + 'callback' => __CLASS__ . '::set_jetpack_license',
90 + 'permission_callback' => __CLASS__ . '::set_jetpack_license_key_permission_check',
91 + 'args' => array(
92 + 'license' => array(
93 + 'required' => true,
94 + 'type' => 'string',
95 + 'validate_callback' => __CLASS__ . '::validate_string',
96 + 'sanitize_callback' => 'sanitize_text_field',
97 + ),
98 + ),
99 + )
100 + );
101 +
102 + /**
103 + * Get Jetpack user licenses.
104 + */
105 + register_rest_route(
106 + 'jetpack/v4',
107 + 'licensing/user/licenses',
108 + array(
109 + 'methods' => \WP_REST_Server::READABLE,
110 + 'callback' => __CLASS__ . '::get_user_licenses',
111 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
112 + )
113 + );
114 +
115 + /**
116 + * Get Jetpack user license counts.
117 + */
118 + register_rest_route(
119 + 'jetpack/v4',
120 + 'licensing/user/counts',
121 + array(
122 + 'methods' => \WP_REST_Server::READABLE,
123 + 'callback' => __CLASS__ . '::get_user_license_counts',
124 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
125 + )
126 + );
127 +
128 + /**
129 + * Update user-licensing activation notice dismiss info.
130 + */
131 + register_rest_route(
132 + 'jetpack/v4',
133 + 'licensing/user/activation-notice-dismiss',
134 + array(
135 + 'methods' => \WP_REST_Server::EDITABLE,
136 + 'callback' => __CLASS__ . '::update_licensing_activation_notice_dismiss',
137 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
138 + 'args' => array(
139 + 'last_detached_count' => array(
140 + 'required' => true,
141 + 'type' => 'integer',
142 + 'validate_callback' => __CLASS__ . '::validate_non_neg_int',
143 + ),
144 + ),
145 + )
146 + );
147 +
148 + /**
149 + * Attach licenses to user account
150 + */
151 + register_rest_route(
152 + 'jetpack/v4',
153 + '/licensing/attach-licenses',
154 + array(
155 + 'methods' => \WP_REST_Server::EDITABLE,
156 + 'callback' => __CLASS__ . '::attach_jetpack_licenses',
157 + 'permission_callback' => __CLASS__ . '::can_manage_options_check',
158 + 'args' => array(
159 + 'licenses' => array(
160 + 'required' => true,
161 + 'type' => 'array',
162 + 'items' => array(
163 + 'type' => 'string',
164 + ),
165 + ),
166 + ),
167 + )
168 + );
169 + }
170 +
171 + /**
172 + * Verify that the user can set a Jetpack license key
173 + *
174 + * @since 1.7.0
175 + *
176 + * @since-jetpack 9.5.0
177 + *
178 + * @return bool|WP_Error True if user is able to set a Jetpack license key
179 + */
180 + public static function set_jetpack_license_key_permission_check() {
181 + if ( Licensing::instance()->is_licensing_input_enabled() ) {
182 + return true;
183 + }
184 +
185 + return new WP_Error( 'invalid_user_permission_set_jetpack_license_key', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
186 + }
187 +
188 + /**
189 + * Verify that user can manage_options
190 + *
191 + * @since 1.7.0
192 + *
193 + * @return bool Whether user has the capability 'manage_options'.
194 + */
195 + public static function can_manage_options_check() {
196 + if ( current_user_can( 'manage_options' ) ) {
197 + return true;
198 + }
199 +
200 + return new WP_Error( 'invalid_user_permission_view_admin', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
201 + }
202 +
203 + /**
204 + * Validates that the parameter is a string.
205 + *
206 + * @since 1.7.0
207 + *
208 + * @since-jetpack 4.3.0
209 + *
210 + * @param string $value Value to check.
211 + * @param WP_REST_Request $request The request sent to the WP REST API.
212 + * @param string $param Name of the parameter passed to endpoint holding $value.
213 + *
214 + * @return bool|WP_Error
215 + */
216 + public static function validate_string( $value, $request, $param ) {
217 + if ( ! is_string( $value ) ) {
218 + /* translators: %s: The literal parameter name. Should not be translated. */
219 + return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a string.', 'jetpack-licensing' ), $param ) );
220 + }
221 + return true;
222 + }
223 +
224 + /**
225 + * Validates that the parameter is a non-negative integer (includes 0).
226 + *
227 + * @since 1.7.0
228 + *
229 + * @since-jetpack 10.4.0
230 + *
231 + * @param int $value Value to check.
232 + * @param WP_REST_Request $request The request sent to the WP REST API.
233 + * @param string $param Name of the parameter passed to endpoint holding $value.
234 + *
235 + * @return bool|WP_Error
236 + */
237 + public static function validate_non_neg_int( $value, $request, $param ) {
238 + if ( ! is_numeric( $value ) || $value < 0 ) {
239 + return new WP_Error(
240 + 'invalid_param',
241 + /* translators: %s: The literal parameter name. Should not be translated. */
242 + sprintf( esc_html__( '%s must be a non-negative integer.', 'jetpack-licensing' ), $param )
243 + );
244 + }
245 + return true;
246 + }
247 +
248 + /**
249 + * Update the last licensing error message.
250 + *
251 + * @since 1.7.0
252 + *
253 + * @since-jetpack 9.0.0
254 + *
255 + * @param WP_REST_Request $request The request.
256 + *
257 + * @return bool true.
258 + */
259 + public static function update_licensing_error( $request ) {
260 + Licensing::instance()->log_error( $request['error'] );
261 +
262 + return true;
263 + }
264 +
265 + /**
266 + * Get the last licensing error message, if any.
267 + *
268 + * @since 1.7.0
269 + *
270 + * @since-jetpack 9.0.0
271 + *
272 + * @return string Licensing error message or empty string.
273 + */
274 + public static function get_licensing_error() {
275 + return Licensing::instance()->last_error();
276 + }
277 +
278 + /**
279 + * Set a Jetpack license
280 + *
281 + * @since 1.7.0
282 + *
283 + * @since-jetpack 9.6.0
284 + *
285 + * @param WP_REST_Request $request The request.
286 + *
287 + * @return WP_REST_Response|WP_Error A response object if the option was successfully updated, or a WP_Error if it failed.
288 + */
289 + public static function set_jetpack_license( $request ) {
290 + $license = trim( sanitize_text_field( $request['license'] ) );
291 +
292 + if ( Licensing::instance()->append_license( $license ) ) {
293 + return rest_ensure_response( array( 'code' => 'success' ) );
294 + }
295 +
296 + return new WP_Error(
297 + 'setting_license_key_failed',
298 + esc_html__( 'Could not set this license key. Please try again.', 'jetpack-licensing' ),
299 + array( 'status' => 500 )
300 + );
301 + }
302 +
303 + /**
304 + * Gets the users licenses.
305 + *
306 + * @since 1.7.0
307 + *
308 + * @since-jetpack 10.4.0
309 + *
310 + * @return string|WP_Error A JSON object of user licenses if the request was successful, or a WP_Error otherwise.
311 + */
312 + public static function get_user_licenses() {
313 + $wpcom_request = Client::wpcom_json_api_request_as_user(
314 + '/jetpack-licensing/user/licenses',
315 + '2',
316 + array(
317 + 'method' => 'GET',
318 + 'headers' => array(
319 + 'Content-Type' => 'application/json',
320 + 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
321 + ),
322 + )
323 + );
324 +
325 + $response_code = wp_remote_retrieve_response_code( $wpcom_request );
326 + if ( 200 === $response_code ) {
327 + $licenses = json_decode( wp_remote_retrieve_body( $wpcom_request ) );
328 + return $licenses;
329 + } else {
330 + return new WP_Error(
331 + 'failed_to_fetch_data',
332 + esc_html__( 'Unable to fetch the requested data.', 'jetpack-licensing' ),
333 + array( 'status' => $response_code )
334 + );
335 + }
336 + }
337 +
338 + /**
339 + * Gets the users licenses counts.
340 + *
341 + * @since 1.7.0
342 + *
343 + * @since-jetpack 10.4.0
344 + *
345 + * @return string|WP_Error A JSON object of user license counts if the request was successful, or a WP_Error otherwise.
346 + */
347 + public static function get_user_license_counts() {
348 + $wpcom_request = Client::wpcom_json_api_request_as_user(
349 + '/jetpack-licensing/user/licenses/counts',
350 + '2',
351 + array(
352 + 'method' => 'GET',
353 + 'headers' => array(
354 + 'Content-Type' => 'application/json',
355 + 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
356 + ),
357 + )
358 + );
359 +
360 + $response_code = wp_remote_retrieve_response_code( $wpcom_request );
361 + if ( 200 === $response_code ) {
362 + $license_counts = json_decode( wp_remote_retrieve_body( $wpcom_request ) );
363 + return $license_counts;
364 + } else {
365 + return new WP_Error(
366 + 'failed_to_fetch_data',
367 + esc_html__( 'Unable to fetch the requested data.', 'jetpack-licensing' ),
368 + array( 'status' => $response_code )
369 + );
370 + }
371 + }
372 +
373 + /**
374 + * Update the user-licenses activation notice dismissal data.
375 + *
376 + * @since 1.7.0
377 + *
378 + * @since-jetpack 10.4.0
379 + *
380 + * @param WP_REST_Request $request The request sent to the WP REST API.
381 + *
382 + * @return array|WP_Error
383 + */
384 + public static function update_licensing_activation_notice_dismiss( $request ) {
385 +
386 + if ( ! isset( $request['last_detached_count'] ) ) {
387 + return new WP_Error( 'invalid_param', esc_html__( 'Missing parameter "last_detached_count".', 'jetpack-licensing' ), array( 'status' => 404 ) );
388 + }
389 +
390 + $default = array(
391 + 'last_detached_count' => null,
392 + 'last_dismissed_time' => null,
393 + );
394 + $last_detached_count = ( '' === $request['last_detached_count'] )
395 + ? $default['last_detached_count']
396 + : $request['last_detached_count'];
397 + $last_dismissed_time = ( '' === $request['last_detached_count'] )
398 + ? $default['last_dismissed_time']
399 + // Use UTC timezone and convert to ISO8601 format(DateTime::W3C) for best compatibility with JavaScript Date in all browsers.
400 + : ( new \DateTime( 'NOW', new \DateTimeZone( 'UTC' ) ) )->format( \DateTime::W3C );
401 +
402 + $notice_data = array(
403 + 'last_detached_count' => $last_detached_count,
404 + 'last_dismissed_time' => $last_dismissed_time,
405 + );
406 +
407 + Jetpack_Options::update_option( 'licensing_activation_notice_dismiss', $notice_data, true );
408 + return rest_ensure_response( $notice_data );
409 + }
410 +
411 + /**
412 + * Attach Jetpack licenses
413 + *
414 + * @since 1.7.0
415 + *
416 + * @since-jetpack 10.4.0
417 + *
418 + * @param WP_REST_Request $request The request.
419 + *
420 + * @return WP_REST_Response|WP_Error A response object
421 + */
422 + public static function attach_jetpack_licenses( $request ) {
423 + $licenses = array_map(
424 + function ( $license ) {
425 + return trim( sanitize_text_field( $license ) );
426 + },
427 + $request['licenses']
428 + );
429 + return rest_ensure_response( Licensing::instance()->attach_licenses( $licenses ) );
430 + }
431 +}