diff --git a/src/wp-includes/class-wp-oembed-controller.php b/src/wp-includes/class-wp-oembed-controller.php
index 3ab621408e..912e2d131b 100644
--- a/src/wp-includes/class-wp-oembed-controller.php
+++ b/src/wp-includes/class-wp-oembed-controller.php
@@ -36,9 +36,10 @@ final class WP_oEmbed_Controller {
'/embed',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_item' ),
- 'args' => array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_item' ),
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'url' => array(
'description' => __( 'The URL of the resource for which to fetch oEmbed data.' ),
'required' => true,
diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
index d3bb80a3d6..e9a5799b60 100644
--- a/src/wp-includes/rest-api.php
+++ b/src/wp-includes/rest-api.php
@@ -88,6 +88,20 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
$arg_group = array_merge( $defaults, $arg_group );
$arg_group['args'] = array_merge( $common_args, $arg_group['args'] );
+
+ if ( ! isset( $arg_group['permission_callback'] ) ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1. The REST API route being registered. 2. The argument name. 3. The suggested function name. */
+ __( 'The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.', 'LION' ),
+ '' . $clean_namespace . '/' . trim( $route, '/' ) . '
',
+ 'permission_callback
',
+ '__return_true
'
+ ),
+ '5.5.0'
+ );
+ }
}
$full_route = '/' . $clean_namespace . '/' . trim( $route, '/' );
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
index fd9759d79e..938697157b 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
@@ -60,9 +60,10 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
),
),
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_item' ),
- 'args' => array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_item' ),
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
),
),
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
index 88d233d4af..2320668222 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
@@ -116,9 +116,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
'/' . $this->rest_base . '/me',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_current_item' ),
- 'args' => array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'permission_callback' => '__return_true',
+ 'callback' => array( $this, 'get_current_item' ),
+ 'args' => array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
),
),
diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php
index 789c4e19b3..123e872f07 100644
--- a/tests/phpunit/tests/rest-api.php
+++ b/tests/phpunit/tests/rest-api.php
@@ -84,8 +84,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -120,12 +121,14 @@ class Tests_REST_API extends WP_UnitTestCase {
'/test',
array(
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
),
array(
- 'methods' => array( 'POST' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
),
)
);
@@ -160,16 +163,18 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
register_rest_route(
'test-ns',
'/test',
array(
- 'methods' => array( 'POST' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -187,18 +192,20 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'should_exist' => false,
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => false,
)
);
register_rest_route(
'test-ns',
'/test',
array(
- 'methods' => array( 'POST' ),
- 'callback' => '__return_null',
- 'should_exist' => true,
+ 'methods' => array( 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => true,
),
true
);
@@ -223,8 +230,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'',
'/test-empty-namespace',
array(
- 'methods' => array( 'POST' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
),
true
);
@@ -242,8 +250,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'/test-empty-route',
'',
array(
- 'methods' => array( 'POST' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
),
true
);
@@ -264,8 +273,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -282,8 +292,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET',
- 'callback' => '__return_null',
+ 'methods' => 'GET',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -300,8 +311,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET', 'POST' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET', 'POST' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -324,8 +336,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET,POST',
- 'callback' => '__return_null',
+ 'methods' => 'GET,POST',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -345,8 +358,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET,POST',
- 'callback' => '__return_null',
+ 'methods' => 'GET,POST',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -367,8 +381,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET,POST',
- 'callback' => '__return_true',
+ 'methods' => 'GET,POST',
+ 'callback' => '__return_true',
+ 'permission_callback' => '__return_true',
)
);
@@ -910,8 +925,9 @@ class Tests_REST_API extends WP_UnitTestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
)
);
@@ -996,7 +1012,8 @@ class Tests_REST_API extends WP_UnitTestCase {
'/my-namespace/v1/',
'/my-route',
array(
- 'callback' => '__return_true',
+ 'callback' => '__return_true',
+ 'permission_callback' => '__return_true',
)
);
@@ -1006,6 +1023,66 @@ class Tests_REST_API extends WP_UnitTestCase {
$this->assertTrue( rest_do_request( '/my-namespace/v1/my-route' )->get_data() );
}
+ /**
+ * @ticket 50075
+ */
+ public function test_register_route_with_missing_permission_callback_top_level_route() {
+ $this->setExpectedIncorrectUsage( 'register_rest_route' );
+
+ $registered = register_rest_route(
+ 'my-ns/v1',
+ '/my-route',
+ array(
+ 'callback' => '__return_true',
+ )
+ );
+
+ $this->assertTrue( $registered );
+ }
+
+ /**
+ * @ticket 50075
+ */
+ public function test_register_route_with_missing_permission_callback_single_wrapped_route() {
+ $this->setExpectedIncorrectUsage( 'register_rest_route' );
+
+ $registered = register_rest_route(
+ 'my-ns/v1',
+ '/my-route',
+ array(
+ array(
+ 'callback' => '__return_true',
+ ),
+ )
+ );
+
+ $this->assertTrue( $registered );
+ }
+
+
+ /**
+ * @ticket 50075
+ */
+ public function test_register_route_with_missing_permission_callback_multiple_wrapped_route() {
+ $this->setExpectedIncorrectUsage( 'register_rest_route' );
+
+ $registered = register_rest_route(
+ 'my-ns/v1',
+ '/my-route',
+ array(
+ array(
+ 'callback' => '__return_true',
+ ),
+ array(
+ 'callback' => '__return_true',
+ 'permission_callback' => '__return_true',
+ ),
+ )
+ );
+
+ $this->assertTrue( $registered );
+ }
+
public function _dp_rest_filter_response_by_context() {
return array(
'default' => array(
diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php
index 8f178bff2b..5870e8cb07 100644
--- a/tests/phpunit/tests/rest-api/rest-server.php
+++ b/tests/phpunit/tests/rest-api/rest-server.php
@@ -66,9 +66,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'args' => array(
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'foo' => array(
'default' => 'bar',
),
@@ -88,9 +89,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'args' => array(
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'foo' => array(
'default' => 'bar',
),
@@ -110,9 +112,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'optional',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'args' => array(
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'foo' => array(),
),
)
@@ -131,9 +134,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'no-zero',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'args' => array(
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'foo' => array(
'default' => 'bar',
),
@@ -150,8 +154,9 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'head-request',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_true',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_true',
+ 'permission_callback' => '__return_true',
)
);
$request = new WP_REST_Request( 'HEAD', '/head-request/test' );
@@ -171,8 +176,9 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'/test',
array(
array(
- 'methods' => array( 'HEAD' ),
- 'callback' => '__return_true',
+ 'methods' => array( 'HEAD' ),
+ 'callback' => '__return_true',
+ 'permission_callback' => '__return_true',
),
array(
'methods' => array( 'GET' ),
@@ -193,9 +199,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'/test/(?P.*)',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => '__return_false',
- 'args' => array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => '__return_false',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'data' => array(),
),
),
@@ -266,9 +273,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET',
- 'callback' => '__return_null',
- 'should_exist' => false,
+ 'methods' => 'GET',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => false,
)
);
@@ -293,9 +301,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => 'GET',
- 'callback' => '__return_null',
- 'should_exist' => false,
+ 'methods' => 'GET',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => false,
)
);
@@ -303,9 +312,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => 'POST',
- 'callback' => '__return_null',
- 'should_exist' => false,
+ 'methods' => 'POST',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => false,
)
);
@@ -342,9 +352,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => 'POST',
- 'callback' => '__return_null',
- 'should_exist' => false,
+ 'methods' => 'POST',
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'should_exist' => false,
)
);
@@ -365,8 +376,9 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'/test',
array(
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
),
array(
'methods' => array( 'POST' ),
@@ -1327,9 +1339,10 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => '__return_null',
- 'args' => array(
+ 'methods' => array( 'GET' ),
+ 'callback' => '__return_null',
+ 'permission_callback' => '__return_true',
+ 'args' => array(
'someinteger' => array(
'validate_callback' => array( $this, '_validate_as_integer_123' ),
'sanitize_callback' => 'absint',
@@ -1362,10 +1375,11 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => function () {
+ 'methods' => array( 'GET' ),
+ 'callback' => function () {
return new WP_REST_Response();
},
+ 'permission_callback' => '__return_true',
)
);
@@ -1383,10 +1397,11 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => function () {
+ 'methods' => array( 'GET' ),
+ 'callback' => function () {
return new WP_REST_Response( 'data', 204 );
},
+ 'permission_callback' => '__return_true',
)
);
@@ -1473,20 +1488,22 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
'test-ns',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => function() {
+ 'methods' => array( 'GET' ),
+ 'callback' => function() {
return new WP_REST_Response( 'data', 204 );
},
+ 'permission_callback' => '__return_true',
)
);
register_rest_route(
'test-ns/v1',
'/test',
array(
- 'methods' => array( 'GET' ),
- 'callback' => function() {
+ 'methods' => array( 'GET' ),
+ 'callback' => function() {
return new WP_REST_Response( 'data', 204 );
},
+ 'permission_callback' => '__return_true',
)
);