Version Description
Download this release
Release Info
Developer | dmchale |
Plugin | Disable REST API |
Version | v1.6 |
Comparing to | |
See all releases |
Code changes from version v1.5.1 to v1.6
- admin.php +31 -78
- classes/admin.php +93 -0
- classes/disable-rest-api.php +176 -34
- classes/helpers.php +209 -0
- classes/requirements-check.php +2 -2
- css/admin.css +13 -0
- disable-json-api.php +14 -3
- js/admin-footer.js +22 -0
- js/admin-header.js +7 -0
- readme.txt +18 -10
- uninstall.php +1 -6
admin.php
CHANGED
@@ -1,95 +1,48 @@
|
|
1 |
-
<style>
|
2 |
-
#DRA_container ul li {
|
3 |
-
padding-left: 20px;
|
4 |
-
}
|
5 |
-
|
6 |
-
#DRA_container em {
|
7 |
-
font-size: 0.8em;
|
8 |
-
}
|
9 |
-
</style>
|
10 |
-
|
11 |
-
<script>
|
12 |
-
function dra_namespace_click(namespace, id) {
|
13 |
-
if (jQuery('#dra_namespace_' + id).is(":checked")) {
|
14 |
-
jQuery("input[data-namespace='" + namespace + "']").prop('checked', true);
|
15 |
-
} else {
|
16 |
-
jQuery("input[data-namespace='" + namespace + "']").prop('checked', false);
|
17 |
-
}
|
18 |
-
};
|
19 |
-
</script>
|
20 |
-
|
21 |
<div class="wrap">
|
22 |
<h1><?php echo esc_html__( "Disable REST API", "disable-json-api" ); ?></h1>
|
23 |
<?php settings_errors( 'DRA-notices' ); ?>
|
|
|
24 |
<p><?php echo esc_html__( "By default, this plugin ensures that the entire REST API is protected from non-authenticated users. You may use this page to specify which endpoints should be allowed to behave as normal.", "disable-json-api" ); ?></p>
|
25 |
<p>
|
26 |
<strong><?php echo esc_html__( "IMPORTANT NOTE:", "disable-json-api" ); ?></strong> <?php echo esc_html__( "Checking a box merely restores default functionality to an endpoint. Other authentication and/or permissions may still be required for access, or other themes/plugins may also affect access to those endpoints.", "disable-json-api" ); ?>
|
27 |
</p>
|
28 |
|
29 |
-
<
|
30 |
-
<?php wp_nonce_field( 'DRA_admin_nonce' ); ?>
|
31 |
-
|
32 |
-
<div id="DRA_container"><?php DRA_display_route_checkboxes(); ?></div>
|
33 |
-
|
34 |
-
<?php submit_button(); ?>
|
35 |
-
<input type="submit" name="reset"
|
36 |
-
value="<?php echo esc_attr__( "Reset Whitelisted Routes", "disable-json-api" ); ?>"
|
37 |
-
onclick="return confirm('<?php echo esc_attr__( "Are you sure you wish to clear all whitelisted routes?", "disable-json-api" ); ?>');">
|
38 |
-
</form>
|
39 |
-
</div>
|
40 |
-
|
41 |
-
<?php
|
42 |
-
/**
|
43 |
-
* Loop through all routes returned by the REST API and display them on-screen
|
44 |
-
*
|
45 |
-
*/
|
46 |
-
function DRA_display_route_checkboxes() {
|
47 |
-
$wp_rest_server = rest_get_server();
|
48 |
-
$all_namespaces = $wp_rest_server->get_namespaces();
|
49 |
-
$all_routes = array_keys( $wp_rest_server->get_routes() );
|
50 |
-
$whitelisted_routes = is_array( get_option( 'DRA_route_whitelist' ) ) ? get_option( 'DRA_route_whitelist' ) : array();
|
51 |
-
|
52 |
-
$loopCounter = 0;
|
53 |
-
$current_namespace = '';
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
-
|
60 |
-
$current_namespace = $route;
|
61 |
-
if ( 0 != $loopCounter ) {
|
62 |
-
echo "</ul>";
|
63 |
-
}
|
64 |
|
65 |
-
|
66 |
-
|
|
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
|
72 |
-
|
73 |
-
echo "<li><label><input name='rest_routes[]' value='$route' type='checkbox' data-namespace='$current_namespace' $checkedProp> " . esc_html( $route ) . "</label></li>";
|
74 |
-
}
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
-
|
83 |
-
* During comparison, encode the route being requested in the same fashion that it's stored in the database option
|
84 |
-
* Encoding during save happens in Disable_REST_API::maybe_process_settings_form()
|
85 |
-
*
|
86 |
-
* @param $route
|
87 |
-
* @param $whitelisted_routes
|
88 |
-
*
|
89 |
-
* @return string
|
90 |
-
*/
|
91 |
-
function DRA_get_route_checked_prop( $route, $whitelisted_routes ) {
|
92 |
-
$is_route_checked = in_array( esc_html( $route ), $whitelisted_routes, true );
|
93 |
|
94 |
-
|
95 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="wrap">
|
2 |
<h1><?php echo esc_html__( "Disable REST API", "disable-json-api" ); ?></h1>
|
3 |
<?php settings_errors( 'DRA-notices' ); ?>
|
4 |
+
|
5 |
<p><?php echo esc_html__( "By default, this plugin ensures that the entire REST API is protected from non-authenticated users. You may use this page to specify which endpoints should be allowed to behave as normal.", "disable-json-api" ); ?></p>
|
6 |
<p>
|
7 |
<strong><?php echo esc_html__( "IMPORTANT NOTE:", "disable-json-api" ); ?></strong> <?php echo esc_html__( "Checking a box merely restores default functionality to an endpoint. Other authentication and/or permissions may still be required for access, or other themes/plugins may also affect access to those endpoints.", "disable-json-api" ); ?>
|
8 |
</p>
|
9 |
|
10 |
+
<hr />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
+
<div id="select-container">
|
13 |
+
<?php echo esc_html__( "Rules for", "disable-json-api" ); ?>: <select name="role" id="dra-role">
|
14 |
+
<option value="none"><?php echo esc_html__( "Unauthenticated Users", "disable-json-api" ); ?></option>
|
15 |
+
<?php
|
16 |
+
$role = ( isset( $_GET['role'] ) ) ? $_GET['role'] : 'none';
|
17 |
+
wp_dropdown_roles( $role );
|
18 |
+
?>
|
19 |
+
</select>
|
20 |
+
</div>
|
21 |
|
22 |
+
<hr />
|
|
|
|
|
|
|
|
|
23 |
|
24 |
+
<form method="post" action="" id="DRA_form">
|
25 |
+
<?php wp_nonce_field( 'DRA_admin_nonce' ); ?>
|
26 |
+
<input type="hidden" name="role" value="<?php echo esc_attr( $role ); ?>">
|
27 |
|
28 |
+
<div id="default-allow-container">
|
29 |
+
<?php DRA_Admin::display_role_default_allow( $role ); ?>
|
30 |
+
</div>
|
31 |
|
32 |
+
<hr />
|
|
|
|
|
33 |
|
34 |
+
<div id="route-container">
|
35 |
+
<?php DRA_Admin::display_route_checkboxes( $role ); ?>
|
36 |
+
<hr />
|
37 |
+
</div>
|
38 |
|
39 |
+
<div id="button-container">
|
40 |
+
<?php submit_button(); ?>
|
41 |
+
<input type="submit" name="reset" id="dra-reset-button"
|
42 |
+
value="<?php echo esc_attr__( "Reset Allowed List of Routes", "disable-json-api" ); ?>"
|
43 |
+
onclick="return confirm('<?php echo esc_attr__( "Are you sure you wish to reset all allowed routes for this user role?", "disable-json-api" ); ?>');">
|
44 |
+
</div>
|
45 |
|
46 |
+
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
+
</div>
|
|
classes/admin.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class DRA_Admin {
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Loop through all routes returned by the REST API and display them on-screen
|
6 |
+
*
|
7 |
+
* @param string $role
|
8 |
+
*/
|
9 |
+
static function display_route_checkboxes( $role = 'none' ) {
|
10 |
+
$all_namespaces = DRA_Helpers::get_all_rest_namespaces();
|
11 |
+
$all_routes = DRA_Helpers::get_all_rest_routes();
|
12 |
+
$allowed_routes = DRA_Helpers::get_allowed_routes( $role );
|
13 |
+
|
14 |
+
$loopCounter = 0;
|
15 |
+
$current_namespace = '';
|
16 |
+
|
17 |
+
foreach ( $all_routes as $route ) {
|
18 |
+
$is_route_namespace = in_array( ltrim( $route, "/" ), $all_namespaces );
|
19 |
+
$checkedProp = self::get_route_checked_prop( $route, $allowed_routes );
|
20 |
+
|
21 |
+
if ( $is_route_namespace || "/" == $route ) {
|
22 |
+
$current_namespace = $route;
|
23 |
+
if ( 0 != $loopCounter ) {
|
24 |
+
echo "</ul>";
|
25 |
+
}
|
26 |
+
|
27 |
+
$route_for_display = ( "/" == $route ) ? "/ <em>" . esc_html__( "REST API ROOT", "disable-json-api" ) . "</em>" : esc_html( $route );
|
28 |
+
echo "<label class='switch'><input name='rest_routes[]' value='$route' type='checkbox' id='dra_namespace_$loopCounter' onclick='dra_namespace_click(\"$route\", $loopCounter)' $checkedProp><span class='slider'></span></label><h2><label for='dra_namespace_$loopCounter'> $route_for_display</label></h2><ul>";
|
29 |
+
|
30 |
+
if ( "/" == $route ) {
|
31 |
+
echo "<li>" . sprintf( esc_html__( "On this website, the REST API root is %s", "disable-json-api" ), "<strong>" . rest_url() . "</strong>" ) . "</li>";
|
32 |
+
}
|
33 |
+
|
34 |
+
} else {
|
35 |
+
echo "<li><label class='switch'><input name='rest_routes[]' id='dra_namespace_$loopCounter' value='$route' type='checkbox' data-namespace='$current_namespace' $checkedProp><span class='slider'></span></label><label for='dra_namespace_$loopCounter'> " . esc_html( $route ) . "</label></li>";
|
36 |
+
}
|
37 |
+
|
38 |
+
$loopCounter ++;
|
39 |
+
}
|
40 |
+
echo "</ul>";
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* During comparison, encode the route being requested in the same fashion that it's stored in the database option
|
46 |
+
* Encoding during save happens in Disable_REST_API::maybe_process_settings_form()
|
47 |
+
*
|
48 |
+
* @param $route
|
49 |
+
* @param $allowed_routes
|
50 |
+
*
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
static function get_route_checked_prop( $route, $allowed_routes ) {
|
54 |
+
$is_route_checked = in_array( esc_html( $route ), array_map( 'esc_html', $allowed_routes ), true );
|
55 |
+
|
56 |
+
return checked( $is_route_checked, true, false );
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Displays setting for default role on admin page
|
62 |
+
*
|
63 |
+
* @param $role
|
64 |
+
*/
|
65 |
+
static function display_role_default_allow( $role ) {
|
66 |
+
$default_allow_true_checked = '';
|
67 |
+
$default_allow_false_checked = '';
|
68 |
+
|
69 |
+
$role_default_allow = DRA_Helpers::get_default_allow_for_role( $role );
|
70 |
+
if ( $role_default_allow ) {
|
71 |
+
$default_allow_true_checked = ' checked="checked"';
|
72 |
+
} else {
|
73 |
+
$default_allow_false_checked = ' checked="checked"';
|
74 |
+
}
|
75 |
+
|
76 |
+
/* translators: name of user role */
|
77 |
+
echo sprintf( '<h2>%s</h2>', sprintf( esc_html__( 'Manage Rules for %s Users', 'disable-json-api' ), DRA_Helpers::get_role_name( $role ) ) );
|
78 |
+
?>
|
79 |
+
<p style="font-style:italic;">
|
80 |
+
<?php
|
81 |
+
echo esc_html__( 'NOTE: New routes may be added in the future by plugins, themes, or WordPress itself.', 'disable-json-api' );
|
82 |
+
echo '<br />';
|
83 |
+
echo esc_html__( 'If you choose to manage access for a user role, you will have to come back and add permissions for any new routes later.', 'disable-json-api' );
|
84 |
+
?>
|
85 |
+
</p>
|
86 |
+
<label><input type="radio" name="default_allow" value="0" <?php echo $default_allow_false_checked; ?>> <?php echo esc_html__( 'Manage REST API Access', 'disable-json-api' ); ?></label>
|
87 |
+
|
88 |
+
<label><input type="radio" name="default_allow" value="1" <?php echo $default_allow_true_checked; ?>> <?php echo esc_html__( 'Allow Full REST API Access', 'disable-json-api' ); ?></label>
|
89 |
+
<?php
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
}
|
classes/disable-rest-api.php
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
* Disable_REST_API class
|
5 |
*
|
@@ -9,6 +8,7 @@ class Disable_REST_API {
|
|
9 |
|
10 |
const MENU_SLUG = 'disable_rest_api_settings';
|
11 |
const CAPABILITY = 'manage_options';
|
|
|
12 |
|
13 |
/**
|
14 |
* Stores 'disable-json-api/disable-json-api.php' typically
|
@@ -28,21 +28,26 @@ class Disable_REST_API {
|
|
28 |
// Set variable so the class knows how to reference the plugin
|
29 |
$this->base_file_path = plugin_basename( $path );
|
30 |
|
|
|
|
|
|
|
|
|
31 |
add_action( 'admin_menu', array( &$this, 'define_admin_link' ) );
|
32 |
|
33 |
-
|
|
|
34 |
|
35 |
}
|
36 |
|
37 |
|
38 |
/**
|
39 |
-
* Checks for a current route being requested, and processes the
|
40 |
*
|
41 |
* @param $access
|
42 |
*
|
43 |
* @return WP_Error|null|boolean
|
44 |
*/
|
45 |
-
public function
|
46 |
|
47 |
// Return current value of $access and skip all plugin functionality
|
48 |
if ( $this->allow_rest_api() ) {
|
@@ -51,10 +56,11 @@ class Disable_REST_API {
|
|
51 |
|
52 |
$current_route = $this->get_current_route();
|
53 |
|
54 |
-
if ( ! $this->
|
55 |
return $this->get_wp_error( $access );
|
56 |
}
|
57 |
|
|
|
58 |
return $access;
|
59 |
|
60 |
}
|
@@ -75,29 +81,53 @@ class Disable_REST_API {
|
|
75 |
|
76 |
|
77 |
/**
|
78 |
-
* Checks a route for whether it belongs to the
|
79 |
*
|
80 |
* @param $currentRoute
|
81 |
*
|
82 |
* @return boolean
|
83 |
*/
|
84 |
-
private function
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
}, false );
|
89 |
|
90 |
-
|
|
|
91 |
|
|
|
|
|
92 |
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
|
102 |
}
|
103 |
|
@@ -109,11 +139,15 @@ class Disable_REST_API {
|
|
109 |
*/
|
110 |
public function define_admin_link() {
|
111 |
|
112 |
-
add_options_page(
|
113 |
-
|
114 |
-
'
|
115 |
-
|
|
|
|
|
|
|
116 |
add_filter( "plugin_action_links_$this->base_file_path", array( &$this, 'settings_link' ) );
|
|
|
117 |
|
118 |
}
|
119 |
|
@@ -149,6 +183,18 @@ class Disable_REST_API {
|
|
149 |
|
150 |
}
|
151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
|
153 |
/**
|
154 |
* Process the admin page settings form submission
|
@@ -165,22 +211,46 @@ class Disable_REST_API {
|
|
165 |
return;
|
166 |
}
|
167 |
|
168 |
-
//
|
169 |
-
$
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
172 |
|
173 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
if ( empty( $rest_routes ) || isset( $_POST['reset'] ) ) {
|
175 |
-
delete_option( 'DRA_route_whitelist' );
|
176 |
-
add_settings_error( 'DRA-notices', esc_attr( 'settings_updated' ), esc_html__( 'All whitelists have been removed.', 'disable-json-api' ), 'updated' );
|
177 |
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
|
181 |
-
// Save
|
182 |
-
|
183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
}
|
186 |
|
@@ -191,7 +261,7 @@ class Disable_REST_API {
|
|
191 |
* @return bool
|
192 |
*/
|
193 |
private function allow_rest_api() {
|
194 |
-
return (bool) apply_filters( 'dra_allow_rest_api',
|
195 |
}
|
196 |
|
197 |
|
@@ -215,4 +285,76 @@ class Disable_REST_API {
|
|
215 |
return new WP_Error( 'rest_cannot_access', $error_message, array( 'status' => rest_authorization_required_code() ) );
|
216 |
}
|
217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
* Disable_REST_API class
|
4 |
*
|
8 |
|
9 |
const MENU_SLUG = 'disable_rest_api_settings';
|
10 |
const CAPABILITY = 'manage_options';
|
11 |
+
const VERSION = '1.6';
|
12 |
|
13 |
/**
|
14 |
* Stores 'disable-json-api/disable-json-api.php' typically
|
28 |
// Set variable so the class knows how to reference the plugin
|
29 |
$this->base_file_path = plugin_basename( $path );
|
30 |
|
31 |
+
// Do logic for upgrading to 1.6 from versions less than 1.6
|
32 |
+
add_action( 'init', array( &$this, 'option_check' ) );
|
33 |
+
|
34 |
+
// Set up admin page for plugin settings
|
35 |
add_action( 'admin_menu', array( &$this, 'define_admin_link' ) );
|
36 |
|
37 |
+
// This actually does everything in this plugin
|
38 |
+
add_filter( 'rest_authentication_errors', array( &$this, 'you_shall_not_pass' ), 20 );
|
39 |
|
40 |
}
|
41 |
|
42 |
|
43 |
/**
|
44 |
+
* Checks for a current route being requested, and processes the allowlist
|
45 |
*
|
46 |
* @param $access
|
47 |
*
|
48 |
* @return WP_Error|null|boolean
|
49 |
*/
|
50 |
+
public function you_shall_not_pass( $access ) {
|
51 |
|
52 |
// Return current value of $access and skip all plugin functionality
|
53 |
if ( $this->allow_rest_api() ) {
|
56 |
|
57 |
$current_route = $this->get_current_route();
|
58 |
|
59 |
+
if ( ! $this->is_route_allowed( $current_route ) ) {
|
60 |
return $this->get_wp_error( $access );
|
61 |
}
|
62 |
|
63 |
+
// If we got all the way here, return the unmodified $access response
|
64 |
return $access;
|
65 |
|
66 |
}
|
81 |
|
82 |
|
83 |
/**
|
84 |
+
* Checks a route for whether it belongs to the list of allowed routes
|
85 |
*
|
86 |
* @param $currentRoute
|
87 |
*
|
88 |
* @return boolean
|
89 |
*/
|
90 |
+
private function is_route_allowed( $currentRoute ) {
|
91 |
|
92 |
+
$current_options = get_option( 'disable_rest_api_options', array() );
|
93 |
+
$current_user_roles = $this->get_current_user_roles();
|
|
|
94 |
|
95 |
+
// Loop through user roles belonging to the current user
|
96 |
+
foreach ( $current_user_roles as $role ) {
|
97 |
|
98 |
+
// If we have a definition for the current user's role
|
99 |
+
if ( isset( $current_options['roles'][$role] ) ) {
|
100 |
|
101 |
+
// See if this route is specifically allowed
|
102 |
+
$is_currentRoute_allowed = array_reduce( DRA_Helpers::get_allowed_routes( $role ), function ( $isMatched, $pattern ) use ( $currentRoute ) {
|
103 |
+
return $isMatched || (bool) preg_match( '@^' . htmlspecialchars_decode( $pattern ) . '$@i', $currentRoute );
|
104 |
+
}, false );
|
105 |
+
if ( $is_currentRoute_allowed ) {
|
106 |
+
return true;
|
107 |
+
}
|
108 |
+
|
109 |
+
// See if this route is specifically disallowed
|
110 |
+
$is_currentRoute_disallowed = array_reduce( DRA_Helpers::get_allowed_routes( $role, false ), function ( $isMatched, $pattern ) use ( $currentRoute ) {
|
111 |
+
return $isMatched || (bool) preg_match( '@^' . htmlspecialchars_decode( $pattern ) . '$@i', $currentRoute );
|
112 |
+
}, false );
|
113 |
+
if ( $is_currentRoute_disallowed ) {
|
114 |
+
return false;
|
115 |
+
}
|
116 |
|
117 |
+
// If the route has no definition, see if the role is set to allow unknown routes by default
|
118 |
+
if ( true === $current_options['roles'][$role]['default_allow'] ) {
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
|
122 |
+
}
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
// If we got all the way here, we didn't find any rules that matched the route and none of the user roles had a "default unknowns to true" rule.
|
127 |
+
// Most likely, we're here because the request is from a user role we don't have a definition for.
|
128 |
+
// Return the plugin-global setting for what should be done in the case of something we don't know what to do with.
|
129 |
+
// As of this writing in v1.6, this is "allow" by default since we want new User Roles to be ALLOWED access to everything until an admin chooses to take that right away.
|
130 |
+
return $current_options['default_allow'];
|
131 |
|
132 |
}
|
133 |
|
139 |
*/
|
140 |
public function define_admin_link() {
|
141 |
|
142 |
+
add_options_page(
|
143 |
+
esc_html__( 'Disable REST API Settings', 'disable-json-api' ),
|
144 |
+
esc_html__( 'Disable REST API', 'disable-json-api' ),
|
145 |
+
self::CAPABILITY,
|
146 |
+
self::MENU_SLUG,
|
147 |
+
array( &$this, 'settings_page' )
|
148 |
+
);
|
149 |
add_filter( "plugin_action_links_$this->base_file_path", array( &$this, 'settings_link' ) );
|
150 |
+
add_action( 'admin_enqueue_scripts', array( &$this, 'admin_enqueues' ) );
|
151 |
|
152 |
}
|
153 |
|
183 |
|
184 |
}
|
185 |
|
186 |
+
/**
|
187 |
+
* Enqueues for adding CSS and JavaScript to the admin settings page
|
188 |
+
*/
|
189 |
+
public function admin_enqueues( $hook_suffix ) {
|
190 |
+
if ( $hook_suffix == 'settings_page_' . self::MENU_SLUG ) {
|
191 |
+
$enqueue_file_base = WP_PLUGIN_DIR . '/' . plugin_dir_path( $this->base_file_path );
|
192 |
+
wp_enqueue_style( 'dra-admin-css', plugins_url( 'css/admin.css', $this->base_file_path ), array(), filemtime( $enqueue_file_base . 'css/admin.css' ), 'all' );
|
193 |
+
wp_enqueue_script( 'dra-admin-header', plugins_url( 'js/admin-header.js', $this->base_file_path ), array( 'jquery' ), filemtime( $enqueue_file_base . 'js/admin-header.js' ), false );
|
194 |
+
wp_enqueue_script( 'dra-admin-footer', plugins_url( 'js/admin-footer.js', $this->base_file_path ), array( 'jquery' ), filemtime( $enqueue_file_base . 'js/admin-footer.js' ), true );
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
|
199 |
/**
|
200 |
* Process the admin page settings form submission
|
211 |
return;
|
212 |
}
|
213 |
|
214 |
+
// Confirm a valid role has been passed
|
215 |
+
$role = ( isset( $_POST['role'] ) ) ? $_POST['role'] : 'dra-undefined';
|
216 |
+
if ( ! DRA_Helpers::is_valid_role( $role ) ) {
|
217 |
+
add_settings_error( 'DRA-notices', esc_attr( 'settings_updated' ), esc_html__( 'Invalid user role detected when processing form. No updates have been made.', 'disable-json-api' ), 'error' );
|
218 |
+
return;
|
219 |
+
}
|
220 |
+
|
221 |
+
// Catch the `default_allow` value for this role
|
222 |
+
$default_allow = ( isset( $_POST['default_allow'] ) && "1" == $_POST['default_allow'] ) ? true : false;
|
223 |
|
224 |
+
// Catch the routes that should be allowed
|
225 |
+
$rest_routes = ( isset( $_POST['rest_routes'] ) ) ? wp_unslash( $_POST['rest_routes'] ) : array();
|
226 |
+
|
227 |
+
// Retrieve all current rules for all roles
|
228 |
+
$arr_option = get_option( 'disable_rest_api_options' );
|
229 |
+
|
230 |
+
// If resetting or allowlist is empty, clear the option and exit the function
|
231 |
if ( empty( $rest_routes ) || isset( $_POST['reset'] ) ) {
|
|
|
|
|
232 |
|
233 |
+
// Unauthorized users default to no routes allowed. All other user roles default to allowing all routes
|
234 |
+
$rest_routes_for_setting = DRA_Helpers::build_routes_rule_for_all( $default_allow );
|
235 |
+
$msg = esc_html__( 'All allowlists have been reset for this user role.', 'disable-json-api' );
|
236 |
+
|
237 |
+
} else {
|
238 |
+
|
239 |
+
// Get back the full list of true/false routes based on the posted routes allowed
|
240 |
+
$rest_routes_for_setting = DRA_Helpers::build_routes_rule( $rest_routes );
|
241 |
+
$msg = esc_html__( 'Allowlist settings saved for this user role.', 'disable-json-api' );
|
242 |
+
|
243 |
}
|
244 |
|
245 |
+
// Save only the rules for this role back to itself
|
246 |
+
$arr_option['roles'][$role] = array(
|
247 |
+
'default_allow' => $default_allow,
|
248 |
+
'allow_list' => $rest_routes_for_setting,
|
249 |
+
);
|
250 |
+
|
251 |
+
// Save allowlist to the Options table and return with message for user
|
252 |
+
update_option( 'disable_rest_api_options', $arr_option );
|
253 |
+
add_settings_error( 'DRA-notices', esc_attr( 'settings_updated' ), $msg, 'updated' );
|
254 |
|
255 |
}
|
256 |
|
261 |
* @return bool
|
262 |
*/
|
263 |
private function allow_rest_api() {
|
264 |
+
return (bool) apply_filters( 'dra_allow_rest_api', false );
|
265 |
}
|
266 |
|
267 |
|
285 |
return new WP_Error( 'rest_cannot_access', $error_message, array( 'status' => rest_authorization_required_code() ) );
|
286 |
}
|
287 |
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Helper function to migrate from pre-version-1.6 to the new option
|
291 |
+
*/
|
292 |
+
public function option_check() {
|
293 |
+
|
294 |
+
// If our new option already exists, we can bail
|
295 |
+
if ( get_option( 'disable_rest_api_options') ) {
|
296 |
+
return;
|
297 |
+
}
|
298 |
+
|
299 |
+
// Make sure we have a default option defined
|
300 |
+
$this->create_settings_option();
|
301 |
+
|
302 |
+
}
|
303 |
+
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Create settings option for the plugin
|
307 |
+
*/
|
308 |
+
private function create_settings_option() {
|
309 |
+
|
310 |
+
// Define the basic structure of our new option
|
311 |
+
$arr_option = array(
|
312 |
+
'version' => self::VERSION, // the current version of this plugin
|
313 |
+
'default_allow' => true, // if a role is not specifically defined in the settings, should the default be to ALLOW the route or not?
|
314 |
+
'roles' => array(), // array of the user roles in this install of wordpress
|
315 |
+
);
|
316 |
+
|
317 |
+
// Default list of allowed routes. By default, nothing is allowed because we're checking for our pre-v1.6 option here for migration purposes
|
318 |
+
$pre_1_6_allowed_routes = get_option( 'DRA_route_whitelist', array() );
|
319 |
+
|
320 |
+
// Decode the html encoding before passing to the function that builds the new routes. They'll get re-encoded later
|
321 |
+
$pre_1_6_allowed_routes = array_map( 'html_entity_decode', $pre_1_6_allowed_routes );
|
322 |
+
|
323 |
+
// Build the rules for this role based on the merge with the previously allowed rules (if any)
|
324 |
+
$new_unauthenticated_rules = DRA_Helpers::build_routes_rule( $pre_1_6_allowed_routes );
|
325 |
+
|
326 |
+
// Define the "unauthenticated" rules based on the old option value (or default value of "nothing")
|
327 |
+
$arr_option['roles']['none'] = array(
|
328 |
+
'default_allow' => false,
|
329 |
+
'allow_list' => $new_unauthenticated_rules,
|
330 |
+
);
|
331 |
+
|
332 |
+
// Save new option
|
333 |
+
update_option( 'disable_rest_api_options', $arr_option );
|
334 |
+
|
335 |
+
// delete the old option if applicable
|
336 |
+
if ( ! empty( $pre_1_6_allowed_routes ) ) {
|
337 |
+
delete_option( 'DRA_route_whitelist' );
|
338 |
+
}
|
339 |
+
|
340 |
+
}
|
341 |
+
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Return array with list of roles the current user belongs to
|
345 |
+
*
|
346 |
+
* @return array
|
347 |
+
*/
|
348 |
+
private function get_current_user_roles() {
|
349 |
+
if ( ! is_user_logged_in() ) {
|
350 |
+
return array(
|
351 |
+
'name' => 'none',
|
352 |
+
);
|
353 |
+
}
|
354 |
+
|
355 |
+
$user = wp_get_current_user();
|
356 |
+
return ( array ) $user->roles;
|
357 |
+
|
358 |
+
}
|
359 |
+
|
360 |
}
|
classes/helpers.php
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class DRA_Helpers {
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Make sure this is called after wp-settings.php is loaded, or the `rest_get_server()` will throw 500's
|
6 |
+
*
|
7 |
+
* @return array
|
8 |
+
*/
|
9 |
+
static function get_all_rest_routes() {
|
10 |
+
$wp_rest_server = rest_get_server();
|
11 |
+
return array_keys( $wp_rest_server->get_routes() );
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Make sure this is called after wp-settings.php is loaded, or the `rest_get_server()` will throw 500's
|
17 |
+
*
|
18 |
+
* @return string[]
|
19 |
+
*/
|
20 |
+
static function get_all_rest_namespaces() {
|
21 |
+
$wp_rest_server = rest_get_server();
|
22 |
+
return $wp_rest_server->get_namespaces();
|
23 |
+
}
|
24 |
+
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Make sure this is called after wp-settings.php is loaded, or the `self::get_all_rest_routes()` will throw 500's
|
28 |
+
*
|
29 |
+
* @param $allowed_routes
|
30 |
+
*
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
static function build_routes_rule( $allowed_routes ) {
|
34 |
+
|
35 |
+
// The full list of all routes in the system
|
36 |
+
$all_routes = self::get_all_rest_routes();
|
37 |
+
|
38 |
+
// Initialize our new rules
|
39 |
+
$new_rules = array();
|
40 |
+
|
41 |
+
// Loop through ALL routes, find out if any exist in the previously-existing rules. If so, they SHOULD be allowed. Default for everyone is false
|
42 |
+
foreach ( $all_routes as $route ) {
|
43 |
+
$new_value = false;
|
44 |
+
if ( ! empty( $allowed_routes ) && in_array( $route, $allowed_routes ) ) {
|
45 |
+
$new_value = true;
|
46 |
+
}
|
47 |
+
$new_rules[esc_html($route)] = $new_value;
|
48 |
+
}
|
49 |
+
|
50 |
+
// Return full list of all known routes, with true/false values for whether they are allowed
|
51 |
+
return $new_rules;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Make sure this is called after wp-settings.php is loaded, or the `self::get_all_rest_routes()` will throw 500's
|
57 |
+
*
|
58 |
+
* @param bool $default_value
|
59 |
+
*
|
60 |
+
* @return array
|
61 |
+
*/
|
62 |
+
static function build_routes_rule_for_all( $default_value = true ) {
|
63 |
+
// The full list of all routes in the system
|
64 |
+
$all_routes = self::get_all_rest_routes();
|
65 |
+
|
66 |
+
// Initialize our new rules
|
67 |
+
$new_rules = array();
|
68 |
+
|
69 |
+
// Loop through ALL routes, set all to the desired value
|
70 |
+
foreach ( $all_routes as $route ) {
|
71 |
+
$new_rules[esc_html($route)] = $default_value;
|
72 |
+
}
|
73 |
+
|
74 |
+
// Return full list of all known routes with values defined
|
75 |
+
return $new_rules;
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Confirms if the passed value is either 'none' or another role defined in the system
|
81 |
+
*
|
82 |
+
* @param $role
|
83 |
+
*
|
84 |
+
* @return bool
|
85 |
+
*/
|
86 |
+
static function is_valid_role( $role ) {
|
87 |
+
|
88 |
+
// If we requested 'none', we know it's okay
|
89 |
+
if ( 'none' == $role ) {
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
|
93 |
+
// Get all roles from the system. Loop through and see if one of them is the one we're asking about
|
94 |
+
$editable_roles = get_editable_roles();
|
95 |
+
foreach ( $editable_roles as $editable_role => $details ) {
|
96 |
+
if ( $role == $editable_role ) {
|
97 |
+
return true;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
// If we got here, we're trying to ask for an invalid user role
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Check the WP Option for our stored values of which routes should be allowed based on the supplied role
|
108 |
+
*
|
109 |
+
* @param $role
|
110 |
+
* @param bool $get_allowed
|
111 |
+
*
|
112 |
+
* @return array
|
113 |
+
*/
|
114 |
+
static function get_allowed_routes( $role, $get_allowed = true ) {
|
115 |
+
$arr_option = get_option( 'disable_rest_api_options', array() );
|
116 |
+
|
117 |
+
// If we have an empty array, just return that
|
118 |
+
if ( empty( $arr_option ) ) {
|
119 |
+
return $arr_option;
|
120 |
+
}
|
121 |
+
|
122 |
+
$option_rules = array();
|
123 |
+
$allowed_rules = array();
|
124 |
+
|
125 |
+
if ( 'none' == $role && ! isset( $arr_option['roles']['none'] ) ) {
|
126 |
+
|
127 |
+
// This helps us bridge the gap from plugin version <=1.5.1 to >=1.6.
|
128 |
+
// We didn't use to store results based on role, but we want to return the values for "unauthenticated users" if we have recently upgraded
|
129 |
+
$option_rules = ( array ) DRA_Helpers::build_routes_rule( $arr_option );
|
130 |
+
|
131 |
+
} elseif ( isset( $arr_option['roles'][$role]['allow_list'] ) ) {
|
132 |
+
|
133 |
+
// If we have a definition for the currently requested role, return it
|
134 |
+
$option_rules = ( array ) $arr_option['roles'][$role]['allow_list'];
|
135 |
+
|
136 |
+
} else {
|
137 |
+
|
138 |
+
// If we failed all the way down to here, return a default array since we're asking for a role we don't have a definition for yet
|
139 |
+
$option_rules = ( array ) DRA_Helpers::build_routes_rule_for_all( true );
|
140 |
+
|
141 |
+
}
|
142 |
+
|
143 |
+
// Loop through and only save the keys that have a value pairing of true
|
144 |
+
foreach ( $option_rules as $key => $value ) {
|
145 |
+
if ( $get_allowed === $value ) {
|
146 |
+
$allowed_rules[] = $key;
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
// Get rid of < and > before doing our comparisons
|
151 |
+
$allowed_rules = array_map( 'htmlspecialchars_decode', $allowed_rules );
|
152 |
+
|
153 |
+
// Return our array of allowed rules
|
154 |
+
return $allowed_rules;
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Return the setting for what the default route behavior is for a specified role
|
161 |
+
*
|
162 |
+
* @param $role
|
163 |
+
*
|
164 |
+
* @return bool
|
165 |
+
*/
|
166 |
+
static function get_default_allow_for_role( $role ) {
|
167 |
+
$arr_option = get_option( 'disable_rest_api_options', array() );
|
168 |
+
|
169 |
+
// If we have an empty array, return false so we deny access
|
170 |
+
if ( empty( $arr_option ) ) {
|
171 |
+
return false;
|
172 |
+
}
|
173 |
+
|
174 |
+
// Unauthorized users default to DONT ALLOW, authorized users default to DO ALLOW
|
175 |
+
$default_allow = ( 'none' == $role ) ? false : true;
|
176 |
+
|
177 |
+
if ( isset( $arr_option['roles'][$role]['default_allow'] ) ) {
|
178 |
+
$default_allow = $arr_option['roles'][$role]['default_allow'];
|
179 |
+
}
|
180 |
+
|
181 |
+
// Return our default rule
|
182 |
+
return ( bool ) $default_allow;
|
183 |
+
|
184 |
+
}
|
185 |
+
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Returns the translated name of the role based on provided role slug
|
189 |
+
*
|
190 |
+
* @param $role
|
191 |
+
*
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
+
static function get_role_name( $role ) {
|
195 |
+
|
196 |
+
if ( 'none' == $role ) {
|
197 |
+
return __( 'Unauthenticated', 'disable-json-api' );
|
198 |
+
}
|
199 |
+
|
200 |
+
$editable_roles = get_editable_roles();
|
201 |
+
if ( isset( $editable_roles[$role] ) ) {
|
202 |
+
return translate_user_role( $editable_roles[$role]['name'] );
|
203 |
+
}
|
204 |
+
|
205 |
+
return '';
|
206 |
+
|
207 |
+
}
|
208 |
+
|
209 |
+
}
|
classes/requirements-check.php
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
*
|
7 |
*/
|
8 |
|
9 |
-
class
|
10 |
private $title = '';
|
11 |
private $php = '5.2.4';
|
12 |
private $wp = '3.8';
|
@@ -71,4 +71,4 @@ class Disable_REST_API_Requirements_Check {
|
|
71 |
echo "<p>The “" . esc_html( $this->title ) . "” plugin cannot run on WordPress versions older than " . $this->wp . '. Please update WordPress.</p>';
|
72 |
echo '</div>';
|
73 |
}
|
74 |
-
}
|
6 |
*
|
7 |
*/
|
8 |
|
9 |
+
class DRA_Requirements_Check {
|
10 |
private $title = '';
|
11 |
private $php = '5.2.4';
|
12 |
private $wp = '3.8';
|
71 |
echo "<p>The “" . esc_html( $this->title ) . "” plugin cannot run on WordPress versions older than " . $this->wp . '. Please update WordPress.</p>';
|
72 |
echo '</div>';
|
73 |
}
|
74 |
+
}
|
css/admin.css
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
h2 { display: inline; }
|
2 |
+
#route-container ul li { padding-left: 20px; }
|
3 |
+
#route-container em { font-size: 0.8em; }
|
4 |
+
.switch { position: relative; display: inline-block; width: 38px; height: 20px; margin-right: 0.4em; }
|
5 |
+
.switch input { opacity: 0; width: 0; height: 0; }
|
6 |
+
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: .4s; transition: .4s; border-radius: 18px; display:inline; }
|
7 |
+
.slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 4px; bottom: 3px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 50%; }
|
8 |
+
input:checked + .slider { background-color: #2196F3; }
|
9 |
+
input:focus + .slider { box-shadow: 0 0 1px #2196F3; }
|
10 |
+
input:checked + .slider:before { -webkit-transform: translateX(16px); -ms-transform: translateX(16px); transform: translateX(16px); }
|
11 |
+
div#select-container, div#default-allow-container, div#route-container { padding: 1em 0 1em 0; }
|
12 |
+
div#route-container { display: none; }
|
13 |
+
input#dra-reset-button { display: none; }
|
disable-json-api.php
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
/**
|
3 |
* Plugin Name: Disable REST API
|
4 |
* Plugin URI: http://www.binarytemplar.com/disable-json-api
|
5 |
-
* Description: Disable the use of the REST API on your website to anonymous users
|
6 |
-
* Version: 1.
|
7 |
* Author: Dave McHale
|
8 |
* Author URI: http://www.binarytemplar.com
|
9 |
* Text Domain: disable-json-api
|
@@ -25,7 +25,7 @@ function disable_rest_api_load_textdomain() {
|
|
25 |
// Requirements check, to cleanly handle failure of WP/PHP version requirements
|
26 |
include( dirname( __FILE__ ) . '/classes/requirements-check.php' );
|
27 |
|
28 |
-
$dra_requirements_check = new
|
29 |
'title' => 'Disable REST API',
|
30 |
'php' => '5.3',
|
31 |
'wp' => '4.4',
|
@@ -43,8 +43,19 @@ if ( $dra_requirements_check->passes() ) {
|
|
43 |
// WordPress 4.7+ disables the REST API via authentication short-circuit.
|
44 |
// For versions of WordPress < 4.7, disable the REST API via filters
|
45 |
if ( version_compare( get_bloginfo( 'version' ), '4.7', '>=' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
require_once( plugin_dir_path( __FILE__ ) . 'classes/disable-rest-api.php' );
|
47 |
new Disable_REST_API( __FILE__ );
|
|
|
48 |
} else {
|
49 |
require_once( plugin_dir_path( __FILE__ ) . 'functions/legacy.php' );
|
50 |
DRA_Disable_Via_Filters();
|
2 |
/**
|
3 |
* Plugin Name: Disable REST API
|
4 |
* Plugin URI: http://www.binarytemplar.com/disable-json-api
|
5 |
+
* Description: Disable the use of the REST API on your website to anonymous users. You can optionally enable select endpoints if you wish. Now with support for User Roles!
|
6 |
+
* Version: 1.6
|
7 |
* Author: Dave McHale
|
8 |
* Author URI: http://www.binarytemplar.com
|
9 |
* Text Domain: disable-json-api
|
25 |
// Requirements check, to cleanly handle failure of WP/PHP version requirements
|
26 |
include( dirname( __FILE__ ) . '/classes/requirements-check.php' );
|
27 |
|
28 |
+
$dra_requirements_check = new DRA_Requirements_Check( array(
|
29 |
'title' => 'Disable REST API',
|
30 |
'php' => '5.3',
|
31 |
'wp' => '4.4',
|
43 |
// WordPress 4.7+ disables the REST API via authentication short-circuit.
|
44 |
// For versions of WordPress < 4.7, disable the REST API via filters
|
45 |
if ( version_compare( get_bloginfo( 'version' ), '4.7', '>=' ) ) {
|
46 |
+
|
47 |
+
// Load in extra classes
|
48 |
+
require_once( plugin_dir_path( __FILE__ ) . 'classes/helpers.php' );
|
49 |
+
|
50 |
+
// Only load admin classes if in admin area
|
51 |
+
if ( is_admin() ) {
|
52 |
+
require_once( plugin_dir_path( __FILE__ ) . 'classes/admin.php' );
|
53 |
+
}
|
54 |
+
|
55 |
+
// Load the primary Disable_REST_API class
|
56 |
require_once( plugin_dir_path( __FILE__ ) . 'classes/disable-rest-api.php' );
|
57 |
new Disable_REST_API( __FILE__ );
|
58 |
+
|
59 |
} else {
|
60 |
require_once( plugin_dir_path( __FILE__ ) . 'functions/legacy.php' );
|
61 |
DRA_Disable_Via_Filters();
|
js/admin-footer.js
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function maybe_show_dra_routes() {
|
2 |
+
let manage = jQuery('input[name=default_allow]:checked').val().toString();
|
3 |
+
if ( '0' === manage ) {
|
4 |
+
jQuery('div#route-container, input#dra-reset-button').css( 'display', 'block' );
|
5 |
+
} else {
|
6 |
+
jQuery('div#route-container, input#dra-reset-button').css( 'display', 'none' );
|
7 |
+
}
|
8 |
+
}
|
9 |
+
|
10 |
+
jQuery( function() {
|
11 |
+
|
12 |
+
maybe_show_dra_routes();
|
13 |
+
|
14 |
+
jQuery('select#dra-role').change( function() {
|
15 |
+
window.location.href = window.location.origin + window.location.pathname + '?page=disable_rest_api_settings&role=' + jQuery(this).val();
|
16 |
+
});
|
17 |
+
|
18 |
+
jQuery('input[name=default_allow]').change( function() {
|
19 |
+
maybe_show_dra_routes();
|
20 |
+
});
|
21 |
+
|
22 |
+
});
|
js/admin-header.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function dra_namespace_click(namespace, id) {
|
2 |
+
if (jQuery('#dra_namespace_' + id).is(":checked")) {
|
3 |
+
jQuery("#route-container input[data-namespace='" + namespace + "']").prop('checked', true);
|
4 |
+
} else {
|
5 |
+
jQuery("#route-container input[data-namespace='" + namespace + "']").prop('checked', false);
|
6 |
+
}
|
7 |
+
}
|
readme.txt
CHANGED
@@ -3,24 +3,24 @@ Contributors: dmchale, tangrufus
|
|
3 |
Tags: admin, api, json, REST, rest-api, disable
|
4 |
Requires at least: 4.4
|
5 |
Requires PHP: 5.6
|
6 |
-
Tested up to: 5.
|
7 |
-
Stable tag: 1.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
-
Disable the use of the REST API on your website to
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
The most comprehensive plugin for controlling access to the WordPress REST API!
|
16 |
|
17 |
-
Works as a "set it and forget it" install. Just upload and activate, and the entire REST API will be inaccessible to your
|
18 |
|
19 |
-
|
20 |
|
21 |
-
|
22 |
|
23 |
-
For
|
24 |
|
25 |
== Installation ==
|
26 |
|
@@ -34,18 +34,23 @@ For WordPress versions 4.4, 4.5 and 4.6, this plugin makes use of the `rest_enab
|
|
34 |
|
35 |
While logged into WordPress as any user, the REST API will function as intended. Because of this, you must use a new browser - or Chrome's incognito mode - to test your website with a clean session. Go to yourdomain.com/wp-json/ (or yourdomain.com/?rest_route=/ if you have pretty permalinks disabled) while NOT LOGGED IN to test the results. You will see an authentication error returned if the plugin is active. "DRA: Only authenticated users can access the REST API."
|
36 |
|
37 |
-
= Does this plugin disable
|
38 |
|
39 |
-
This plugin is ONLY meant to disable endpoints accessible via the
|
40 |
|
41 |
== Screenshots ==
|
42 |
|
43 |
1. The JSON returned by a website with the API disabled via filters (WP versions 4.4, 4.5, 4.6)
|
44 |
2. The JSON returned by a website with the API disabled via authentication methods (WP versions 4.7+)
|
45 |
-
3. The Settings page lets you selectively whitelist endpoints registered with the REST API.
|
46 |
|
47 |
== Changelog ==
|
48 |
|
|
|
|
|
|
|
|
|
|
|
49 |
= 1.5.1 =
|
50 |
* Tested up to WP v5.5
|
51 |
|
@@ -88,6 +93,9 @@ This plugin is ONLY meant to disable endpoints accessible via the default REST A
|
|
88 |
|
89 |
== Upgrade Notice ==
|
90 |
|
|
|
|
|
|
|
91 |
= 1.4 =
|
92 |
* Adds support to optionally whitelist individual routes of the REST API via Settings page.
|
93 |
|
3 |
Tags: admin, api, json, REST, rest-api, disable
|
4 |
Requires at least: 4.4
|
5 |
Requires PHP: 5.6
|
6 |
+
Tested up to: 5.6
|
7 |
+
Stable tag: 1.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
+
Disable the use of the REST API on your website to site users. Now with User Role support!
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
The most comprehensive plugin for controlling access to the WordPress REST API!
|
16 |
|
17 |
+
Works as a "set it and forget it" install. Just upload and activate, and the entire REST API will be inaccessible to your general site visitors.
|
18 |
|
19 |
+
But if you do need to grant access to some endpoints, you can do that too. Go to the Settings page and you can quickly whitelist individual endpoints (or entire branches of endpoints) in the REST API.
|
20 |
|
21 |
+
You can even do this on a per-user-role basis, so your unauthenticated users have one set of rules while WooCommerce customers have another while Subscribers and Editors and Admins all have their own. NOTE: Out of the box, all defined user roles will still be granted full access to the REST API until you choose to manage those settings.
|
22 |
|
23 |
+
For most versions of WordPress, this plugin will return an authentication error if a user is not allowed to access an endpoint. For legacy support, WordPress 4.4, 4.5, and 4.6 use the provided `rest_enabled` filter to disable the entire REST API.
|
24 |
|
25 |
== Installation ==
|
26 |
|
34 |
|
35 |
While logged into WordPress as any user, the REST API will function as intended. Because of this, you must use a new browser - or Chrome's incognito mode - to test your website with a clean session. Go to yourdomain.com/wp-json/ (or yourdomain.com/?rest_route=/ if you have pretty permalinks disabled) while NOT LOGGED IN to test the results. You will see an authentication error returned if the plugin is active. "DRA: Only authenticated users can access the REST API."
|
36 |
|
37 |
+
= Does this plugin disable every REST API that is installed on my site? =
|
38 |
|
39 |
+
This plugin is ONLY meant to disable endpoints accessible via the core REST API that is part of WordPress itself. If a plugin or theme has implemented their own REST API (not to be confused with implementing their own endpoints within the WordPress API) this plugin will have no effect.
|
40 |
|
41 |
== Screenshots ==
|
42 |
|
43 |
1. The JSON returned by a website with the API disabled via filters (WP versions 4.4, 4.5, 4.6)
|
44 |
2. The JSON returned by a website with the API disabled via authentication methods (WP versions 4.7+)
|
45 |
+
3. The Settings page lets you selectively whitelist endpoints registered with the REST API, on a per-user-role basis.
|
46 |
|
47 |
== Changelog ==
|
48 |
|
49 |
+
= 1.6 =
|
50 |
+
* Tested up to WP v5.6
|
51 |
+
* Added support for managing endpoint access on a per-user-role basis
|
52 |
+
* Soooooooo many small changes behind the scenes to support the above
|
53 |
+
|
54 |
= 1.5.1 =
|
55 |
* Tested up to WP v5.5
|
56 |
|
93 |
|
94 |
== Upgrade Notice ==
|
95 |
|
96 |
+
= 1.6 =
|
97 |
+
* By popular request... now with User Role support!
|
98 |
+
|
99 |
= 1.4 =
|
100 |
* Adds support to optionally whitelist individual routes of the REST API via Settings page.
|
101 |
|
uninstall.php
CHANGED
@@ -10,9 +10,4 @@ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
|
10 |
die;
|
11 |
}
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
delete_option( $option_name );
|
16 |
-
|
17 |
-
// for site options in Multisite
|
18 |
-
delete_site_option( $option_name );
|
10 |
die;
|
11 |
}
|
12 |
|
13 |
+
delete_option( 'disable_rest_api_options' );
|
|
|
|
|
|
|
|
|
|