PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 All 502 releases
jetpack / src / reprint-export / class-rest-controller.php

class-rest-controller.php in Jetpack – WP Security, Backup, Speed, & Growth 16.2, at src/reprint-export/class-rest-controller.php

144 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST controller for Jetpack Reprint export provisioning endpoints.
4 *
5 * Requires a verified Jetpack user token for a site administrator.
6 *
7 * @package automattic/jetpack
8 */
9
10 namespace Automattic\Jetpack\Reprint_Export;
11
12 use Automattic\Jetpack\Connection\Rest_Authentication;
13 use WP_REST_Controller;
14 use WP_REST_Response;
15 use WP_REST_Server;
16
17 /**
18 * Reprint exporter REST controller.
19 */
20 class REST_Controller extends WP_REST_Controller {
21
22 /**
23 * The API namespace.
24 *
25 * @var string
26 */
27 protected $namespace = 'jetpack/v4';
28
29 /**
30 * The REST base path.
31 *
32 * @var string
33 */
34 protected $rest_base = 'reprint';
35
36 /**
37 * Registers the reprint export routes.
38 */
39 public function register_routes() {
40 register_rest_route(
41 $this->namespace,
42 '/' . $this->rest_base . '/rotate-export-secret',
43 array(
44 array(
45 'methods' => WP_REST_Server::CREATABLE,
46 'callback' => array( $this, 'rotate_secret' ),
47 'permission_callback' => array( $this, 'permission_check' ),
48 ),
49 )
50 );
51
52 register_rest_route(
53 $this->namespace,
54 '/' . $this->rest_base . '/enable-export',
55 array(
56 array(
57 'methods' => WP_REST_Server::CREATABLE,
58 'callback' => array( $this, 'enable_export' ),
59 'permission_callback' => array( $this, 'permission_check' ),
60 ),
61 )
62 );
63 }
64
65 /**
66 * Opens the export window without rotating the secret, so a client that
67 * already has one can reopen a window that has closed.
68 *
69 * Registered only where the feature is available, so clients also use a 404
70 * from here to tell whether the site supports export at all.
71 *
72 * @return WP_REST_Response The unix timestamp the window was opened at.
73 */
74 public function enable_export() {
75 $enabled_at = Reprint_Exporter::open_export_window();
76
77 Reprint_Exporter::record_event(
78 'window_opened',
79 array( 'user_id' => get_current_user_id() )
80 );
81
82 return new WP_REST_Response( array( 'enabled_at' => $enabled_at ), 200 );
83 }
84
85 /**
86 * Rotates the shared secret and returns it.
87 *
88 * Uses random_bytes() rather than wp_generate_password(). That helper is for
89 * passwords a person reads and types, and sites can filter it through
90 * `random_password` to enforce their own policy — an extension point we do
91 * not want on a credential. random_bytes() also throws rather than quietly
92 * falling back to a weaker source, which wp_rand() will do.
93 *
94 * @return WP_REST_Response The new secret on success, or a 500 error.
95 */
96 public function rotate_secret() {
97 $secret = bin2hex( random_bytes( 32 ) );
98
99 if ( ! Reprint_Exporter::store_secret( $secret ) ) {
100 return new WP_REST_Response(
101 array( 'error' => 'Failed to persist the new secret.' ),
102 500
103 );
104 }
105
106 Reprint_Exporter::record_event(
107 'secret_rotated',
108 array( 'user_id' => get_current_user_id() )
109 );
110
111 return new WP_REST_Response( array( 'secret' => $secret ), 200 );
112 }
113
114 /**
115 * Permission callback: a Jetpack-signed request from a site administrator.
116 *
117 * Deliberately a role check, not a capability one. This hands out a secret
118 * that streams the whole database and file tree, and no capability says
119 * that — `manage_options` is the closest, but plugins grant it to shop
120 * managers and the like.
121 *
122 * @return bool
123 */
124 public function permission_check() {
125 if ( ! Rest_Authentication::is_signed_with_user_token() ) {
126 return false;
127 }
128
129 $user = wp_get_current_user();
130 if ( ! $user || ! $user->exists() ) {
131 return false;
132 }
133
134 // Network administrator only: the export takes every table and everything
135 // under ABSPATH, so a subsite administrator would leave with every other
136 // site's users, content and uploads.
137 if ( is_multisite() ) {
138 return is_super_admin( $user->ID );
139 }
140
141 return in_array( 'administrator', $user->roles, true );
142 }
143 }
144