REST API: Improve validation for usernames and passwords.
Also improves the slashing of user data in the REST API to avoid data loss. Props jnylen0. Fixes #38739. git-svn-id: https://develop.svn.wordpress.org/trunk@39219 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
47a04c044d
commit
ecb1e33d0d
|
@ -417,7 +417,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
$ret = wpmu_validate_user_signup( $user->user_login, $user->user_email );
|
$ret = wpmu_validate_user_signup( $user->user_login, $user->user_email );
|
||||||
|
|
||||||
if ( is_wp_error( $ret['errors'] ) && ! empty( $ret['errors']->errors ) ) {
|
if ( is_wp_error( $ret['errors'] ) && ! empty( $ret['errors']->errors ) ) {
|
||||||
return $ret['errors'];
|
$error = new WP_Error( 'rest_invalid_param', __( 'Invalid user parameter(s).' ), array( 'status' => 400 ) );
|
||||||
|
foreach ( $ret['errors']->errors as $code => $messages ) {
|
||||||
|
foreach ( $messages as $message ) {
|
||||||
|
$error->add( $code, $message );
|
||||||
|
}
|
||||||
|
if ( $error_data = $error->get_error_data( $code ) ) {
|
||||||
|
$error->add_data( $error_data, $code );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +438,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->ID = $user_id;
|
$user->ID = $user_id;
|
||||||
$user_id = wp_update_user( $user );
|
$user_id = wp_update_user( wp_slash( (array) $user ) );
|
||||||
|
|
||||||
if ( is_wp_error( $user_id ) ) {
|
if ( is_wp_error( $user_id ) ) {
|
||||||
return $user_id;
|
return $user_id;
|
||||||
|
@ -437,7 +446,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
|
|
||||||
add_user_to_blog( get_site()->id, $user_id, '' );
|
add_user_to_blog( get_site()->id, $user_id, '' );
|
||||||
} else {
|
} else {
|
||||||
$user_id = wp_insert_user( $user );
|
$user_id = wp_insert_user( wp_slash( (array) $user ) );
|
||||||
|
|
||||||
if ( is_wp_error( $user_id ) ) {
|
if ( is_wp_error( $user_id ) ) {
|
||||||
return $user_id;
|
return $user_id;
|
||||||
|
@ -552,7 +561,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
// Ensure we're operating on the same user we already checked.
|
// Ensure we're operating on the same user we already checked.
|
||||||
$user->ID = $id;
|
$user->ID = $id;
|
||||||
|
|
||||||
$user_id = wp_update_user( $user );
|
$user_id = wp_update_user( wp_slash( (array) $user ) );
|
||||||
|
|
||||||
if ( is_wp_error( $user_id ) ) {
|
if ( is_wp_error( $user_id ) ) {
|
||||||
return $user_id;
|
return $user_id;
|
||||||
|
@ -996,6 +1005,61 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a username for the REST API.
|
||||||
|
*
|
||||||
|
* Performs a couple of checks like edit_user() in wp-admin/includes/user.php.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param mixed $value The username submitted in the request.
|
||||||
|
* @param WP_REST_Request $request Full details about the request.
|
||||||
|
* @param string $param The parameter name.
|
||||||
|
* @return WP_Error|string The sanitized username, if valid, otherwise an error.
|
||||||
|
*/
|
||||||
|
public function check_username( $value, $request, $param ) {
|
||||||
|
$username = (string) rest_sanitize_value_from_schema( $value, $request, $param );
|
||||||
|
|
||||||
|
if ( ! validate_username( $username ) ) {
|
||||||
|
return new WP_Error( 'rest_user_invalid_username', __( 'Username contains invalid characters.' ), array( 'status' => 400 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This filter is documented in wp-includes/user.php */
|
||||||
|
$illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );
|
||||||
|
|
||||||
|
if ( in_array( strtolower( $username ), array_map( 'strtolower', $illegal_logins ) ) ) {
|
||||||
|
return new WP_Error( 'rest_user_invalid_username', __( 'Sorry, that username is not allowed.' ), array( 'status' => 400 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a user password for the REST API.
|
||||||
|
*
|
||||||
|
* Performs a couple of checks like edit_user() in wp-admin/includes/user.php.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param mixed $value The password submitted in the request.
|
||||||
|
* @param WP_REST_Request $request Full details about the request.
|
||||||
|
* @param string $param The parameter name.
|
||||||
|
* @return WP_Error|string The sanitized password, if valid, otherwise an error.
|
||||||
|
*/
|
||||||
|
public function check_user_password( $value, $request, $param ) {
|
||||||
|
$password = (string) rest_sanitize_value_from_schema( $value, $request, $param );
|
||||||
|
|
||||||
|
if ( empty( $password ) ) {
|
||||||
|
return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot be empty.' ), array( 'status' => 400 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( false !== strpos( $password, "\\" ) ) {
|
||||||
|
return new WP_Error( 'rest_user_invalid_password', __( 'Passwords cannot contain the "\\" character.' ), array( 'status' => 400 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $password;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the user's schema, conforming to JSON Schema.
|
* Retrieves the user's schema, conforming to JSON Schema.
|
||||||
*
|
*
|
||||||
|
@ -1022,7 +1086,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
'context' => array( 'edit' ),
|
'context' => array( 'edit' ),
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'arg_options' => array(
|
'arg_options' => array(
|
||||||
'sanitize_callback' => 'sanitize_user',
|
'sanitize_callback' => array( $this, 'check_username' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'name' => array(
|
'name' => array(
|
||||||
|
@ -1066,9 +1130,6 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
'description' => __( 'Description of the resource.' ),
|
'description' => __( 'Description of the resource.' ),
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'context' => array( 'embed', 'view', 'edit' ),
|
'context' => array( 'embed', 'view', 'edit' ),
|
||||||
'arg_options' => array(
|
|
||||||
'sanitize_callback' => 'wp_filter_post_kses',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
'link' => array(
|
'link' => array(
|
||||||
'description' => __( 'Author URL to the resource.' ),
|
'description' => __( 'Author URL to the resource.' ),
|
||||||
|
@ -1119,6 +1180,9 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'context' => array(), // Password is never displayed.
|
'context' => array(), // Password is never displayed.
|
||||||
'required' => true,
|
'required' => true,
|
||||||
|
'arg_options' => array(
|
||||||
|
'sanitize_callback' => array( $this, 'check_user_password' ),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
'capabilities' => array(
|
'capabilities' => array(
|
||||||
'description' => __( 'All capabilities assigned to the resource.' ),
|
'description' => __( 'All capabilities assigned to the resource.' ),
|
||||||
|
|
|
@ -161,3 +161,24 @@ function _upload_dir_https( $uploads ) {
|
||||||
|
|
||||||
return $uploads;
|
return $uploads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip `setcookie` calls in auth_cookie functions due to warning:
|
||||||
|
// Cannot modify header information - headers already sent by ...
|
||||||
|
|
||||||
|
function wp_set_auth_cookie( $user_id, $remember = false, $secure = '', $token = '' ) {
|
||||||
|
$auth_cookie = null;
|
||||||
|
$expire = null;
|
||||||
|
$expiration = null;
|
||||||
|
$user_id = null;
|
||||||
|
$scheme = null;
|
||||||
|
/** This action is documented in wp-inclues/pluggable.php */
|
||||||
|
do_action( 'set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme );
|
||||||
|
$logged_in_cookie = null;
|
||||||
|
/** This action is documented in wp-inclues/pluggable.php */
|
||||||
|
do_action( 'set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in' );
|
||||||
|
}
|
||||||
|
|
||||||
|
function wp_clear_auth_cookie() {
|
||||||
|
/** This action is documented in wp-inclues/pluggable.php */
|
||||||
|
do_action( 'clear_auth_cookie' );
|
||||||
|
}
|
||||||
|
|
|
@ -10,11 +10,16 @@
|
||||||
* @group restapi
|
* @group restapi
|
||||||
*/
|
*/
|
||||||
class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
|
protected static $superadmin;
|
||||||
protected static $user;
|
protected static $user;
|
||||||
protected static $editor;
|
protected static $editor;
|
||||||
protected static $site;
|
protected static $site;
|
||||||
|
|
||||||
public static function wpSetUpBeforeClass( $factory ) {
|
public static function wpSetUpBeforeClass( $factory ) {
|
||||||
|
self::$superadmin = $factory->user->create( array(
|
||||||
|
'role' => 'administrator',
|
||||||
|
'user_login' => 'superadmin',
|
||||||
|
) );
|
||||||
self::$user = $factory->user->create( array(
|
self::$user = $factory->user->create( array(
|
||||||
'role' => 'administrator',
|
'role' => 'administrator',
|
||||||
) );
|
) );
|
||||||
|
@ -25,6 +30,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
|
|
||||||
if ( is_multisite() ) {
|
if ( is_multisite() ) {
|
||||||
self::$site = $factory->blog->create( array( 'domain' => 'rest.wordpress.org', 'path' => '/' ) );
|
self::$site = $factory->blog->create( array( 'domain' => 'rest.wordpress.org', 'path' => '/' ) );
|
||||||
|
update_site_option( 'site_admins', array( 'superadmin' ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,8 +181,8 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
|
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
$headers = $response->get_headers();
|
$headers = $response->get_headers();
|
||||||
$this->assertEquals( 50, $headers['X-WP-Total'] );
|
$this->assertEquals( 51, $headers['X-WP-Total'] );
|
||||||
$this->assertEquals( 5, $headers['X-WP-TotalPages'] );
|
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
||||||
$next_link = add_query_arg( array(
|
$next_link = add_query_arg( array(
|
||||||
'page' => 2,
|
'page' => 2,
|
||||||
), rest_url( 'wp/v2/users' ) );
|
), rest_url( 'wp/v2/users' ) );
|
||||||
|
@ -190,7 +196,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$request->set_param( 'page', 3 );
|
$request->set_param( 'page', 3 );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
$headers = $response->get_headers();
|
$headers = $response->get_headers();
|
||||||
$this->assertEquals( 51, $headers['X-WP-Total'] );
|
$this->assertEquals( 52, $headers['X-WP-Total'] );
|
||||||
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
||||||
$prev_link = add_query_arg( array(
|
$prev_link = add_query_arg( array(
|
||||||
'page' => 2,
|
'page' => 2,
|
||||||
|
@ -205,7 +211,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$request->set_param( 'page', 6 );
|
$request->set_param( 'page', 6 );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
$headers = $response->get_headers();
|
$headers = $response->get_headers();
|
||||||
$this->assertEquals( 51, $headers['X-WP-Total'] );
|
$this->assertEquals( 52, $headers['X-WP-Total'] );
|
||||||
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
||||||
$prev_link = add_query_arg( array(
|
$prev_link = add_query_arg( array(
|
||||||
'page' => 5,
|
'page' => 5,
|
||||||
|
@ -217,7 +223,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$request->set_param( 'page', 8 );
|
$request->set_param( 'page', 8 );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
$headers = $response->get_headers();
|
$headers = $response->get_headers();
|
||||||
$this->assertEquals( 51, $headers['X-WP-Total'] );
|
$this->assertEquals( 52, $headers['X-WP-Total'] );
|
||||||
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
|
||||||
$prev_link = add_query_arg( array(
|
$prev_link = add_query_arg( array(
|
||||||
'page' => 6,
|
'page' => 6,
|
||||||
|
@ -393,7 +399,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
|
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
|
||||||
$request->set_param( 'offset', 1 );
|
$request->set_param( 'offset', 1 );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
$this->assertCount( 3, $response->get_data() );
|
$this->assertCount( 4, $response->get_data() );
|
||||||
// 'offset' works with 'per_page'
|
// 'offset' works with 'per_page'
|
||||||
$request->set_param( 'per_page', 2 );
|
$request->set_param( 'per_page', 2 );
|
||||||
$response = $this->server->dispatch( $request );
|
$response = $this->server->dispatch( $request );
|
||||||
|
@ -715,6 +721,88 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$this->check_add_edit_user_response( $response );
|
$this->check_add_edit_user_response( $response );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_create_item_invalid_username() {
|
||||||
|
$this->allow_user_to_manage_multisite();
|
||||||
|
wp_set_current_user( self::$user );
|
||||||
|
|
||||||
|
$params = array(
|
||||||
|
'username' => '¯\_(ツ)_/¯',
|
||||||
|
'password' => 'testpassword',
|
||||||
|
'email' => 'test@example.com',
|
||||||
|
'name' => 'Test User',
|
||||||
|
'nickname' => 'testuser',
|
||||||
|
'slug' => 'test-user',
|
||||||
|
'roles' => array( 'editor' ),
|
||||||
|
'description' => 'New API User',
|
||||||
|
'url' => 'http://example.com',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Username rules are different (more strict) for multisite; see `wpmu_validate_user_signup`
|
||||||
|
if ( is_multisite() ) {
|
||||||
|
$params['username'] = 'no-dashes-allowed';
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'POST', '/wp/v2/users' );
|
||||||
|
$request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
|
||||||
|
$request->set_body_params( $params );
|
||||||
|
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
|
||||||
|
|
||||||
|
$data = $response->get_data();
|
||||||
|
if ( is_multisite() ) {
|
||||||
|
$this->assertInternalType( 'array', $data['additional_errors'] );
|
||||||
|
$this->assertCount( 1, $data['additional_errors'] );
|
||||||
|
$error = $data['additional_errors'][0];
|
||||||
|
$this->assertEquals( 'user_name', $error['code'] );
|
||||||
|
$this->assertEquals( 'Usernames can only contain lowercase letters (a-z) and numbers.', $error['message'] );
|
||||||
|
} else {
|
||||||
|
$this->assertInternalType( 'array', $data['data']['params'] );
|
||||||
|
$errors = $data['data']['params'];
|
||||||
|
$this->assertInternalType( 'string', $errors['username'] );
|
||||||
|
$this->assertEquals( 'Username contains invalid characters.', $errors['username'] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_illegal_user_logins() {
|
||||||
|
return array( 'nope' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_create_item_illegal_username() {
|
||||||
|
$this->allow_user_to_manage_multisite();
|
||||||
|
wp_set_current_user( self::$user );
|
||||||
|
|
||||||
|
add_filter( 'illegal_user_logins', array( $this, 'get_illegal_user_logins' ) );
|
||||||
|
|
||||||
|
$params = array(
|
||||||
|
'username' => 'nope',
|
||||||
|
'password' => 'testpassword',
|
||||||
|
'email' => 'test@example.com',
|
||||||
|
'name' => 'Test User',
|
||||||
|
'nickname' => 'testuser',
|
||||||
|
'slug' => 'test-user',
|
||||||
|
'roles' => array( 'editor' ),
|
||||||
|
'description' => 'New API User',
|
||||||
|
'url' => 'http://example.com',
|
||||||
|
);
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'POST', '/wp/v2/users' );
|
||||||
|
$request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
|
||||||
|
$request->set_body_params( $params );
|
||||||
|
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
|
||||||
|
remove_filter( 'illegal_user_logins', array( $this, 'get_illegal_user_logins' ) );
|
||||||
|
|
||||||
|
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
|
||||||
|
|
||||||
|
$data = $response->get_data();
|
||||||
|
$this->assertInternalType( 'array', $data['data']['params'] );
|
||||||
|
$errors = $data['data']['params'];
|
||||||
|
$this->assertInternalType( 'string', $errors['username'] );
|
||||||
|
$this->assertEquals( 'Sorry, that username is not allowed.', $errors['username'] );
|
||||||
|
}
|
||||||
|
|
||||||
public function test_create_new_network_user_on_site_does_not_add_user_to_sub_site() {
|
public function test_create_new_network_user_on_site_does_not_add_user_to_sub_site() {
|
||||||
if ( ! is_multisite() ) {
|
if ( ! is_multisite() ) {
|
||||||
$this->markTestSkipped( 'Test requires multisite.' );
|
$this->markTestSkipped( 'Test requires multisite.' );
|
||||||
|
@ -810,7 +898,20 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
|
|
||||||
wpmu_delete_user( $user_id );
|
wpmu_delete_user( $user_id );
|
||||||
|
|
||||||
$this->assertErrorResponse( 'user_name', $switched_response );
|
$this->assertErrorResponse( 'rest_invalid_param', $switched_response, 400 );
|
||||||
|
$data = $switched_response->get_data();
|
||||||
|
$this->assertInternalType( 'array', $data['additional_errors'] );
|
||||||
|
$this->assertCount( 2, $data['additional_errors'] );
|
||||||
|
$errors = $data['additional_errors'];
|
||||||
|
foreach ( $errors as $error ) {
|
||||||
|
// Check the code matches one we know.
|
||||||
|
$this->assertContains( $error['code'], array( 'user_name', 'user_email' ) );
|
||||||
|
if ( 'user_name' === $error['code'] ) {
|
||||||
|
$this->assertEquals( 'Sorry, that username already exists!', $error['message'] );
|
||||||
|
} else {
|
||||||
|
$this->assertEquals( 'Sorry, that email address is already used!', $error['message'] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_update_existing_network_user_on_sub_site_adds_user_to_site() {
|
public function test_update_existing_network_user_on_sub_site_adds_user_to_site() {
|
||||||
|
@ -1305,6 +1406,213 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
|
||||||
$this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
|
$this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_update_item_invalid_password() {
|
||||||
|
$this->allow_user_to_manage_multisite();
|
||||||
|
wp_set_current_user( self::$user );
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', self::$editor ) );
|
||||||
|
|
||||||
|
$request->set_param( 'password', 'no\\backslashes\\allowed' );
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
|
||||||
|
|
||||||
|
$request->set_param( 'password', '' );
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verify_user_roundtrip( $input = array(), $expected_output = array() ) {
|
||||||
|
if ( isset( $input['id'] ) ) {
|
||||||
|
// Existing user; don't try to create one
|
||||||
|
$user_id = $input['id'];
|
||||||
|
} else {
|
||||||
|
// Create a new user
|
||||||
|
$request = new WP_REST_Request( 'POST', '/wp/v2/users' );
|
||||||
|
foreach ( $input as $name => $value ) {
|
||||||
|
$request->set_param( $name, $value );
|
||||||
|
}
|
||||||
|
$request->set_param( 'email', 'cbg@androidsdungeon.com' );
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertEquals( 201, $response->get_status() );
|
||||||
|
$actual_output = $response->get_data();
|
||||||
|
|
||||||
|
// Compare expected API output to actual API output
|
||||||
|
$this->assertEquals( $expected_output['username'] , $actual_output['username'] );
|
||||||
|
$this->assertEquals( $expected_output['name'] , $actual_output['name'] );
|
||||||
|
$this->assertEquals( $expected_output['first_name'] , $actual_output['first_name'] );
|
||||||
|
$this->assertEquals( $expected_output['last_name'] , $actual_output['last_name'] );
|
||||||
|
$this->assertEquals( $expected_output['url'] , $actual_output['url'] );
|
||||||
|
$this->assertEquals( $expected_output['description'], $actual_output['description'] );
|
||||||
|
$this->assertEquals( $expected_output['nickname'] , $actual_output['nickname'] );
|
||||||
|
|
||||||
|
// Compare expected API output to WP internal values
|
||||||
|
$user = get_userdata( $actual_output['id'] );
|
||||||
|
$this->assertEquals( $expected_output['username'] , $user->user_login );
|
||||||
|
$this->assertEquals( $expected_output['name'] , $user->display_name );
|
||||||
|
$this->assertEquals( $expected_output['first_name'] , $user->first_name );
|
||||||
|
$this->assertEquals( $expected_output['last_name'] , $user->last_name );
|
||||||
|
$this->assertEquals( $expected_output['url'] , $user->user_url );
|
||||||
|
$this->assertEquals( $expected_output['description'], $user->description );
|
||||||
|
$this->assertEquals( $expected_output['nickname'] , $user->nickname );
|
||||||
|
$this->assertTrue( wp_check_password( addslashes( $expected_output['password'] ), $user->user_pass ) );
|
||||||
|
|
||||||
|
$user_id = $actual_output['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the user
|
||||||
|
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
|
||||||
|
foreach ( $input as $name => $value ) {
|
||||||
|
if ( 'username' !== $name ) {
|
||||||
|
$request->set_param( $name, $value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertEquals( 200, $response->get_status() );
|
||||||
|
$actual_output = $response->get_data();
|
||||||
|
|
||||||
|
// Compare expected API output to actual API output
|
||||||
|
if ( isset( $expected_output['username'] ) ) {
|
||||||
|
$this->assertEquals( $expected_output['username'], $actual_output['username'] );
|
||||||
|
}
|
||||||
|
$this->assertEquals( $expected_output['name'] , $actual_output['name'] );
|
||||||
|
$this->assertEquals( $expected_output['first_name'] , $actual_output['first_name'] );
|
||||||
|
$this->assertEquals( $expected_output['last_name'] , $actual_output['last_name'] );
|
||||||
|
$this->assertEquals( $expected_output['url'] , $actual_output['url'] );
|
||||||
|
$this->assertEquals( $expected_output['description'], $actual_output['description'] );
|
||||||
|
$this->assertEquals( $expected_output['nickname'] , $actual_output['nickname'] );
|
||||||
|
|
||||||
|
// Compare expected API output to WP internal values
|
||||||
|
$user = get_userdata( $actual_output['id'] );
|
||||||
|
if ( isset( $expected_output['username'] ) ) {
|
||||||
|
$this->assertEquals( $expected_output['username'], $user->user_login );
|
||||||
|
}
|
||||||
|
$this->assertEquals( $expected_output['name'] , $user->display_name );
|
||||||
|
$this->assertEquals( $expected_output['first_name'] , $user->first_name );
|
||||||
|
$this->assertEquals( $expected_output['last_name'] , $user->last_name );
|
||||||
|
$this->assertEquals( $expected_output['url'] , $user->user_url );
|
||||||
|
$this->assertEquals( $expected_output['description'], $user->description );
|
||||||
|
$this->assertEquals( $expected_output['nickname'] , $user->nickname );
|
||||||
|
$this->assertTrue( wp_check_password( addslashes( $expected_output['password'] ), $user->user_pass ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_roundtrip_as_editor() {
|
||||||
|
wp_set_current_user( self::$editor );
|
||||||
|
$this->assertEquals( ! is_multisite(), current_user_can( 'unfiltered_html' ) );
|
||||||
|
$this->verify_user_roundtrip( array(
|
||||||
|
'id' => self::$editor,
|
||||||
|
'name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'first_name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'last_name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'url' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'description' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'nickname' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'password' => 'o/ ¯_(ツ)_/¯ \'"',
|
||||||
|
), array(
|
||||||
|
'name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'first_name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'last_name' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'url' => 'http://o/%20¯_(ツ)_/¯',
|
||||||
|
'description' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'nickname' => '\o/ ¯\_(ツ)_/¯',
|
||||||
|
'password' => 'o/ ¯_(ツ)_/¯ \'"',
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_roundtrip_as_editor_html() {
|
||||||
|
wp_set_current_user( self::$editor );
|
||||||
|
if ( is_multisite() ) {
|
||||||
|
$this->assertFalse( current_user_can( 'unfiltered_html' ) );
|
||||||
|
$this->verify_user_roundtrip( array(
|
||||||
|
'id' => self::$editor,
|
||||||
|
'name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'first_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'last_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'url' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'nickname' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
), array(
|
||||||
|
'name' => 'div strong',
|
||||||
|
'first_name' => 'div strong',
|
||||||
|
'last_name' => 'div strong',
|
||||||
|
'url' => 'http://divdiv/div%20strongstrong/strong%20scriptoh%20noes/script',
|
||||||
|
'description' => 'div <strong>strong</strong> oh noes',
|
||||||
|
'nickname' => 'div strong',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
) );
|
||||||
|
} else {
|
||||||
|
$this->assertTrue( current_user_can( 'unfiltered_html' ) );
|
||||||
|
$this->verify_user_roundtrip( array(
|
||||||
|
'id' => self::$editor,
|
||||||
|
'name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'first_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'last_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'url' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'nickname' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
), array(
|
||||||
|
'name' => 'div strong',
|
||||||
|
'first_name' => 'div strong',
|
||||||
|
'last_name' => 'div strong',
|
||||||
|
'url' => 'http://divdiv/div%20strongstrong/strong%20scriptoh%20noes/script',
|
||||||
|
'description' => 'div <strong>strong</strong> oh noes',
|
||||||
|
'nickname' => 'div strong',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_roundtrip_as_superadmin() {
|
||||||
|
wp_set_current_user( self::$superadmin );
|
||||||
|
$this->assertTrue( current_user_can( 'unfiltered_html' ) );
|
||||||
|
$valid_username = is_multisite() ? 'noinvalidcharshere' : 'no-invalid-chars-here';
|
||||||
|
$this->verify_user_roundtrip( array(
|
||||||
|
'username' => $valid_username,
|
||||||
|
'name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'first_name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'last_name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'url' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'description' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'nickname' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'password' => '& & &invalid; < < &lt;',
|
||||||
|
), array(
|
||||||
|
'username' => $valid_username,
|
||||||
|
'name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'first_name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'last_name' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'url' => 'http://&%20&%20&invalid;%20%20<%20&lt;',
|
||||||
|
'description' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'nickname' => '\\\&\\\ & &invalid; < < &lt;',
|
||||||
|
'password' => '& & &invalid; < < &lt;',
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_roundtrip_as_superadmin_html() {
|
||||||
|
wp_set_current_user( self::$superadmin );
|
||||||
|
$this->assertTrue( current_user_can( 'unfiltered_html' ) );
|
||||||
|
$valid_username = is_multisite() ? 'noinvalidcharshere' : 'no-invalid-chars-here';
|
||||||
|
$this->verify_user_roundtrip( array(
|
||||||
|
'username' => $valid_username,
|
||||||
|
'name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'first_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'last_name' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'url' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'nickname' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
), array(
|
||||||
|
'username' => $valid_username,
|
||||||
|
'name' => 'div strong',
|
||||||
|
'first_name' => 'div strong',
|
||||||
|
'last_name' => 'div strong',
|
||||||
|
'url' => 'http://divdiv/div%20strongstrong/strong%20scriptoh%20noes/script',
|
||||||
|
'description' => 'div <strong>strong</strong> oh noes',
|
||||||
|
'nickname' => 'div strong',
|
||||||
|
'password' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
public function test_delete_item() {
|
public function test_delete_item() {
|
||||||
$user_id = $this->factory->user->create( array( 'display_name' => 'Deleted User' ) );
|
$user_id = $this->factory->user->create( array( 'display_name' => 'Deleted User' ) );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue