Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.08% covered (success)
98.08%
51 / 52
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
REST_Controller
98.08% covered (success)
98.08%
51 / 52
75.00% covered (warning)
75.00%
3 / 4
7
0.00% covered (danger)
0.00%
0 / 1
 register_rest_routes
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
1
 helper_script_permissions_callback
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 install_helper_script
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 delete_helper_script
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * The Jetpack Helper Script Rest Controller class.
4 * Registers the REST routes.
5 *
6 * @package automattic/jetpack-transport-helper
7 */
8
9// After changing this file, consider increasing the version number ("VXXX") in all the files using this namespace, in
10// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
11// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
12// are installed, or in some other cases).
13namespace Automattic\Jetpack\Transport_Helper\V0005;
14
15use Automattic\Jetpack\Backup\V0005\Helper_Script_Manager;
16use Automattic\Jetpack\Connection\Rest_Authentication;
17use WP_Error;
18use WP_REST_Request;
19use WP_REST_Server;
20use function esc_html__;
21use function is_wp_error;
22use function register_rest_route;
23use function rest_authorization_required_code;
24use function rest_ensure_response;
25
26/**
27 * Registers the REST routes.
28 */
29class REST_Controller {
30    /**
31     * Registers the REST routes.
32     *
33     * @access public
34     * @static
35     */
36    public static function register_rest_routes() {
37        // Install a Helper Script to assist with fetching data.
38        register_rest_route(
39            'jetpack/v4',
40            // This route can be generalized once we no longer depend on the backup package
41            '/backup-helper-script',
42            array(
43                'methods'             => WP_REST_Server::CREATABLE,
44                'callback'            => __CLASS__ . '::install_helper_script',
45                'permission_callback' => __CLASS__ . '::helper_script_permissions_callback',
46                'args'                => array(
47                    'helper' => array(
48                        'description' => __( 'base64 encoded Helper Script body.', 'jetpack-transport-helper' ),
49                        'type'        => 'string',
50                        'required'    => true,
51                    ),
52                ),
53            )
54        );
55
56        // Delete a Helper Script.
57        register_rest_route(
58            'jetpack/v4',
59            // This route can be generalized once we no longer depend on the backup package
60            '/backup-helper-script',
61            array(
62                'methods'             => WP_REST_Server::DELETABLE,
63                'callback'            => __CLASS__ . '::delete_helper_script',
64                'permission_callback' => __CLASS__ . '::helper_script_permissions_callback',
65                'args'                => array(
66                    'path' => array(
67                        'description' => __( 'Path to Helper Script', 'jetpack-transport-helper' ),
68                        'type'        => 'string',
69                        'required'    => true,
70                    ),
71                ),
72            )
73        );
74    }
75
76    /**
77     * The Jetpack endpoints should only be available via site-level authentication.
78     * This means that the corresponding endpoints can only be accessible from WPCOM.
79     *
80     * @access public
81     * @static
82     *
83     * @return bool|WP_Error True if a blog token was used to sign the request, WP_Error otherwise.
84     */
85    public static function helper_script_permissions_callback() {
86        if ( Rest_Authentication::is_signed_with_blog_token() ) {
87            return true;
88        }
89
90        $error_msg = esc_html__(
91            'You are not allowed to perform this action.',
92            'jetpack-transport-helper'
93        );
94
95        return new WP_Error( 'rest_forbidden', $error_msg, array( 'status' => rest_authorization_required_code() ) );
96    }
97
98    /**
99     * Install the Helper Script.
100     *
101     * @access public
102     * @static
103     *
104     * @param WP_REST_Request $request The request sent to the WP REST API.
105     *
106     * @return array|WP_Error An array with installation info on success:
107     *
108     *   'path'    (string) Helper script installation path on the filesystem.
109     *   'url'     (string) URL to the helper script.
110     *   'abspath' (string) WordPress root.
111     *
112     *   or an instance of WP_Error on failure.
113     */
114    public static function install_helper_script( $request ) {
115        $helper_script = $request->get_param( 'helper' );
116
117        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
118        $helper_script = base64_decode( $helper_script );
119        if ( ! $helper_script ) {
120            return new WP_Error( 'invalid_args', __( 'Helper Script body must be base64 encoded', 'jetpack-transport-helper' ), 400 );
121        }
122
123        $installation_info = Helper_Script_Manager::install_helper_script( $helper_script );
124        Helper_Script_Manager::cleanup_expired_helper_scripts();
125
126        return rest_ensure_response( $installation_info );
127    }
128
129    /**
130     * Delete a Helper Script.
131     *
132     * @access public
133     * @static
134     *
135     * @param WP_REST_Request $request The request sent to the WP REST API.
136     *
137     * @return array|WP_Error An array with 'success' key indicating the result of the delete operation.
138     */
139    public static function delete_helper_script( $request ) {
140        $path_to_helper_script = $request->get_param( 'path' );
141
142        $delete_result = Helper_Script_Manager::delete_helper_script( $path_to_helper_script );
143        Helper_Script_Manager::cleanup_expired_helper_scripts();
144
145        if ( is_wp_error( $delete_result ) ) {
146            return $delete_result;
147        }
148
149        return rest_ensure_response( array( 'success' => true ) );
150    }
151}